-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathsemgrep.py
More file actions
71 lines (55 loc) · 2.15 KB
/
semgrep.py
File metadata and controls
71 lines (55 loc) · 2.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import io
import os
import tempfile
from functools import cache
from pathlib import Path
import yaml
from codemodder.codemods.base_detector import BaseDetector
from codemodder.context import CodemodExecutionContext
from codemodder.result import ResultSet
from codemodder.semgrep import SemgrepResultSet
from codemodder.semgrep import run as semgrep_run
def _populate_yaml(rule: str, codemod_id: str) -> str:
rule_yaml = yaml.safe_load(io.StringIO(rule))
config = {"rules": rule_yaml} if "rules" not in rule_yaml else rule_yaml
config["rules"][0].setdefault("id", codemod_id)
config["rules"][0].setdefault("message", "Semgrep found a match")
config["rules"][0].setdefault("severity", "WARNING")
config["rules"][0].setdefault("languages", ["python"])
return yaml.safe_dump(config)
def _create_temp_yaml_file(rule: str, codemod_id: str):
fd, path = tempfile.mkstemp()
with os.fdopen(fd, "w") as ff:
ff.write(_populate_yaml(rule, codemod_id))
return [Path(path)]
class SemgrepRuleDetector(BaseDetector):
rule: str
def __init__(self, rule: str):
self.rule = rule
def get_yaml_files(self, codemod_id: str) -> list[Path]:
return _create_temp_yaml_file(self.rule, codemod_id)
def apply(
self,
codemod_id: str,
context: CodemodExecutionContext,
) -> ResultSet:
yaml_files = self.get_yaml_files(codemod_id)
with context.timer.measure("semgrep"):
files_to_analyze = context.semgrep_results_for_rule(codemod_id)
return semgrep_run(context, yaml_files, files_to_analyze)
class SemgrepSarifFileDetector(BaseDetector):
def apply(
self,
codemod_id: str,
context: CodemodExecutionContext,
) -> ResultSet:
del codemod_id
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