Your AI coder will happily ship an app that works in the demo and:
• puts your OpenAI key in the browser
• leaves every Supabase row readable by anyone
• grants paid access on the Stripe success page
I built guardrails for that. 🧵
@aguardientico Plus one: turn off auto-update for any extension that runs with shell access and update on purpose after a day or two. A short-lived bad release like this one would mostly pass you by.
@Saanjana_Nikita The minimum before real users show up: know where it's hosted, keep secret keys out of the frontend, turn on row-level security if it's Supabase, and set up backups. Those four cover most of the horror stories.
@liorpesoa Good list. One addition: if the scan finds a key in git history, deleting the line isn't enough. Rotate the key first, since anyone who cloned or scraped the repo already has it. Cleaning the history comes second.
@9sjin And a classic Stripe bug in vibe-coded apps: granting access on the success page. Anyone can open that URL without paying. Fulfill from a verified webhook (checkout.session.completed, signature checked) and treat the success page as just a thank-you.
@hexablob Two habits that shrink the blast radius: turn off extension auto-update in the editor you code in, and keep only dev/test keys in your local .env. Prod keys live in your host's env settings, so a compromised laptop leaks test creds, not live ones.
@ihteshamali If you might be affected: check which version of the Claude Code extension you have, remove it if it's the bad one, look in ~/.ssh/authorized_keys for keys you don't recognize, and rotate any tokens that machine could reach, from a different computer.
@jcinjpn The anon key is meant to be public, so devtools isn't the real problem. RLS being off is. Quick test: open a private window, take the anon key from the bundle, and try selecting from each table. If rows come back, the policy is what's missing, not the key.
@deni0107 Right, the policies are the other half. A quick test: sign in as a second user and try to read the first user's rows. If you can, the policy needs work.
Stuck in a fix loop? If the agent's third attempt hits the same error, stop.
Revert to your last good commit, start a fresh chat, paste the full error and the file, and ask it to explain the cause before writing any code.
A clean context usually beats a fourth patch.
@tommy_hayes1 Glad it helped! Webhooks are an easy one to miss because everything works in testing even without the signature check. Thanks for reading!
@SabarnathX Agree. What helps most in practice: commit before every agent run, one branch per task, and read the diff before merging. If it deletes files or touches auth or payments, that's a stop-and-review moment, not an auto-accept.
@poorvith_mp Rule 1 is the big one! I also make the agent paste the exact command and the last lines of real output, and run the tests yourself before merging. "All tests pass" after it quietly skipped or deleted the failing test is a classic.
@theozbuilds Good check. One nuance: Supabase's anon key in the bundle is expected and fine only if RLS is on with real policies. Anon key plus a table with RLS off is the actual leak, so also try reading your tables while logged out.
@xyjkaipost Good breakdown. I'd add one more layer: give the agent a dev .env with test-mode keys only (Stripe sk_test, a throwaway Supabase project). If something does read it, the blast radius is a sandbox, not prod. Live keys stay in your host's secret store.
@whoizmide Painful one. A cheap guard: keep the session secret only in env, and have the app refuse to boot if it's missing or under 32 chars. Then a "helpful" refactor fails loudly at startup instead of quietly signing sessions with something weak.
@0xAndrewShu Good additions. The PreToolUse hook is what closes the bash gap the Read deny rules leave. I'd also scan commits for key-shaped strings, since no hook catches a secret the app itself writes to a log.