11import 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
418def 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"\n Total findings: { len (filtered_findings )} " )
0 commit comments