Skip to content

Commit 051a94b

Browse files
committed
feat: add --redact flag to include option to redact found secrets
1 parent a3cf509 commit 051a94b

3 files changed

Lines changed: 34 additions & 7 deletions

File tree

cli.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,17 @@
2525
help="Only show findings matching the selected severity",
2626
)
2727

28+
parser.add_argument(
29+
"--redact",
30+
action="store_true",
31+
help="Redact found secret values",
32+
)
33+
2834
# Parse command-line arguments
2935
args = parser.parse_args()
3036

3137
# Extract parsed CLI values for use by the application
3238
input_path = args.path
3339
use_json = args.json
40+
redact_secrets = args.redact
3441
chosen_severity = args.severity

main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
Errors related to invalid input paths are handled gracefully.
1313
"""
1414

15-
from cli import input_path, chosen_severity, use_json
15+
from cli import input_path, chosen_severity, use_json, redact_secrets
1616
from scanner import check_path, scan, list_python_files
1717
from output import filter_results, output
1818

@@ -32,7 +32,7 @@
3232
filtered_findings = filter_results(results, chosen_severity)
3333

3434
# Output results in the selected format
35-
output(filtered_findings, use_json, files)
35+
output(filtered_findings, use_json, redact_secrets, files)
3636

3737
except FileNotFoundError as e:
3838
# Display a user-friendly error message for invalid paths

output.py

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
import json
22

3+
def redact_value(value):
4+
"""
5+
Redact a detected secret while preserving limited identifying context.
6+
7+
Short values are fully redacted. Longer values keep a small prefix and
8+
suffix so users can identify which secret was found without exposing it.
9+
"""
10+
if not value or len(value) <= 4:
11+
return "[REDACTED]"
12+
13+
if len(value) <= 8:
14+
return f"{value[0]}{'*' * (len(value) - 2)}{value[-1]}"
15+
16+
return f"{value[:2]}{'*' * (len(value) - 4)}{value[-2:]}"
317

418
def filter_results(results, chosen_severity):
519
"""
@@ -24,7 +38,7 @@ def filter_results(results, chosen_severity):
2438
return filtered_findings
2539

2640

27-
def output_json(filtered_findings):
41+
def output_json(filtered_findings, redact_secrets):
2842
"""
2943
Output findings in machine-readable JSON format.
3044
@@ -37,21 +51,24 @@ def output_json(filtered_findings):
3751
"""
3852
json_results = []
3953
for filtered_finding in filtered_findings:
54+
value = filtered_finding.value
55+
if redact_secrets:
56+
value = redact_value(value)
4057
finding = {
4158
"line": filtered_finding.line_number,
4259
"var_name": filtered_finding.var_name,
4360
"file": str(filtered_finding.file_path),
4461
"rule_id": filtered_finding.rule_id,
4562
"rule": filtered_finding.rule_name,
4663
"severity": filtered_finding.severity,
47-
"value": filtered_finding.value,
64+
"value": value,
4865
"reason": filtered_finding.reason,
4966
}
5067
json_results.append(finding)
5168
print(json.dumps(json_results, indent=2))
5269

5370

54-
def output(filtered_findings, use_json, files):
71+
def output(filtered_findings, use_json, redact_secrets, files):
5572
"""
5673
Display scan results in either JSON or human-readable CLI format.
5774
@@ -69,7 +86,7 @@ def output(filtered_findings, use_json, files):
6986
None
7087
"""
7188
if use_json:
72-
output_json(filtered_findings)
89+
output_json(filtered_findings, redact_secrets)
7390
return
7491

7592
print(f"Scanning {len(files)} Python files...")
@@ -80,7 +97,10 @@ def output(filtered_findings, use_json, files):
8097
print("\n--- Findings ---\n")
8198

8299
for finding in filtered_findings:
83-
print(f"[{finding.severity}] {finding.file_path}:{finding.line_number} {finding.rule_name}{finding.value}")
100+
display_value = finding.value
101+
if redact_secrets:
102+
display_value = redact_value(display_value)
103+
print(f"[{finding.severity}] {finding.file_path}:{finding.line_number} {finding.rule_name}{display_value}")
84104
print(f" Reason: {finding.reason}\n")
85105

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

0 commit comments

Comments
 (0)