Dev.to · 4 min read

A client's vibe-coded app was leaking data. Here's how I closed it in 24 hours

A client's vibe-coded app was leaking data. Here's how I closed it in 24 hours

A client's internal app (an inventory dashboard connected to 4 live Shopify stores) had been built fast, the way a lot of tools get built now. Then an alert came in from an outside scanning service: the repo was public. I traced it the same hour, and the real problem wasn't the repo. It was a database rule that had survived from the prototype: create policy "Allow all for demo" on orders for all using (true); Every table had one. Anyone holding the public anon key (the one that ships in every frontend bundle) could read the orders table, read 4 live Shopify admin tokens, and write to the table that decides who's an admin. I confirmed it with nothing but the anon key, then locked it down. How this happens to people who know better Nobody writes using (true) on purpose for production. It happens like this: You prototype fast, often with an AI builder, and RLS gets in the way, so a "demo" policy goes in. The demo works and becomes the product. The repo gets flipped to public to share a preview. The anon key, which is public anyway, now opens everything. Each step on its own looks harmless. Together they make a breach. AI tools have made steps 1 and 2 take minutes, which is why this keeps coming up so much in 2026. The first 24 hours Repo set to private. Revoked all table access from anon. Every open policy became to authenticated using (is_staff()). Token columns are readable by the service role only, enforced with column grants, not just policies. Sign-up turned off. It was open on an internal tool, so anyone could have made an account. A shared checkCaller() guard went onto 18 edge functions. The anon key is a valid JWT, so "requires auth" on its own proves nothing. Edge logs showed no third-party reads, but they only go back 24 hours. So I treated every token as stolen anyway. The part most guides skip: rotation Re-running Shopify OAuth does not kill old tokens. They stay valid until you rotate the app's client secret and revoke the old one. The order that actually worked: Find every place the secret lives: .env files, Vercel env, Supabase secrets, database rows, webhook URLs. Rotate the client secret and mint new tokens. Update all of those places, then redeploy. Revoke the old secret. Test from the attacker's side: old token → 401, new token → 200, unsigned webhook → 401. We also rotated 47 webhook URL tokens. And when I redeployed, Vercel blocked two builds for a known framework CVE, so "fix the leak" turned into "patch the framework" in the same hour. What I run now, every day at 10:00 A single script scans everything I can reach: Every local repo: tracked .env files, plus secrets in files and git history GitHub: any repo that's public Every Supabase project: RLS off, using (true) policies, secret columns visible to anon, security definer functions callable by anon, public buckets, sign-up state, edge functions without a guard Vercel: env vars marked public that look like secrets Live sites: the HTML and JS bundles, checked against my own .env values npm audit on production dependencies It writes a report and fixes nothing on its own. Real findings get fixed. Intended exceptions go into an allowlist with a written reason, and nothing gets quietly ignored. The checklist I now apply before anything ships Repo private by default, .env* in .gitignore before the first commit Only anon/publishable keys in frontend code RLS on every table, never using (true) for anon on private data Webhooks verified by signature with a constant-time compare Verify like an attacker: the anon key and no auth against tables, RPCs and functions AI made building ten times faster. It did nothing for the security review. If you run tools like this for clients, automate the check before a stranger runs it for you. More on how I build and secure commerce systems: fahadazhar.site

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Cybersecurity News