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 · 繁體中文版
That lockdown commit looked careful
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.
Why a careful audit still missed it
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.
The same week, a mechanical re-audit caught 3 leaks the human review missed
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.
I'm not going to oversell this
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.
Takeaway
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
Top comments (0)