-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
first semgrep sarif codemod for jinja autoescape
- Loading branch information
1 parent
eb6ef50
commit e585cf7
Showing
9 changed files
with
180 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from functools import cache | ||
from pathlib import Path | ||
|
||
from codemodder.codemods.base_codemod import Metadata, Reference, ToolMetadata, ToolRule | ||
from codemodder.codemods.base_detector import BaseDetector | ||
from codemodder.codemods.base_transformer import BaseTransformerPipeline | ||
from codemodder.context import CodemodExecutionContext | ||
from codemodder.result import ResultSet | ||
from codemodder.semgrep import SemgrepResultSet | ||
from core_codemods.api.core_codemod import CoreCodemod, SASTCodemod | ||
|
||
|
||
class SemgrepCodemod(SASTCodemod): | ||
@property | ||
def origin(self): | ||
return "semgrep" | ||
|
||
@classmethod | ||
def from_core_codemod( | ||
cls, | ||
name: str, | ||
other: CoreCodemod, | ||
rule_id: str, | ||
rule_name: str, | ||
rule_url: str, | ||
transformer: BaseTransformerPipeline | None = None, | ||
): | ||
|
||
return SemgrepCodemod( | ||
metadata=Metadata( | ||
name=name, | ||
summary=other.summary, | ||
review_guidance=other._metadata.review_guidance, | ||
references=( | ||
other.references + [Reference(url=rule_url, description=rule_name)] | ||
), | ||
description=other.description, | ||
tool=ToolMetadata( | ||
name="Semgrep", | ||
rules=[ | ||
ToolRule( | ||
id=rule_id, | ||
name=rule_name, | ||
url=rule_url, | ||
) | ||
], | ||
), | ||
), | ||
transformer=transformer if transformer else other.transformer, | ||
detector=SemgrepSarifFileDetector(), | ||
requested_rules=[rule_id], | ||
) | ||
|
||
|
||
class SemgrepSarifFileDetector(BaseDetector): | ||
def apply( | ||
self, | ||
codemod_id: str, | ||
context: CodemodExecutionContext, | ||
files_to_analyze: list[Path], | ||
) -> ResultSet: | ||
del codemod_id | ||
del files_to_analyze | ||
return process_semgrep_findings( | ||
tuple(context.tool_result_files_map.get("semgrep", ())) | ||
) # Convert list to tuple for cache hashability | ||
|
||
|
||
@cache | ||
def process_semgrep_findings(semgrep_sarif_files: tuple[str]) -> ResultSet: | ||
results = SemgrepResultSet() | ||
for file in semgrep_sarif_files or (): | ||
results |= SemgrepResultSet.from_sarif(file) | ||
return results |
10 changes: 10 additions & 0 deletions
10
src/core_codemods/semgrep/semgrep_enable_jinja2_autoescape.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from core_codemods.enable_jinja2_autoescape import EnableJinja2Autoescape | ||
from core_codemods.semgrep.api import SemgrepCodemod | ||
|
||
SemgrepEnableJinja2Autoescape = SemgrepCodemod.from_core_codemod( | ||
name="enable-jinja2-autoescape-semgrep", | ||
other=EnableJinja2Autoescape, | ||
rule_id="python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2", | ||
rule_name="direct-use-of-jinja2", | ||
rule_url="https://sg.run/RoKe", | ||
) |
67 changes: 67 additions & 0 deletions
67
tests/codemods/semgrep/test_semgrep_enable_jinja2_autoescape.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import json | ||
|
||
from codemodder.codemods.test import BaseSASTCodemodTest | ||
from core_codemods.semgrep.semgrep_enable_jinja2_autoescape import ( | ||
SemgrepEnableJinja2Autoescape, | ||
) | ||
|
||
|
||
class TestEnableJinja2Autoescape(BaseSASTCodemodTest): | ||
codemod = SemgrepEnableJinja2Autoescape | ||
tool = "semgrep" | ||
|
||
def test_name(self): | ||
assert self.codemod.name == "enable-jinja2-autoescape-semgrep" | ||
|
||
def test_import(self, tmpdir): | ||
input_code = """ | ||
import jinja2 | ||
env = jinja2.Environment() | ||
var = "hello" | ||
""" | ||
expexted_output = """ | ||
import jinja2 | ||
env = jinja2.Environment(autoescape=True) | ||
var = "hello" | ||
""" | ||
results = { | ||
"runs": [ | ||
{ | ||
"results": [ | ||
{ | ||
"fingerprints": {"matchBasedId/v1": "123"}, | ||
"locations": [ | ||
{ | ||
"physicalLocation": { | ||
"artifactLocation": { | ||
"uri": "code.py", | ||
"uriBaseId": "%SRCROOT%", | ||
}, | ||
"region": { | ||
"endColumn": 27, | ||
"endLine": 3, | ||
"snippet": { | ||
"text": "env = jinja2.Environment()" | ||
}, | ||
"startColumn": 7, | ||
"startLine": 3, | ||
}, | ||
} | ||
} | ||
], | ||
"message": { | ||
"text": "Detected direct use of jinja2. If not done properly, this may bypass HTML escaping which opens up the application to cross-site scripting (XSS) vulnerabilities. Prefer using the Flask method 'render_template()' and templates with a '.html' extension in order to prevent XSS." | ||
}, | ||
"properties": {}, | ||
"ruleId": "python.flask.security.xss.audit.direct-use-of-jinja2.direct-use-of-jinja2", | ||
} | ||
] | ||
} | ||
] | ||
} | ||
self.run_and_assert( | ||
tmpdir, | ||
input_code, | ||
expexted_output, | ||
results=json.dumps(results), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters