Skip to content

Commit 419c64d

Browse files
committed
feat: add detection reasons to findings output
1 parent 3e259a9 commit 419c64d

5 files changed

Lines changed: 17 additions & 10 deletions

File tree

detectors/find_secrets.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def detect_ast_secrets(code):
3535
vulnerabilities = apply_rules(var_name, val)
3636

3737
if vulnerabilities:
38-
for pattern_name, severity, value in vulnerabilities:
39-
findings.append((line_number, pattern_name, severity, value))
38+
for pattern_name, severity, value, reason in vulnerabilities:
39+
findings.append((line_number, pattern_name, severity, value, reason))
4040

4141
return findings

detectors/rule_engine.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ def apply_rules(var_name, val):
2222
# Match structured secret values, such as AWS access keys
2323
if "value_pattern" in data:
2424
if data["value_pattern"].fullmatch(val):
25-
findings.append((rule, data["severity"], val))
25+
findings.append((rule, data["severity"], val, data["reason"]))
2626

2727
# Match suspicious variable names and enforce minimum value length
2828
if "var_patterns" in data:
2929
for pattern in data["var_patterns"]:
3030
match = pattern.search(var_name)
3131
if match and len(val) >= data["min_length"]:
32-
findings.append((rule, data["severity"], val))
32+
findings.append((rule, data["severity"], val, data["reason"]))
3333

3434
return findings or None

detectors/rules.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"AWS Access Key": {
1010
"value_pattern": re.compile(r"(AKIA[0-9A-Z]{16})"),
1111
"severity": "HIGH",
12+
"reason": "value matched AKIA-prefixed AWS access key pattern",
1213
},
1314
"Password": {
1415
"var_patterns": [
@@ -18,6 +19,7 @@
1819
],
1920
"min_length": 4,
2021
"severity": "HIGH",
22+
"reason": "variable name matched password/pwd/passwd pattern and value met minimum length",
2123
},
2224
"API Key": {
2325
"var_patterns": [
@@ -26,17 +28,20 @@
2628
],
2729
"min_length": 4,
2830
"severity": "HIGH",
31+
"reason": "variable name matched api_key/apikey pattern and value met minimum length",
2932
},
3033
"Token": {
3134
"var_patterns": [re.compile(r"token", re.IGNORECASE)],
3235
"min_length": 4,
3336
"severity": "MEDIUM",
37+
"reason": "variable name matched token pattern and value met minimum length",
3438
},
3539
"Secret": {
3640
"var_patterns": [
3741
re.compile(r"secret", re.IGNORECASE),
3842
],
3943
"min_length": 4,
4044
"severity": "MEDIUM",
45+
"reason": "variable name matched secret pattern and value met minimum length",
4146
},
4247
}

output.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ def filter_results(results, chosen_severity):
1818
Filtered findings matching the selected severity.
1919
"""
2020
filtered_findings = []
21-
for line_number, file, rule_name, severity, value in results:
21+
for line_number, file, rule_name, severity, value, reason in results:
2222
if severity == chosen_severity or chosen_severity is None:
23-
filtered_findings.append((line_number, file, rule_name, severity, value))
23+
filtered_findings.append((line_number, file, rule_name, severity, value, reason))
2424
return filtered_findings
2525

2626

@@ -36,13 +36,14 @@ def output_json(filtered_findings):
3636
None
3737
"""
3838
json_results = []
39-
for line_number, file, rule_name, severity, value in filtered_findings:
39+
for line_number, file, rule_name, severity, value, reason in filtered_findings:
4040
finding = {
4141
"line": line_number,
4242
"file": str(file),
4343
"rule": rule_name,
4444
"severity": severity,
4545
"value": value,
46+
"reason": reason,
4647
}
4748
json_results.append(finding)
4849
print(json.dumps(json_results, indent=2))
@@ -76,7 +77,8 @@ def output(filtered_findings, use_json, files):
7677
else:
7778
print("\n--- Findings ---\n")
7879

79-
for line_number, file, rule_name, severity, value in filtered_findings:
80+
for line_number, file, rule_name, severity, value, reason in filtered_findings:
8081
print(f"[{severity}] {file}:{line_number} {rule_name}{value}")
82+
print(f" Reason: {reason}\n")
8183

8284
print(f"\nTotal findings: {len(filtered_findings)}")

scanner.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ def scan(files):
7272
content = f.read()
7373

7474
ast_results = detect_ast_secrets(content)
75-
for line_number, rule_name, severity, value in ast_results:
76-
findings.append((line_number, file, rule_name, severity, value))
75+
for line_number, rule_name, severity, value, reason in ast_results:
76+
findings.append((line_number, file, rule_name, severity, value, reason))
7777

7878
return findings
7979

0 commit comments

Comments
 (0)