-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathsemgrep.py
More file actions
74 lines (63 loc) · 2.2 KB
/
semgrep.py
File metadata and controls
74 lines (63 loc) · 2.2 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
72
73
74
import subprocess
import itertools
import yaml
from tempfile import NamedTemporaryFile
from typing import List
from pathlib import Path
from codemodder import global_state
from codemodder.sarifs import results_by_path_and_rule_id
from codemodder.logging import logger
YAML_FILES_DIR = Path("codemodder") / "codemods" / "semgrep"
def run_on_directory(yaml_files: List[Path], directory: Path):
"""
Runs Semgrep and outputs a dict with the results organized by rule_id.
"""
with NamedTemporaryFile(prefix="semgrep", suffix=".sarif") as temp_sarif_file:
command = [
"semgrep",
"scan",
"--legacy",
"--no-error",
"--dataflow-traces",
"--sarif",
"-o",
temp_sarif_file.name,
]
command.extend(
itertools.chain.from_iterable(
map(lambda f: ["--config", str(f)], yaml_files)
)
)
command.append(str(directory))
joined_command = " ".join(command)
logger.debug("Executing semgrep with: `%s`", joined_command)
subprocess.run(joined_command, shell=True, check=True)
results = results_by_path_and_rule_id(temp_sarif_file.name)
return results
def run(codemods: dict) -> dict:
semgrep_codemods = only_semgrep(codemods)
if semgrep_codemods:
return run_on_directory(
find_all_yaml_files(semgrep_codemods), Path(global_state.DIRECTORY)
)
return {}
def find_all_yaml_files(codemods) -> list[Path]:
"""
Finds all yaml files associated with the given codemods.
"""
return [
YAML_FILES_DIR / yaml_file
for codemod in codemods.values()
for yaml_file in codemod.YAML_FILES
]
def only_semgrep(codemods) -> dict:
"""
Returns only semgrep codemods.
"""
return {name: codemod for name, codemod in codemods.items() if codemod.IS_SEMGREP}
def rule_ids_from_yaml_files(yaml_files):
all_yaml = []
for file in yaml_files:
with open(YAML_FILES_DIR / file, encoding="utf-8") as yaml_file:
all_yaml.append(yaml.load(yaml_file, Loader=yaml.Loader))
return [r["id"] for yaml_file in all_yaml for r in yaml_file["rules"]]