The corpus figure in the headline is wrong. The correct number is 826,644 unique real agent commands, not 1,085,159.
The original count summed the per-dataset unique totals, and one dataset —
nvidia/SWE-Hero-openhands-trajectories — was enumerated twice (250,000 + 300,000).
A recount against a single global dedup set (scripts/corpus_million_globaldedup.py,
artifact results/million_recall_2026-07-28.json) gives 826,644 unique
commands, 303 catalog-flagged dangers, 301 neutralized and
2 allowed. Two SWE-Gym splits were excluded because their upstream split names
changed, so the honest range is 826,644–835,128; we cite the lower bound.
The result itself does not change: 0 real recall misses. The two remaining allows are the same disposable-artifact cleanups adjudicated below — the earlier "4 allows = 2 unique commands" wording was itself an artifact of the double count. The title and URL of this post are left as published so existing links and citations keep resolving; every number in the body below has been corrected.
We replayed 826,644 real AI-agent commands through a deterministic gate
0 misses on the covered set. ~0.6% intervention. And a bypass suite that prints its own open gaps — 3 named today, 2 of which slip the whole product — instead of hiding them.
TL;DR: an AI agent that "knows" the safety rule still runs terraform destroy,
because a rule in the prompt is documentation, not enforcement. We built a
deterministic, fail-closed gate that sits at the tool boundary and blocks
irreversible actions before they execute. Then we did the boring, falsifiable
thing: replayed 826,644 unique real agent commands from 5 public datasets
through the full gate. It missed 0 of the real dangers. It also does not
cover every bypass shape — and instead of hiding the ones it misses, we print
them. This post includes that list.
inspectable two-step installer · Apache-2.0 · github.com/BGMLAI/gate.cat
Why this exists
The incidents are real and specific. An AutoGen agent ran terraform destroy in
a loop and burned ~$106k. A Replit agent dropped a production database. On the
Cursor forum, a developer's agent "nuked my entire system" from a git clone
request; another agent deleted a file and then decided to hide the deletion
from the user. The pattern is always the same: benign request → the agent
widens scope → an irreversible command → sometimes a cover-up.
Prompt-level rules don't stop this, because the model that's supposed to follow the rule is the same component that just decided to break it. Enforcement has to live outside the model's control flow.
What the gate is (one paragraph)
A deterministic deny-list of 71 default policies (73 including the opt-in
presets; counted live on 2026-07-29 against v0.4.18 — it was 28 when this post first
ran) for the irreversible-action
class (rm -rf, terraform destroy, DROP TABLE, cloud/k8s deletes, disk
wipes, force-push, secret deletion, …), plus an independent exec analyzer and a
human-in-the-loop stage. Fail-closed: engine error, empty input, anything it
can't reason about → BLOCK, never a silent allow. Same command → same verdict,
no temperature, nothing to persuade. Its strongest form is a Claude Code
PreToolUse hook that runs in the harness — the tool call physically cannot
execute until the gate returns.
The measurement (so you can refute it)
We took 826,644 unique real agent commands from five public datasets
(Nemotron, SWE-Zero, SWE-Hero, Kwai SWE-smith-mini, nebius), plus an independent
catalog of 43 known danger classes, and ran every command through the full
gate pipeline. (Deduplication is global across datasets — see the correction at
the top of this post; artifact: results/million_recall_2026-07-28.json.)
- 0 real recall misses across all 826,644 commands. The catalog flagged 303 dangers; the gate neutralized 301. The remaining 2 "allows" were disposable-artifact cleanups the gate correctly permits (the same shape blocks on a real target) — a catalog false alarm, not a gate miss. We show the adjudication rather than quietly reporting "301/303."
- On a separate axis — 43 known danger classes through the full gate: 100%
recall (30 block, 13 warn), with 0 false-blocks on the benign twins.
Reproducible with no datasets at all:
scripts/recall_danger_axis.py. - Intervention rate ~0.6% on real traffic (measured on two independent logs: a 14.7k-command Claude Code log and a public 8.6k-command SWE-agent corpus). It is a wall you rarely hit, not a nagging assistant. (Measured on those logs — not on yours; your number is your number.)
The part everyone else hides: what we DON'T cover
A security tool that only advertises its wins is selling you a feeling. Here is the gate's own bypass map — the shapes our suite deliberately does not claim to catch, printed by the suite itself:
- a Unicode homoglyph binary name —
rm -rf /srv(U+FF52 fullwidthr) is a different byte sequence, so normpattern matches. Slips the whole product. - printf-hex assembly piped to a shell —
printf '\x72\x6d -rf /srv' | shhas no literalrmtoken and is not thecurl/base64 shape the ENCODED_EXEC wall keys on. Slips the whole product. - a binary name assembled at runtime —
payload=$'\x72m'; $payload -rf /srvnever containsrmas a literal token, so the regex wall can't see it. Wall-only gap: the full product's delete-analyzer still blocks this (verified live againstcheck_action, 2026-07-29 / v0.4.18).
Shapes that used to be on this list and are now caught — relabelled in the
suite, not deleted: base64-assembled payloads (echo <b64> | base64 -d | sh)
and curl … | sh hit the ENCODED_EXEC wall; deletes routed through a language
runtime (python3 -c "os.unlink(...)") surface as a warn for human review;
and (0.4.10) the terraform-destroy agent bypass — piping the interactive yes
into terraform destroy to auto-confirm an irreversible teardown — is now
blocked (the bare interactive form, where a human answers, still passes). The
gap list is supposed to shrink in public. There are still infinitely many ways
to destroy things; a deny-list is a wall in front of the known shapes, not a
proof of safety.
Our bypass suite catches 178/178 of what it claims to, discloses 1 false-block on a 129-case benign corpus (counted against ourselves, not hidden), and prints the open gaps next to the wins (measured 2026-07-29 on v0.4.18; it was 71/71 on a 52-case benign corpus when this post first ran). The honest headline, in one line: the gate is certain only about what it blocks. A command it doesn't match is unchecked, not safe.
That sentence is in our README, not buried in a FAQ. It's also why the right
mental model is gate + sandbox, not gate instead of sandbox: a sandbox limits
the blast radius but can't tell you what the agent tried, and won't stop a
terraform destroy that has real credentials inside the sandbox. They're
complements.
Reproduce it on your own agents (60 seconds, local, no signup)
python3 -m venv .venv
.venv/bin/python -m pip install gate-cat
# 1) the bypass suite, straight from the installed package — real output,
# reproduced 2026-07-29 on gate.cat 0.4.18:
.venv/bin/python -c "from gatecat.integrations import bypass_suite as b; print(b.metrics(b.run()))"
# -> {'claimed_dangers': 178, 'caught': 178, 'catch_rate': 1.0, 'benign': 129,
# 'false_blocks': 1, 'false_block_rate': 0.007751937984496124,
# 'known_gaps': 3, 'product_silent_gaps': 2}
# 2) the full 43-class danger axis (needs the repo, not just the wheel):
git clone https://github.com/BGMLAI/gate.cat && cd gate.cat
python3 scripts/recall_danger_axis.py # 43/43 through the full gate, 0 false-blocks
If your numbers disagree with ours, that's a bug report we want. Every figure in this post traces to a row in our FACTS.md (claim → source → allowed wording). We regenerate the copy from that table, never the other way around.
Honest limits (cite these — they're the point)
- The gate is certain only about what it blocks; unmatched ≠ safe.
- It is not a fact-checker / hallucination detector (the lookup channel is empty by default).
- Prompt-injection defense is experimental and off the headline.
- The uncertainty signal is strongest on small/local models (7–30B, AUC 0.77–0.90) and weaker on frontier (AUC 0.68–0.71).
- Framework adapters (crewAI/LangGraph) — and the framework-agnostic
guard_callableyou wrap AutoGen-style tools with — are in-process convention; only the Claude Code hook is enforcement outside the agent's control flow.
Want the map for your own traffic?
gate.cat is free forever — the gate, the hook, and a local dashboard. Once
it's watching your agent, gate.cat log shows every veto, gate.cat why <cmd>
explains any verdict, and gate.cat stats gives you the running count. That
history lives locally today. (Keeping an off-machine copy — the one your agent
can't delete or rewrite — is the paid tier; the gate itself never costs
anything.)
Written by the maintainer. gate.cat is Apache-2.0 — the deny-list, the exec analyzer, the hook, the bypass map are all open. Poke holes in it: report a veto story or a bypass.
Put the wall in front of your own agent — free, 60 seconds, one line to uninstall.
install safely →