-
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.
* split jwt decode codemod into transformer * add jwt sonar codemod * refactor to result check * document code path * fix integration test * add integration tests * update based on review
- Loading branch information
1 parent
72a2b2a
commit badb2da
Showing
10 changed files
with
212 additions
and
40 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from core_codemods.sonar.sonar_jwt_decode_verify import ( | ||
SonarJwtDecodeVerify, | ||
JwtDecodeVerifySonarTransformer, | ||
) | ||
from codemodder.codemods.test import ( | ||
BaseIntegrationTest, | ||
original_and_expected_from_code_path, | ||
) | ||
|
||
|
||
class TestJwtDecodeVerify(BaseIntegrationTest): | ||
codemod = SonarJwtDecodeVerify | ||
code_path = "tests/samples/jwt_decode_verify.py" | ||
original_code, expected_new_code = original_and_expected_from_code_path( | ||
code_path, | ||
[ | ||
( | ||
10, | ||
"""decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], verify=True)\n""", | ||
), | ||
( | ||
11, | ||
"""decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], options={"verify_signature": True})\n""", | ||
), | ||
], | ||
) | ||
sonar_issues_json = "tests/samples/sonar_issues.json" | ||
|
||
expected_diff = '--- \n+++ \n@@ -8,7 +8,7 @@\n \n encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm="HS256")\n \n-decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], verify=False)\n-decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], options={"verify_signature": False})\n+decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], verify=True)\n+decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], options={"verify_signature": True})\n \n var = "something"\n' | ||
expected_line_change = "11" | ||
num_changes = 2 | ||
change_description = JwtDecodeVerifySonarTransformer.change_description |
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
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,42 @@ | ||
import libcst as cst | ||
from codemodder.codemods.base_codemod import Reference | ||
from codemodder.result import same_line, fuzzy_column_match | ||
from codemodder.codemods.sonar import SonarCodemod | ||
from codemodder.codemods.libcst_transformer import ( | ||
LibcstTransformerPipeline, | ||
) | ||
from core_codemods.jwt_decode_verify import JwtDecodeVerify, JwtDecodeVerifyTransformer | ||
|
||
|
||
class JwtDecodeVerifySonarTransformer(JwtDecodeVerifyTransformer): | ||
def filter_by_result(self, node) -> bool: | ||
""" | ||
Special case result-matching for this rule because the sonar | ||
results returned have a start/end column for the verify keyword | ||
within the `decode` call, not for the entire call like semgrep returns. | ||
""" | ||
match node: | ||
case cst.Call(): | ||
pos_to_match = self.node_position(node) | ||
return any( | ||
self.match_location(pos_to_match, result) | ||
for result in self.results or [] | ||
) | ||
return False | ||
|
||
def match_location(self, pos, result): | ||
return any( | ||
same_line(pos, location) and fuzzy_column_match(pos, location) | ||
for location in result.locations | ||
) | ||
|
||
|
||
SonarJwtDecodeVerify = SonarCodemod.from_core_codemod( | ||
name="jwt-decode-verify-S5659", | ||
other=JwtDecodeVerify, | ||
rules=["python:S5659"], | ||
new_references=[ | ||
Reference(url="https://rules.sonarsource.com/python/RSPEC-5659/"), | ||
], | ||
transformer=LibcstTransformerPipeline(JwtDecodeVerifySonarTransformer), | ||
) |
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,68 @@ | ||
import json | ||
from core_codemods.sonar.sonar_jwt_decode_verify import SonarJwtDecodeVerify | ||
from codemodder.codemods.test import BaseSASTCodemodTest | ||
|
||
|
||
class TestSonarJwtDecodeVerify(BaseSASTCodemodTest): | ||
codemod = SonarJwtDecodeVerify | ||
tool = "sonar" | ||
|
||
def test_name(self): | ||
assert self.codemod.name == "jwt-decode-verify-S5659" | ||
|
||
def test_simple(self, tmpdir): | ||
input_code = """ | ||
import jwt | ||
SECRET_KEY = "mysecretkey" | ||
payload = { | ||
"user_id": 123, | ||
"username": "john", | ||
} | ||
encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm="HS256") | ||
decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], verify=False) | ||
decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], options={"verify_signature": False}) | ||
""" | ||
expected = """ | ||
import jwt | ||
SECRET_KEY = "mysecretkey" | ||
payload = { | ||
"user_id": 123, | ||
"username": "john", | ||
} | ||
encoded_jwt = jwt.encode(payload, SECRET_KEY, algorithm="HS256") | ||
decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], verify=True) | ||
decoded_payload = jwt.decode(encoded_jwt, SECRET_KEY, algorithms=["HS256"], options={"verify_signature": True}) | ||
""" | ||
issues = { | ||
"issues": [ | ||
{ | ||
"rule": "python:S5659", | ||
"status": "OPEN", | ||
"component": f"{tmpdir / 'code.py'}", | ||
"textRange": { | ||
"startLine": 11, | ||
"endLine": 11, | ||
"startOffset": 76, | ||
"endOffset": 88, | ||
}, | ||
}, | ||
{ | ||
"rule": "python:S5659", | ||
"status": "OPEN", | ||
"component": f"{tmpdir / 'code.py'}", | ||
"textRange": { | ||
"startLine": 12, | ||
"endLine": 12, | ||
"startOffset": 84, | ||
"endOffset": 111, | ||
}, | ||
}, | ||
] | ||
} | ||
self.run_and_assert( | ||
tmpdir, input_code, expected, results=json.dumps(issues), num_changes=2 | ||
) |