cd /news/developer-tools/how-a-security-bug-gave-birth-to-a-m… Β· home β€Ί topics β€Ί developer-tools β€Ί article
[ARTICLE Β· art-123413] src=dev.to β†— pub= topic=developer-tools verified=true sentiment=Β· neutral

How a Security Bug Gave Birth to a Method, Then the Method Caught What the Audit Missed

A developer detailed how a security bug led to the creation of the Confrontation-Point Law, a method for auditing database write permissions. The method, which forces a mechanical re-census of all write points using grep/AST and privilege queries, caught three admin direct-write points that a previous human audit missed. The developer emphasized that narrative judgments like 'I read it, looks fine' are insufficient, and only machine-verified checks should be trusted.

read4 min views2 publishedSep 8, 2026

At 5:27pm on 2026-07-03, I revoked self-write access on 8 sensitive columns of our members table. At 9:42pm the same day, I reverted it β€” an admin save feature started throwing 403 errors. Locked, then unlocked, same day.

That incident became the seed for a method we call the Confrontation-Point Law. I won't claim it's proven β€” there's exactly one real case so far, and we've deliberately labeled it "armed, not battle-tested." But that one case is one of my favorite technical stories to date, because what it caught was something a careful human audit had already missed.

Read on: Previous: don't ask a model to narrate itself Β· Next: AI auditing an AI's own toolchain Β· ηΉι«”δΈ­ζ–‡η‰ˆ

The 07-03 lockdown commit's header read: "verified all 5 write paths to the users table site-wide, MembersCenter.vue goes through fn_admin_* RPCs." That's not a throwaway line β€” someone actually enumerated the paths and labeled each as a legitimate channel. On paper, this looked like a solid audit.

But inside that same file, the function saveEditMember calls an RPC to write member_level at line 2010 β€” and ten lines later, at line 2020, the same function does a raw .from('users').update({ tier_updated_at, tier_expires_at, tier_auto_downgrade }). Direct write, no gate.

The same function was, at the file level, a proper RPC channel β€” and at the field level, simultaneously an unguarded direct-write channel. That gap is exactly what triggered the 403s that night, and exactly why we reverted four hours later.

Looking back, what bothers me isn't that there was a bug. It's why a careful audit still missed it. The answer is blunt: the auditor read the code, saw the RPC call, saw a comment that said "goes through RPC," and issued a file-level verdict. The census got outsourced to narrative. The fire wasn't because the set of write points was too large to enumerate β€” we later verified the whole frontend only touches that field in 3 files, something a dumb grep finds in seconds. The fire was because the verdict substituted "I read it, looks fine" for "I mechanically checked every single line."

That finding is what produced the first rule of the Confrontation-Point Law: every frozen judgment needs to name its confrontation point β€” a place where intent and actual state are forced to meet, where any disagreement blocks progress, sitting right on the boundary where real harm happens. Who's allowed to sit in the "this is what's actually true" seat? Only a machine β€” a real query like has_column_privilege, never an agent reading code and saying "I checked, looks fine." Narrative sitting in that seat is a fake census. That "goes through RPC" comment is a live example of narrative sitting in the wrong seat.

On 07-04, instead of trusting "I read it, looks fine" again, we ran a fully mechanical re-census: every claimed-legitimate write point had to be re-derived through grep/AST plus an actual privilege query. Anything that couldn't be re-derived got flagged red on the spot β€” no exceptions.

This caught 3 admin direct-write points the earlier review had completely missed: renewTier, dismissBinding, importMembers. All 8 sensitive columns were re-verdicted from scratch β€” all 8 came back safe to revoke β€” and the three admin write paths got migrated into three new SECURITY DEFINER RPCs. This time the rollout order was deliberately sequenced: ship the RPCs first, wait for the frontend deploy to land, then run the revoke β€” specifically to avoid repeating the 07-03 disaster of locking permissions before the frontend had caught up.

After going live, we actually verified it in production, not just in code review: a regular member trying to self-write any of the 8 columns gets a 403; all 5 admin paths still work.

Honestly: this whole method has exactly one real case behind it so far. We deliberately don't call it "battle-tested" β€” only "armed": self-tests pass, an injected regression test passes, but it hasn't yet stopped a real attack we didn't already know about. That line is written into the method itself: armed is not the same evidence tier as battle-tested.

There's a funny footnote to how this method got written, too: one of the prompts we fed to Fable had a placeholder bug that silently ate the draft content. Fable didn't hallucinate a plausible-sounding answer to cover for it β€” it just refused to answer. We retroactively counted that refusal as a live demonstration of the exact principle we were designing: refusing to answer is itself a legitimate output.

One more loose thread, left here honestly rather than swept under the rug: the same review found Addresses.vue writing to a column called addresses that doesn't actually exist in the database. That's deliberately out of scope for this fix and still unresolved.

A careful-looking audit can still lie at the field level, if its "verified" claim comes from a human reading code and forming a narrative judgment. A census you can actually trust is one where every single row can be mechanically re-derived β€” anything that can't gets flagged, no matter how confident the write-up sounds. And keep "armed" and "battle-tested" as two different evidence tiers β€” blurring them is just lying to yourself with extra steps.

ζœ¬ζ–‡εŽŸθΌ‰ζ–Όζˆ‘ηš„ιƒ¨θ½ζ ΌοΌšHow a Security Bug Gave Birth to a Method, Then the Method Caught What the Audit Missed

── more in #developer-tools 4 stories Β· sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/how-a-security-bug-g…] indexed:0 read:4min 2026-09-08 Β· β€”