@@ -212,7 +212,10 @@ def _level_exceeds(actual: str, maximum: str) -> bool:
212212def _check_gates (report , config : ScanConfig ) -> None :
213213 from mcts .governance .gate_violations import collect_gate_violations
214214
215- violations = collect_gate_violations (report , config )
215+ _exit_on_gate_violations (collect_gate_violations (report , config ), report , config )
216+
217+
218+ def _exit_on_gate_violations (violations : list [str ], report , config : ScanConfig ) -> None :
216219 if not violations :
217220 return
218221
@@ -248,6 +251,54 @@ def _check_gates(report, config: ScanConfig) -> None:
248251 raise typer .Exit (code = 1 )
249252
250253
254+ def _check_finding_policy_gates (
255+ findings : list ,
256+ config : ScanConfig ,
257+ * ,
258+ target : str | None = None ,
259+ scan_scope : str = "repository" ,
260+ ) -> None :
261+ """YAML/CLI policy gates for auxiliary finding lists (no severity heuristic)."""
262+ from mcts .governance .gate_violations import build_gate_scan_report , collect_findings_gate_violations
263+
264+ violations = collect_findings_gate_violations (
265+ findings ,
266+ config ,
267+ target = target ,
268+ scan_scope = scan_scope ,
269+ )
270+ if violations :
271+ gate_report = build_gate_scan_report (
272+ findings ,
273+ config ,
274+ target = target ,
275+ scan_scope = scan_scope ,
276+ )
277+ _exit_on_gate_violations (violations , gate_report , config )
278+
279+
280+ def _check_auxiliary_finding_gates (
281+ findings : list ,
282+ config : ScanConfig ,
283+ * ,
284+ target : str | None = None ,
285+ scan_scope : str = "repository" ,
286+ ) -> None :
287+ """Policy gates plus legacy critical/high heuristic for security-oriented CLIs."""
288+ from mcts .reporting .trust_apply import finding_severity_label
289+
290+ _check_finding_policy_gates (
291+ findings ,
292+ config ,
293+ target = target ,
294+ scan_scope = scan_scope ,
295+ )
296+ if findings and any (
297+ finding_severity_label (finding , config ) in ("critical" , "high" ) for finding in findings
298+ ):
299+ raise typer .Exit (code = 1 )
300+
301+
251302@app .callback ()
252303def main (
253304 version : Annotated [
@@ -1150,7 +1201,6 @@ def inventory(
11501201 scan_all_has_high_severity ,
11511202 write_inventory_scan_all ,
11521203 )
1153- from mcts .reporting .display import effective_severity
11541204 from mcts .reporting .trust_apply import apply_config_trust_layer
11551205 from mcts .taxonomy .mapper import enrich_findings
11561206
@@ -1252,12 +1302,12 @@ def inventory(
12521302 ReportRenderer (resolved_theme , console = console ).render_saved_notice (str (output_path ))
12531303
12541304 combined = shadow_findings + skill_findings + toxic_findings
1255- if combined and any (
1256- ( effective_severity ( f ) if inv_config . findings_trust_mode != "off" else f . severity ). value
1257- in ( "critical" , "high" )
1258- for f in combined
1259- ):
1260- raise typer . Exit ( code = 1 )
1305+ _check_auxiliary_finding_gates (
1306+ combined ,
1307+ inv_config ,
1308+ target = str ( inv_config . target ),
1309+ scan_scope = "inventory" ,
1310+ )
12611311
12621312
12631313@app .command ()
@@ -1294,8 +1344,8 @@ def vet(
12941344 import json
12951345
12961346 from mcts .core .config import ScanConfig
1297- from mcts .reporting .trust_apply import finding_severity_label , merge_scan_config_defaults
1298- from mcts .reporting .vet_trust import apply_trust_to_vet_report , vet_severity_label
1347+ from mcts .reporting .trust_apply import merge_scan_config_defaults
1348+ from mcts .reporting .vet_trust import apply_trust_to_vet_report , vet_finding_to_finding , vet_severity_label
12991349 from mcts .vet import run_vet
13001350
13011351 try :
@@ -1334,8 +1384,13 @@ def vet(
13341384 if not json_output :
13351385 console .print (f"[green]Saved[/green] { output_path } " )
13361386
1337- if any (finding_severity_label (finding , config ) in ("critical" , "high" ) for finding in report .findings ):
1338- raise typer .Exit (code = 1 )
1387+ gate_findings = [vet_finding_to_finding (finding ) for finding in report .findings ]
1388+ _check_auxiliary_finding_gates (
1389+ gate_findings ,
1390+ config ,
1391+ target = package ,
1392+ scan_scope = "vet" ,
1393+ )
13391394
13401395
13411396@app .command ()
@@ -1637,8 +1692,12 @@ def fuzz(
16371692 output_path .write_text (json .dumps (payload , indent = 2 ))
16381693 ReportRenderer (resolved_theme , console = console ).render_saved_notice (str (output_path ))
16391694
1640- if any (finding_severity_label (finding , fuzz_config ) in ("critical" , "high" ) for finding in findings ):
1641- raise typer .Exit (code = 1 )
1695+ _check_auxiliary_finding_gates (
1696+ findings ,
1697+ fuzz_config ,
1698+ target = target_label ,
1699+ scan_scope = "live" if (url or command ) else "repository" ,
1700+ )
16421701
16431702
16441703def _parse_headers (header : list [str ] | None ) -> dict [str , str ]:
@@ -1724,6 +1783,13 @@ def readiness(
17241783 if report .tools_checked == 0 :
17251784 raise typer .Exit (code = 1 )
17261785
1786+ _check_finding_policy_gates (
1787+ report .findings ,
1788+ config ,
1789+ target = str (target ),
1790+ scan_scope = "readiness" ,
1791+ )
1792+
17271793
17281794@app .command (name = "serve" )
17291795def serve_api (
@@ -2205,6 +2271,18 @@ def _execute() -> object:
22052271 console .print (f" • { item } " )
22062272 console .print (f"\n [green]Saved[/green] { output_path } " )
22072273
2274+ if report .static_report :
2275+ from mcts .reporting .models import Finding , ScanReport
2276+
2277+ static_scan = ScanReport .model_validate (report .static_report )
2278+ fuzz_rows = [Finding .model_validate (row ) for row in report .fuzz_findings ]
2279+ _check_auxiliary_finding_gates (
2280+ static_scan .findings + fuzz_rows ,
2281+ config ,
2282+ target = str (target ),
2283+ scan_scope = static_scan .scan_scope ,
2284+ )
2285+
22082286 if report .verdict in {"critical" , "high" }:
22092287 raise typer .Exit (code = 1 )
22102288
0 commit comments