Skip to content

Commit

Permalink
jinja2 autoescape codemod should allow for setting autoescape to `sel…
Browse files Browse the repository at this point in the history
…ect_autoescape` callable (#285)

* jinja autoescape codemod should be merge after review and allow for using select_autoescape()

* update aiohttp jinja2 autoescape allowed values
  • Loading branch information
clavedeluna authored Feb 21, 2024
1 parent f5c8d5e commit a054ed8
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/codemodder/scripts/generate_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class DocMetadata:
),
"enable-jinja2-autoescape": DocMetadata(
importance="High",
guidance_explained="This codemod protects your applications against XSS attacks. We believe using the default behavior is unsafe.",
guidance_explained="This codemod protects your applications against XSS attacks. However, it's possible you would like to set the `autoescape` parameter to a custom callable.",
),
"fix-mutable-params": DocMetadata(
importance="Medium",
Expand Down
6 changes: 3 additions & 3 deletions src/core_codemods/enable_jinja2_autoescape.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class EnableJinja2Autoescape(SimpleCodemod):
metadata = Metadata(
name="enable-jinja2-autoescape",
summary="Enable Jinja2 Autoescape",
review_guidance=ReviewGuidance.MERGE_WITHOUT_REVIEW,
review_guidance=ReviewGuidance.MERGE_AFTER_REVIEW,
references=[
Reference(url="https://owasp.org/www-community/attacks/xss/"),
Reference(
Expand All @@ -28,12 +28,12 @@ class EnableJinja2Autoescape(SimpleCodemod):
- patterns:
- pattern: jinja2.Environment(...)
- pattern-not: jinja2.Environment(..., autoescape=True, ...)
- pattern-not: jinja2.Environment(..., autoescape=jinja2.select_autoescape(...), ...)
- pattern-inside: |
import jinja2
...
- patterns:
- pattern: aiohttp_jinja2.setup(...)
- pattern-not: aiohttp_jinja2.setup(..., autoescape=True, ...)
- pattern: aiohttp_jinja2.setup(..., autoescape=False, ...)
- pattern-inside: |
import aiohttp_jinja2
...
Expand Down
42 changes: 35 additions & 7 deletions tests/codemods/test_enable_jinja2_autoescape.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pytest
from core_codemods.enable_jinja2_autoescape import EnableJinja2Autoescape
from tests.codemods.base_codemod_test import BaseSemgrepCodemodTest

Expand Down Expand Up @@ -99,10 +100,26 @@ def test_autoescape_enabled(self, tmpdir):
expexted_output = input_code
self.run_and_assert(tmpdir, input_code, expexted_output)

@pytest.mark.parametrize(
"code",
[
"""
import jinja2
env = jinja2.Environment(autoescape=jinja2.select_autoescape())
""",
"""
import jinja2
env = jinja2.Environment(autoescape=jinja2.select_autoescape(disabled_extensions=('txt',), default_for_string=True, default=True))
""",
],
)
def test_autoescape_callable(self, tmpdir, code):
self.run_and_assert(tmpdir, code, code)

def test_aiohttp_import_setup(self, tmpdir):
input_code = """
import aiohttp_jinja2
aiohttp_jinja2.setup(app)
aiohttp_jinja2.setup(app, autoescape=False)
"""
expected_output = """
import aiohttp_jinja2
Expand All @@ -113,7 +130,7 @@ def test_aiohttp_import_setup(self, tmpdir):
def test_aiohttp_import_from_setup(self, tmpdir):
input_code = """
from aiohttp_jinja2 import setup
setup(app)
setup(app, autoescape=False)
"""
expected_output = """
from aiohttp_jinja2 import setup
Expand All @@ -124,7 +141,7 @@ def test_aiohttp_import_from_setup(self, tmpdir):
def test_aiohttp_import_alias(self, tmpdir):
input_code = """
from aiohttp_jinja2 import setup as setup_jinja2
setup_jinja2(app)
setup_jinja2(app, autoescape=False)
"""
expected_output = """
from aiohttp_jinja2 import setup as setup_jinja2
Expand All @@ -141,13 +158,24 @@ def test_aiohttp_import_alias_no_change(self, tmpdir):
"""
self.run_and_assert(tmpdir, input_code, expected_output)

def test_aiohttp_set_false(self, tmpdir):
def test_aiohttp_autoescape_default(self, tmpdir):
input_code = """
import aiohttp_jinja2
aiohttp_jinja2.setup(app, autoescape=False)
aiohttp_jinja2.setup(app)
"""
expected_output = """
self.run_and_assert(tmpdir, input_code, input_code)

def test_aiohttp_autoescape_True(self, tmpdir):
input_code = """
import aiohttp_jinja2
aiohttp_jinja2.setup(app, autoescape=True)
"""
self.run_and_assert(tmpdir, input_code, expected_output)
self.run_and_assert(tmpdir, input_code, input_code)

def test_aiohttp_autoescape_callable(self, tmpdir):
input_code = """
import aiohttp_jinja2
import jinja
aiohttp_jinja2.setup(app, autoescape=jinja2.select_autoescape())
"""
self.run_and_assert(tmpdir, input_code, input_code)

0 comments on commit a054ed8

Please sign in to comment.