@@ -291,4 +291,184 @@ def test_cli_text_inline_ignore_works_with_redaction(tmp_path):
291291 assert "a****f" not in result .stdout
292292 assert "abc1234567890j" not in result .stdout
293293 assert "ab**********0j" in result .stdout
294- assert "Token" in result .stdout
294+ assert "Token" in result .stdout
295+
296+
297+ def test_cli_json_rule_specific_ignore_suppresses_only_matching_rule (tmp_path ):
298+ findings_file = write_python_file (
299+ tmp_path ,
300+ "findings.py" ,
301+ 'api_key = "AKIAEXAMPLE123456789" # sentinelscan: ignore AWS_ACCESS_KEY\n ' ,
302+ )
303+
304+ result = run_cli (tmp_path , "--json" )
305+ assert_success (result )
306+
307+ data = parse_json_output (result )
308+
309+ assert_single_json_finding (
310+ data ,
311+ line = 1 ,
312+ file = findings_file ,
313+ var_name = "api_key" ,
314+ rule_id = "API_KEY" ,
315+ rule = "API Key" ,
316+ severity = "HIGH" ,
317+ value = "AKIAEXAMPLE123456789" ,
318+ reason = "variable name matched api_key/apikey pattern and value met minimum length" ,
319+ confidence = "HIGH" ,
320+ )
321+
322+
323+ def test_cli_json_rule_specific_ignore_can_keep_aws_match (tmp_path ):
324+ findings_file = write_python_file (
325+ tmp_path ,
326+ "findings.py" ,
327+ 'api_key = "AKIAEXAMPLE123456789" # sentinelscan: ignore API_KEY\n ' ,
328+ )
329+
330+ result = run_cli (tmp_path , "--json" )
331+ assert_success (result )
332+
333+ data = parse_json_output (result )
334+
335+ assert_single_json_finding (
336+ data ,
337+ line = 1 ,
338+ file = findings_file ,
339+ var_name = "api_key" ,
340+ rule_id = "AWS_ACCESS_KEY" ,
341+ rule = "AWS Access Key" ,
342+ severity = "HIGH" ,
343+ value = "AKIAEXAMPLE123456789" ,
344+ reason = AWS_REASON ,
345+ confidence = "HIGH" ,
346+ )
347+
348+
349+ def test_cli_json_rule_specific_ignore_suppresses_multiple_listed_rules (tmp_path ):
350+ write_python_file (
351+ tmp_path ,
352+ "findings.py" ,
353+ 'api_key = "AKIAEXAMPLE123456789" '
354+ '# sentinelscan: ignore AWS_ACCESS_KEY API_KEY\n ' ,
355+ )
356+
357+ result = run_cli (tmp_path , "--json" )
358+ assert_success (result )
359+
360+ data = parse_json_output (result )
361+
362+ assert data == []
363+
364+
365+ def test_cli_json_unknown_rule_specific_ignore_does_not_suppress (tmp_path ):
366+ findings_file = write_python_file (
367+ tmp_path ,
368+ "findings.py" ,
369+ 'password = "abcdef" # sentinelscan: ignore FAKE_RULE\n ' ,
370+ )
371+
372+ result = run_cli (tmp_path , "--json" )
373+ assert_success (result )
374+
375+ data = parse_json_output (result )
376+
377+ assert_single_json_finding (
378+ data ,
379+ line = 1 ,
380+ file = findings_file ,
381+ var_name = "password" ,
382+ rule_id = "PASSWORD" ,
383+ rule = "Password" ,
384+ severity = "HIGH" ,
385+ value = "abcdef" ,
386+ reason = PASSWORD_REASON ,
387+ confidence = "LOW" ,
388+ )
389+
390+
391+ def test_cli_text_rule_specific_ignore_suppresses_only_matching_rule (tmp_path ):
392+ write_python_file (
393+ tmp_path ,
394+ "findings.py" ,
395+ 'api_key = "AKIAEXAMPLE123456789" # sentinelscan: ignore AWS_ACCESS_KEY\n ' ,
396+ )
397+
398+ result = run_cli (tmp_path )
399+ assert_success (result )
400+
401+ assert "API Key" in result .stdout
402+ assert "AWS Access Key" not in result .stdout
403+ assert "AKIAEXAMPLE123456789" in result .stdout
404+ assert "Confidence:" in result .stdout
405+ assert "Reason:" in result .stdout
406+
407+
408+ def test_cli_text_rule_specific_ignore_can_keep_aws_match (tmp_path ):
409+ write_python_file (
410+ tmp_path ,
411+ "findings.py" ,
412+ 'api_key = "AKIAEXAMPLE123456789" # sentinelscan: ignore API_KEY\n ' ,
413+ )
414+
415+ result = run_cli (tmp_path )
416+ assert_success (result )
417+
418+ assert "AWS Access Key" in result .stdout
419+ assert "API Key" not in result .stdout
420+ assert "AKIAEXAMPLE123456789" in result .stdout
421+ assert "Confidence:" in result .stdout
422+ assert "Reason:" in result .stdout
423+
424+
425+ def test_cli_text_rule_specific_ignore_suppresses_multiple_listed_rules (tmp_path ):
426+ write_python_file (
427+ tmp_path ,
428+ "findings.py" ,
429+ 'api_key = "AKIAEXAMPLE123456789" '
430+ '# sentinelscan: ignore AWS_ACCESS_KEY API_KEY\n ' ,
431+ )
432+
433+ result = run_cli (tmp_path )
434+ assert_success (result )
435+
436+ assert "No vulnerabilities found." in result .stdout
437+ assert "AWS Access Key" not in result .stdout
438+ assert "API Key" not in result .stdout
439+ assert "AKIAEXAMPLE123456789" not in result .stdout
440+
441+
442+ def test_cli_json_rule_specific_ignore_works_with_filters_and_redaction (tmp_path ):
443+ findings_file = write_python_file (
444+ tmp_path ,
445+ "findings.py" ,
446+ 'password = "abcdef" # sentinelscan: ignore PASSWORD\n '
447+ 'token = "abc1234567890j"\n ' ,
448+ )
449+
450+ result = run_cli (
451+ tmp_path ,
452+ "--json" ,
453+ "--severity" ,
454+ "MEDIUM" ,
455+ "--confidence" ,
456+ "HIGH" ,
457+ "--redact" ,
458+ )
459+ assert_success (result )
460+
461+ data = parse_json_output (result )
462+
463+ assert_single_json_finding (
464+ data ,
465+ line = 2 ,
466+ file = findings_file ,
467+ var_name = "token" ,
468+ rule_id = "TOKEN" ,
469+ rule = "Token" ,
470+ severity = "MEDIUM" ,
471+ value = "ab**********0j" ,
472+ reason = TOKEN_REASON ,
473+ confidence = "HIGH" ,
474+ )
0 commit comments