@@ -12,7 +12,7 @@ def handler(self):
1212 config .disable_blocking = False
1313 config .strict_blocking = False
1414 config .sarif_file = None
15- config .sarif_reachable_only = False
15+ config .sarif_reachability = "all"
1616 config .sarif_scope = "diff"
1717 config .sarif_grouping = "instance"
1818 config .sarif_reachability = "all"
@@ -63,6 +63,58 @@ def test_json_output_format(self, handler, caplog):
6363 assert output ["new_alerts" ][0 ]["error" ] is True
6464 assert output ["new_alerts" ][0 ]["description" ] == "Test description"
6565
66+ def test_json_output_includes_unchanged_alerts_with_strict_blocking (self , caplog ):
67+ import logging
68+ from socketsecurity .config import CliConfig
69+ from unittest .mock import Mock
70+
71+ config = Mock (spec = CliConfig )
72+ config .disable_blocking = False
73+ config .strict_blocking = True
74+ config .sbom_file = None
75+
76+ handler = OutputHandler (config , Mock ())
77+
78+ diff = Diff ()
79+ diff .id = "test-scan-id"
80+ diff .diff_url = "https://socket.dev/test"
81+ diff .new_alerts = [
82+ Issue (
83+ title = "New" ,
84+ severity = "high" ,
85+ description = "new" ,
86+ error = True ,
87+ key = "new-key" ,
88+ type = "test-type" ,
89+ pkg_type = "npm" ,
90+ pkg_name = "new-package" ,
91+ pkg_version = "1.0.0" ,
92+ purl = "pkg:npm/new-package@1.0.0" ,
93+ )
94+ ]
95+ diff .unchanged_alerts = [
96+ Issue (
97+ title = "Existing" ,
98+ severity = "high" ,
99+ description = "existing" ,
100+ error = True ,
101+ key = "existing-key" ,
102+ type = "test-type" ,
103+ pkg_type = "npm" ,
104+ pkg_name = "existing-package" ,
105+ pkg_version = "1.0.0" ,
106+ purl = "pkg:npm/existing-package@1.0.0" ,
107+ )
108+ ]
109+
110+ with caplog .at_level (logging .INFO , logger = "socketcli" ):
111+ handler .output_console_json (diff )
112+
113+ output = json .loads (caplog .messages [- 1 ])
114+ assert len (output ["new_alerts" ]) == 2
115+ titles = {a ["title" ] for a in output ["new_alerts" ]}
116+ assert titles == {"New" , "Existing" }
117+
66118 def test_sbom_file_saving (self , handler , tmp_path ):
67119 # Test SBOM file is created correctly
68120 diff = Diff ()
@@ -214,8 +266,8 @@ def test_sarif_file_output(self, tmp_path):
214266 sarif_data = json .load (f )
215267 assert sarif_data ["version" ] == "2.1.0"
216268
217- def test_sarif_reachable_only_filters_non_blocking (self , tmp_path ):
218- """Test that --sarif-reachable-only uses .socket.facts.json reachability."""
269+ def test_sarif_reachability_reachable_filters_non_reachable (self , tmp_path ):
270+ """Test that --sarif-reachability reachable uses .socket.facts.json reachability."""
219271 from socketsecurity .config import CliConfig
220272 from unittest .mock import Mock
221273
@@ -224,7 +276,7 @@ def test_sarif_reachable_only_filters_non_blocking(self, tmp_path):
224276
225277 config = Mock (spec = CliConfig )
226278 config .sarif_file = str (sarif_path )
227- config .sarif_reachable_only = True
279+ config .sarif_reachability = "reachable"
228280 config .sarif_scope = "diff"
229281 config .sbom_file = None
230282 config .target_path = str (tmp_path )
@@ -289,7 +341,7 @@ def make_issue(name, error, ghsa_id):
289341 assert any ("reachable-pkg" in r for r in rule_ids )
290342 assert not any ("unreachable-pkg" in r for r in rule_ids )
291343
292- def test_sarif_reachable_only_falls_back_to_blocking_when_facts_missing (self , tmp_path ):
344+ def test_sarif_reachability_reachable_falls_back_to_blocking_when_facts_missing (self , tmp_path ):
293345 """Test that missing facts file falls back to historical blocking filter."""
294346 from socketsecurity .config import CliConfig
295347 from unittest .mock import Mock
@@ -298,7 +350,7 @@ def test_sarif_reachable_only_falls_back_to_blocking_when_facts_missing(self, tm
298350
299351 config = Mock (spec = CliConfig )
300352 config .sarif_file = str (sarif_path )
301- config .sarif_reachable_only = True
353+ config .sarif_reachability = "reachable"
302354 config .sarif_scope = "diff"
303355 config .sbom_file = None
304356 config .target_path = str (tmp_path )
@@ -328,8 +380,8 @@ def test_sarif_reachable_only_falls_back_to_blocking_when_facts_missing(self, tm
328380 assert any ("blocking-pkg" in r for r in rule_ids )
329381 assert not any ("warn-pkg" in r for r in rule_ids )
330382
331- def test_sarif_output_unchanged_by_strict_blocking_flag (self , tmp_path ):
332- """Strict blocking should not alter SARIF content for diff.new_alerts ."""
383+ def test_sarif_output_includes_unchanged_with_strict_blocking (self , tmp_path ):
384+ """Strict blocking should include unchanged alerts in diff-scope SARIF output ."""
333385 from socketsecurity .config import CliConfig
334386 from unittest .mock import Mock
335387
@@ -339,7 +391,7 @@ def test_sarif_output_unchanged_by_strict_blocking_flag(self, tmp_path):
339391 def build_handler (strict_blocking , output_path ):
340392 config = Mock (spec = CliConfig )
341393 config .sarif_file = str (output_path )
342- config .sarif_reachable_only = False
394+ config .sarif_reachability = "all"
343395 config .sarif_scope = "diff"
344396 config .sbom_file = None
345397 config .strict_blocking = strict_blocking
@@ -375,18 +427,24 @@ def build_diff():
375427 with open (sarif_path_strict_true ) as f :
376428 sarif_true = json .load (f )
377429
378- assert sarif_false == sarif_true
430+ false_rule_ids = [r ["ruleId" ] for r in sarif_false ["runs" ][0 ]["results" ]]
431+ true_rule_ids = [r ["ruleId" ] for r in sarif_true ["runs" ][0 ]["results" ]]
379432
380- def test_sarif_reachable_only_false_includes_all (self , tmp_path ):
381- """Test that without --sarif-reachable-only all alerts are included"""
433+ assert any ("pkg-a" in r for r in false_rule_ids )
434+ assert not any ("pkg-old" in r for r in false_rule_ids )
435+ assert any ("pkg-a" in r for r in true_rule_ids )
436+ assert any ("pkg-old" in r for r in true_rule_ids )
437+
438+ def test_sarif_reachability_all_includes_all (self , tmp_path ):
439+ """Test that --sarif-reachability all includes all alerts."""
382440 from socketsecurity .config import CliConfig
383441 from unittest .mock import Mock
384442
385443 sarif_path = tmp_path / "report.sarif"
386444
387445 config = Mock (spec = CliConfig )
388446 config .sarif_file = str (sarif_path )
389- config .sarif_reachable_only = False
447+ config .sarif_reachability = "all"
390448 config .sarif_scope = "diff"
391449 config .sbom_file = None
392450
@@ -501,7 +559,7 @@ def test_sarif_scope_full_before_after_reachable_filtering_snapshot(self, tmp_pa
501559 def build_handler (output_path , reachable_only ):
502560 config = Mock (spec = CliConfig )
503561 config .sarif_file = str (output_path )
504- config .sarif_reachable_only = reachable_only
562+ config .sarif_reachability = "reachable" if reachable_only else "all"
505563 config .sarif_scope = "full"
506564 config .sbom_file = None
507565 config .target_path = str (tmp_path )
@@ -557,7 +615,7 @@ def test_sarif_scope_full_works_when_diff_not_run(self, tmp_path):
557615
558616 config = Mock (spec = CliConfig )
559617 config .sarif_file = str (out_path )
560- config .sarif_reachable_only = True
618+ config .sarif_reachability = "reachable"
561619 config .sarif_scope = "full"
562620 config .sbom_file = None
563621 config .target_path = str (tmp_path )
@@ -602,7 +660,7 @@ def test_sarif_scope_full_dedupes_duplicate_manifest_uris(self, tmp_path):
602660
603661 config = Mock (spec = CliConfig )
604662 config .sarif_file = str (out_path )
605- config .sarif_reachable_only = True
663+ config .sarif_reachability = "reachable"
606664 config .sarif_scope = "full"
607665 config .sbom_file = None
608666 config .target_path = str (tmp_path )
@@ -644,7 +702,7 @@ def test_sarif_scope_full_with_sarif_file_suppresses_stdout(self, tmp_path, caps
644702
645703 config = Mock (spec = CliConfig )
646704 config .sarif_file = str (out_path )
647- config .sarif_reachable_only = True
705+ config .sarif_reachability = "reachable"
648706 config .sarif_scope = "full"
649707 config .sbom_file = None
650708 config .target_path = str (tmp_path )
@@ -688,7 +746,7 @@ def test_sarif_scope_full_alert_grouping_dedupes_versions(self, tmp_path):
688746
689747 config = Mock (spec = CliConfig )
690748 config .sarif_file = str (out_path )
691- config .sarif_reachable_only = False
749+ config .sarif_reachability = "all"
692750 config .sarif_scope = "full"
693751 config .sarif_grouping = "alert"
694752 config .sarif_reachability = "reachable"
@@ -738,7 +796,7 @@ def test_sarif_scope_full_potentially_filter(self, tmp_path):
738796
739797 config = Mock (spec = CliConfig )
740798 config .sarif_file = str (out_path )
741- config .sarif_reachable_only = False
799+ config .sarif_reachability = "all"
742800 config .sarif_scope = "full"
743801 config .sarif_grouping = "instance"
744802 config .sarif_reachability = "potentially"
0 commit comments