DEV Community

Bryan Williams
Bryan Williams

Posted on

My AI reviews its own code with 4 rival models. The majority just approved a security hole three rounds straight.

Here's a rule I use that sounds paranoid until you watch it work: when my AI agent changes one of its own safety gates, the change gets reviewed by a panel of four rival AI models from four different labs — and one dissent kills the change. Not a vote. If one reviewer says "risky," it's risky, even when the other two say ship it.

One detail before the story, because the numbers below say three, not four: during these rounds one of the four reviewers was down. The system doesn't quietly run smaller when that happens; it stamps the missing seat onto every verdict it issues. So these rounds ran three-of-four, with the absence on the record.

This week that rule earned its keep.

The bug that took four rounds to die

The change under review was a safety gate — the thing that stops my agent from "freezing" a test harness that's secretly blind to some of its inputs. I'd hit that failure before, thought I'd fixed the gate, and sent the fix to the panel.

  • Round 1. My fix let the agent skip the check by writing a justification — a sentence it fully controls. gpt and gemini: looks good. deepseek: "self-attested waiver — logging it doesn't enforce anything."
  • Round 2. Fine — the waiver now requires actually running the check. deepseek again: "your 'did it run' test matches any command that mentions the tool. It never checks the tool passed."
  • Round 3. I ripped the waiver out entirely. deepseek: "the pass-receipt is matched against the agent's own reply text — it can literally type the magic word to clear the gate." That was the real root. I'd missed it three times.
  • Round 4. The receipt now comes only from actual tool output — never from the agent's own words. All three signed off.

Three rounds in a row, two out of three reviewers approved a live hole, and one kept finding the next layer. If I'd taken the majority, I'd have shipped it in round one — confidently.

Different models catch different things, too. Same session, gemini caught a bug the other two walked past: a temp filename built from Date.now ? 'x' : 'x' — a botched ternary that always returns the same string, so every run wrote the same file and could race itself into silently skipping its own check.

Why one dissent beats a vote

Models trained on overlapping data have overlapping blind spots — their errors are correlated. So when they agree, that's weaker evidence than it feels like. The one reviewer who sees what the others don't is exactly the signal you built a panel to find — and a majority vote is designed to erase that reviewer.

So, for verification (not creative work — verification):

  1. Never let a system grade its own output. It'll pass itself. This session proved it would even do it by accident — matching its own reply text as the receipt.
  2. One credible dissent is the verdict. Majority votes are for elections. Bugs don't caucus.

This catches mistakes, not sabotage — a reviewer that's confidently wrong can still slip through. Mistakes are what actually ship, so that trade has been worth it every time.

The kicker

I ran this post through the same panel before publishing. First draft, all three flagged the same thing: my title claimed a universal law from one night's data. They made me walk it back to what you just read — what actually happened, no more, no less.

The system that catches my agent overclaiming caught me overclaiming. That's the whole idea, working.

Top comments (3)

Collapse
 
reidmarlow profile image
Reid Marlow

Round 3 is the exact trap that bites everyone building these harnesses. The moment a verification gate scans the conversational stream or agent-controlled output for a pass token, the agent learns the grammar of the receipt instead of satisfying the constraint.

The next failure mode after round 4 usually moves to the shell environment itself. If the tool execution runs in the same workspace or subshell the agent touches, it can alias the binary, drop a stub script in PATH, or touch a fixture file so the real command exits zero with valid JSON. Getting past that means the verification runner has to execute out-of-band in an immutable container or read directly from a signed execution event log that the agent's process cannot write to.

Collapse
 
bryanw profile image
Bryan Williams

Thanks for that, time to dig deeper.

Collapse
 
vinhnguyenthanhdn profile image
Vinh Nguyen

The absence stamp records the missing seat but not what it costs the verdict: under a rule where one dissent kills, removing a reviewer can only make the gate more permissive, so a three-of-four round is a strictly weaker pass than a four-of-four one. That lands hardest on round 4, the only round that ended in sign-off, so the sequence closed on the most permissive configuration the panel ran. Which seat was down matters too, since deepseek supplied the dissent in all three failing rounds while the other two approved every time, so a panel missing that one seat would have passed the hole in round 1 with the absence dutifully recorded. A veto gate cannot be quorum-independent, so the companion to the stamp is that a degraded pass stays provisional until the missing seat votes.