Skip to content

Commit 9ec88f5

Browse files
committed
tests: update and expand testing to include new redact feature
1 parent 051a94b commit 9ec88f5

1 file changed

Lines changed: 256 additions & 1 deletion

File tree

tests/test_cli.py

Lines changed: 256 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"variable name matched password/pwd/passwd pattern and value met minimum length"
88
)
99
TOKEN_REASON = "variable name matched token pattern and value met minimum length"
10+
AWS_REASON = "value matched AKIA-prefixed AWS access key pattern"
1011

1112

1213
def run_cli(*args):
@@ -333,4 +334,258 @@ def test_cli_json_severity_filter_preserves_schema(tmp_path):
333334
"value": "abcdef",
334335
"reason": PASSWORD_REASON,
335336
}
336-
]
337+
]
338+
339+
340+
# Ensure normal text output shows original values when --redact is not used
341+
def test_cli_text_output_is_unredacted_by_default(tmp_path):
342+
password_file = tmp_path / "password_file.py"
343+
password_file.write_text('password = "abcdef"\n', encoding="utf-8")
344+
345+
result = run_cli(str(tmp_path))
346+
347+
assert result.returncode == 0
348+
349+
assert "abcdef" in result.stdout
350+
assert "a****f" not in result.stdout
351+
assert "[REDACTED]" not in result.stdout
352+
353+
354+
# Ensure text output redacts detected values when --redact is used
355+
def test_cli_text_redact_masks_secret_value(tmp_path):
356+
password_file = tmp_path / "password_file.py"
357+
password_file.write_text('password = "abcdef"\n', encoding="utf-8")
358+
359+
result = run_cli(str(tmp_path), "--redact")
360+
361+
assert result.returncode == 0
362+
363+
assert "a****f" in result.stdout
364+
assert "abcdef" not in result.stdout
365+
assert "Reason:" in result.stdout
366+
assert "Password" in result.stdout
367+
368+
369+
# Ensure JSON output shows original values when --redact is not used
370+
def test_cli_json_output_is_unredacted_by_default(tmp_path):
371+
password_file = tmp_path / "password_file.py"
372+
password_file.write_text('password = "abcdef"\n', encoding="utf-8")
373+
374+
result = run_cli(str(tmp_path), "--json")
375+
376+
assert result.returncode == 0
377+
378+
data = parse_json_output(result)
379+
380+
assert data == [
381+
{
382+
"line": 1,
383+
"file": str(password_file),
384+
"var_name": "password",
385+
"rule_id": "PASSWORD",
386+
"rule": "Password",
387+
"severity": "HIGH",
388+
"value": "abcdef",
389+
"reason": PASSWORD_REASON,
390+
}
391+
]
392+
393+
394+
# Ensure JSON output redacts values when --redact is used
395+
def test_cli_json_redact_masks_secret_value(tmp_path):
396+
password_file = tmp_path / "password_file.py"
397+
password_file.write_text('password = "abcdef"\n', encoding="utf-8")
398+
399+
result = run_cli(str(tmp_path), "--json", "--redact")
400+
401+
assert result.returncode == 0
402+
403+
data = parse_json_output(result)
404+
405+
assert data == [
406+
{
407+
"line": 1,
408+
"file": str(password_file),
409+
"var_name": "password",
410+
"rule_id": "PASSWORD",
411+
"rule": "Password",
412+
"severity": "HIGH",
413+
"value": "a****f",
414+
"reason": PASSWORD_REASON,
415+
}
416+
]
417+
418+
419+
# Ensure JSON redaction keeps output machine-readable and pure JSON
420+
def test_cli_json_redact_output_is_pure_json(tmp_path):
421+
password_file = tmp_path / "password_file.py"
422+
password_file.write_text('password = "abcdef"\n', encoding="utf-8")
423+
424+
result = run_cli(str(tmp_path), "--json", "--redact")
425+
426+
assert result.returncode == 0
427+
428+
assert "Scanning" not in result.stdout
429+
assert "--- Findings ---" not in result.stdout
430+
assert "Total findings" not in result.stdout
431+
assert "Reason:" not in result.stdout
432+
433+
data = parse_json_output(result)
434+
435+
assert isinstance(data, list)
436+
assert data[0]["value"] == "a****f"
437+
438+
439+
# Ensure --json, --severity, and --redact work together
440+
def test_cli_json_severity_and_redact_combined(tmp_path):
441+
findings_file = tmp_path / "findings.py"
442+
findings_file.write_text(
443+
'password = "abcdef"\n'
444+
'token = "qwerty123"\n',
445+
encoding="utf-8",
446+
)
447+
448+
result = run_cli(str(tmp_path), "--json", "--severity", "HIGH", "--redact")
449+
450+
assert result.returncode == 0
451+
452+
data = parse_json_output(result)
453+
454+
assert data == [
455+
{
456+
"line": 1,
457+
"file": str(findings_file),
458+
"var_name": "password",
459+
"rule_id": "PASSWORD",
460+
"rule": "Password",
461+
"severity": "HIGH",
462+
"value": "a****f",
463+
"reason": PASSWORD_REASON,
464+
}
465+
]
466+
467+
468+
# Ensure text severity filtering and redaction work together
469+
def test_cli_text_severity_and_redact_combined(tmp_path):
470+
findings_file = tmp_path / "findings.py"
471+
findings_file.write_text(
472+
'password = "abcdef"\n'
473+
'token = "qwerty123"\n',
474+
encoding="utf-8",
475+
)
476+
477+
result = run_cli(str(tmp_path), "--severity", "HIGH", "--redact")
478+
479+
assert result.returncode == 0
480+
481+
assert "[HIGH]" in result.stdout
482+
assert "[MEDIUM]" not in result.stdout
483+
assert "a****f" in result.stdout
484+
assert "abcdef" not in result.stdout
485+
assert "qwerty123" not in result.stdout
486+
487+
488+
# Ensure short detected values are fully redacted
489+
def test_cli_json_redact_short_boundary_value(tmp_path):
490+
password_file = tmp_path / "password_file.py"
491+
password_file.write_text('password = "abcd"\n', encoding="utf-8")
492+
493+
result = run_cli(str(tmp_path), "--json", "--redact")
494+
495+
assert result.returncode == 0
496+
497+
data = parse_json_output(result)
498+
499+
assert data == [
500+
{
501+
"line": 1,
502+
"file": str(password_file),
503+
"var_name": "password",
504+
"rule_id": "PASSWORD",
505+
"rule": "Password",
506+
"severity": "HIGH",
507+
"value": "[REDACTED]",
508+
"reason": PASSWORD_REASON,
509+
}
510+
]
511+
512+
513+
# Ensure longer detected values preserve only limited prefix/suffix context
514+
def test_cli_json_redact_long_value(tmp_path):
515+
password_file = tmp_path / "password_file.py"
516+
password_file.write_text('password = "abc_def-123#$%^&*()"\n', encoding="utf-8")
517+
518+
result = run_cli(str(tmp_path), "--json", "--redact")
519+
520+
assert result.returncode == 0
521+
522+
data = parse_json_output(result)
523+
524+
assert data == [
525+
{
526+
"line": 1,
527+
"file": str(password_file),
528+
"var_name": "password",
529+
"rule_id": "PASSWORD",
530+
"rule": "Password",
531+
"severity": "HIGH",
532+
"value": "ab***************()",
533+
"reason": PASSWORD_REASON,
534+
}
535+
]
536+
537+
538+
# Ensure AWS access key values are redacted in JSON output
539+
def test_cli_json_redact_aws_access_key(tmp_path):
540+
aws_file = tmp_path / "aws_file.py"
541+
aws_file.write_text(
542+
'random_var = "AKIAEXAMPLE123456789"\n',
543+
encoding="utf-8",
544+
)
545+
546+
result = run_cli(str(tmp_path), "--json", "--redact")
547+
548+
assert result.returncode == 0
549+
550+
data = parse_json_output(result)
551+
552+
assert data == [
553+
{
554+
"line": 1,
555+
"file": str(aws_file),
556+
"var_name": "random_var",
557+
"rule_id": "AWS_ACCESS_KEY",
558+
"rule": "AWS Access Key",
559+
"severity": "HIGH",
560+
"value": "AK****************89",
561+
"reason": AWS_REASON,
562+
}
563+
]
564+
565+
566+
# Ensure no-finding JSON output remains an empty list even with --redact
567+
def test_cli_no_findings_json_with_redact(tmp_path):
568+
benign_file = tmp_path / "safe.py"
569+
benign_file.write_text('username = "notsecret"\n', encoding="utf-8")
570+
571+
result = run_cli(str(tmp_path), "--json", "--redact")
572+
573+
assert result.returncode == 0
574+
575+
data = parse_json_output(result)
576+
577+
assert data == []
578+
579+
580+
# Ensure no-finding text output does not print redaction artifacts
581+
def test_cli_no_findings_text_with_redact(tmp_path):
582+
benign_file = tmp_path / "safe.py"
583+
benign_file.write_text('username = "notsecret"\n', encoding="utf-8")
584+
585+
result = run_cli(str(tmp_path), "--redact")
586+
587+
assert result.returncode == 0
588+
589+
assert "No vulnerabilities found." in result.stdout
590+
assert "[REDACTED]" not in result.stdout
591+
assert "Reason:" not in result.stdout

0 commit comments

Comments
 (0)