A security gate is a non-zero CLI exit that a CI provider treats as a failed check. AgentGuardian’s gate is a single flag —Documentation Index
Fetch the complete documentation index at: https://docs.agentguardian.io/llms.txt
Use this file to discover all available pages before exploring further.
--fail-under N — backed by a six-code exit table and the QA-004 authoritativeness rules that refuse to gate-pass on a thin scan.
When to use this
- Every pull request that touches an agent’s system prompt, tool surface, memory layer, or framework graph.
- Release branches before tag cut.
- A scheduled
cronworkflow against a long-lived hosted agent, to catch drift between releases.
agent-guardian scan --mode fast without --fail-under.
The flag
--fail-under is the only flag that turns a scan into a gate. Without it the CLI always exits 0 on a clean run regardless of the AIVSS — the report is produced, but no merge is ever blocked. Source: cli.py:2303–2305.
Exit-code table
The six exit codes are defined as module-level constants incli.py:83–89. A gate should treat 0 as pass and everything else as block.
| Exit | Constant | Why it fired | What to do |
|---|---|---|---|
0 | EXIT_OK | Scan completed authoritatively and AIVSS ≥ --fail-under. | Allow merge. |
1 | EXIT_FAIL_UNDER | Scan completed and AIVSS < --fail-under, or the scan was non-authoritative (stub model / non-full mode / coverage below threshold). | Block merge. Read the SARIF annotations and the stderr banner. |
2 | EXIT_CONFIG | Bad invocation — unknown flag, missing --framework-ref, malformed --contract, conflicting target modes. | Fix the workflow YAML. Not a security regression. |
3 | EXIT_TARGET_UNREACHABLE | The pre-scan reachability probe for --endpoint mode failed (two POSTs, 2s timeout each). | Verify the agent is up before the scan step. Add a curl --retry health check, or pass --no-preflight if you have your own readiness gate. |
4 | EXIT_LLM_PROVIDER | The LLM provider returned an unrecoverable error (auth, rate limit, network). | Re-run; check the provider secret. |
5 | EXIT_SANDBOX | The sandboxed code adapter refused to load the target. | Inspect the job log; fix the target reference. |
130 | EXIT_USER_INTERRUPT | The runner cancelled the job (timeout, manual cancel). | Re-run; raise --budget-usd or --budget-seconds if the scan is timing out. |
The authoritativeness rules (QA-004)
A scan can finish with a high AIVSS for the wrong reasons — a stub evaluator that cannot flag findings, afast mode that only ran 3 probes per agent, or a full mode that ran out of budget before covering enough probes for a band call. AgentGuardian refuses to gate-pass on any of those.
The gate logic in cli.py:3114–3131 checks three things in order before comparing the AIVSS to the floor:
-
Is the scan authoritative? A scan is non-authoritative when
scoring_valid=False. With--fail-underset, a non-authoritative scan always returnsEXIT_FAIL_UNDERwith this stderr line: -
Is the mode authoritative? Only
--mode fullproduces amode_authoritative=Truescan (seecore/swarm.py:2104). With--fail-underand--mode fastor--mode smart, the CLI prints:…and returnsEXIT_FAIL_UNDER. Fast and smart scans are iteration smoke checks, not release gates. -
Did coverage clear the mode’s threshold? Each mode has an authoritative-coverage floor, defined in
reports/warnings.py(MODE_AUTHORITATIVE_THRESHOLDS):A scan that finishes below its mode’s floor finalises to--modeAuthoritative coverage floor fast60% smart80% full95% band=NOT_EVALUATEDwithscoring_valid=False, which falls through to rule 1 above. The banner names the actual coverage, the threshold, the finding count, and a remediation (raise budget, or drop to a smaller mode).
scan_result.aivss < fail_under.
How to interpret a failure
When the gate blocks a merge, the stderr line is the first thing to read — it tells you why. Map it to one of the four failure modes below and the right remediation is obvious:| stderr line starts with… | Failure mode | Fix |
|---|---|---|
--fail-under N: FAILED -- AIVSS X < floor N | Real regression. The scan was authoritative and the score dropped. | Triage the SARIF findings; revert or mitigate. |
--fail-under N: FAILED -- scan is non-authoritative (NOT_EVALUATED) | Stub model, mixed evaluator, or coverage below the mode floor. | Re-run with a real --model and --mode full; raise --budget-usd if coverage was the cause. |
WARNING: --fail-under N: this scan was run in --mode fast/smart | Mode is wrong for a gate. | Switch the gating workflow to --mode full. Keep fast/smart for unit-test-style smoke checks. |
WARNING: coverage X% is below the --mode full authoritative threshold (95%) | Budget ran out before enough probes ran. The scan still scored, but the band finalised to NOT_EVALUATED. | Raise --budget-usd or --budget-seconds. |
reports/warnings.py:build_authoritativeness_warning — it is the single source of truth for the four banner branches (stub / mixed / low-coverage / authoritative-no-banner) and is unit-snapshot-tested per branch.
Picking the floor
The five-band AIVSS scale is defined inmodels/severity.py:band_for_score:
| Band | Score range |
|---|---|
excellent | 90–100 |
good | 80–89 |
warning | 60–79 |
poor | 40–59 |
critical | 0–39 |
not_evaluated | (non-numeric — see authoritativeness rules above) |
- First two weeks —
--fail-under 40. Blocks onlycritical-band regressions; the team sees what a real swarm finds without breaking every merge. - Steady state —
--fail-under 60. Matches thewarning/poorboundary; rejects merges that introduce apoor-band finding. - Hardened release branch —
--fail-under 80. Matches thegood/warningboundary; only ships when the agent is in thegoodorexcellentband.
70 is meaningfully different from 60 and 80.
Cost ceiling
A gate that can spend unbounded LLM dollars per PR is not a gate you can leave on. Cap the spend with--budget-usd (USD, metered against actual provider spend) or --budget-seconds (wall-clock).
full-mode scan against the bundled vulnerable demo costs roughly $0.06 on gemini:gemini-2.5-flash; 0.10 leaves headroom for variance.
Next step
Fail builds on critical findings
The recipe for translating SARIF severity into a build break, without double-counting against the AIVSS gate.
GitHub Actions
The full workflow YAML, with SARIF auto-upload to the Security tab.
Reports
Open the
scan.sarif and the signed scan.json the gate produces.Scan modes
Why
full is the only mode a gate should run.