Your docs list "Block LLM Agent RCE" as a headline use case. Tracing that feature end-to-end:
In security_lens.py's scan_content, agentic-RCE and prompt-injection hits are counted correctly:
pythoncounts["prompt_injection"] = prompt_injection_hits
counts["agentic_rce"] = agentic_rce_hits
snippets["tainted_injection"] = taint_snippets # <- only this one gets a snippets key
Every taint-tracking snippet — including the [LLM -> RCE] and [LLM State -> RCE] ones — gets dumped into the single "tainted_injection" bucket. snippets["prompt_injection"] and snippets["agentic_rce"] are never created.
Meanwhile, sarif_recorder.py builds its findings by iterating telemetry["threat_snippets"].items() — and since threat_snippets is exactly this snippets dict, it can never produce a GG-AGENT-VULNERABILITY or prompt-injection SARIF result, because those keys simply don't exist to iterate over.
This compounds with a second issue: SecurityLens.evaluate_risk() — the method that would classify agentic_rce > 0 as "Autonomous Execution Vector (Critical)" at a 100.0 score — is never called anywhere in the codebase. I grepped all 21 files for .evaluate_risk(; the only hit is the definition itself. The actual risk scoring for these categories lives in a separate, independently-written implementation in signal_processor.py (_calc_logic_bomb, _calc_injection_surface, etc.). Two parallel implementations of the same five risk categories exist in the codebase; only one is wired in.
Net effect: the numeric risk score for prompt-injection/agentic-RCE probably does get calculated somewhere in the signal_processor path, but the specific, actionable, line-level SARIF finding a CI/CD pipeline would actually act on — the one your cookbook page promises — doesn't get produced. Fix: add snippets["prompt_injection"] = [...] and snippets["agentic_rce"] = [...] in scan_content, and either delete evaluate_risk() or make it the actual source of truth instead of signal_processor.py's parallel copy.
Your docs list "Block LLM Agent RCE" as a headline use case. Tracing that feature end-to-end:
In security_lens.py's scan_content, agentic-RCE and prompt-injection hits are counted correctly:
pythoncounts["prompt_injection"] = prompt_injection_hits
counts["agentic_rce"] = agentic_rce_hits
snippets["tainted_injection"] = taint_snippets # <- only this one gets a snippets key
Every taint-tracking snippet — including the [LLM -> RCE] and [LLM State -> RCE] ones — gets dumped into the single "tainted_injection" bucket. snippets["prompt_injection"] and snippets["agentic_rce"] are never created.
Meanwhile, sarif_recorder.py builds its findings by iterating telemetry["threat_snippets"].items() — and since threat_snippets is exactly this snippets dict, it can never produce a GG-AGENT-VULNERABILITY or prompt-injection SARIF result, because those keys simply don't exist to iterate over.
This compounds with a second issue: SecurityLens.evaluate_risk() — the method that would classify agentic_rce > 0 as "Autonomous Execution Vector (Critical)" at a 100.0 score — is never called anywhere in the codebase. I grepped all 21 files for .evaluate_risk(; the only hit is the definition itself. The actual risk scoring for these categories lives in a separate, independently-written implementation in signal_processor.py (_calc_logic_bomb, _calc_injection_surface, etc.). Two parallel implementations of the same five risk categories exist in the codebase; only one is wired in.
Net effect: the numeric risk score for prompt-injection/agentic-RCE probably does get calculated somewhere in the signal_processor path, but the specific, actionable, line-level SARIF finding a CI/CD pipeline would actually act on — the one your cookbook page promises — doesn't get produced. Fix: add snippets["prompt_injection"] = [...] and snippets["agentic_rce"] = [...] in scan_content, and either delete evaluate_risk() or make it the actual source of truth instead of signal_processor.py's parallel copy.