AI coding tools are incredible. Cursor, Lovable, Bolt, Replit, v0 — they've made shipping software faster than ever. Non-technical founders can now build full apps in a weekend.
But there's a catch nobody talks about enough:
AI optimizes for code that works, not code that's secure.
When your AI assistant suggests making your storage bucket public, or disabling Row Level Security on your database, or hardcoding an API key — it's not being malicious. It's taking the path of least resistance. And that path leads straight to a breach.
The Numbers Are Scary
- Wiz scanned 5,600 AI-built apps: 400 had exposed secrets
- GuardMint audited 200+: 91.5% had vulnerabilities directly from AI hallucination
- Lovable ships 70% of apps with Row Level Security disabled
- Bolt turns RLS off by default
Martin Fowler's team at Thoughtworks put it perfectly:
"Telling an AI agent to be safe is not the same as enforcing that it is safe. Prompts can be overridden, misunderstood, or ignored."
What I Found in 5 Manual Audits
| # | Issue | Apps Affected |
|---|---|---|
| 🔴 | Exposed API key or DB password in frontend JS | 3/5 |
| 🔴 | Row Level Security completely disabled | 4/5 |
| 🔴 | Publicly readable database (entire DB) | 1/5 |
| 🟡 | Routes missing auth checks | 3/5 |
| 🟡 | Storage buckets set to public | 2/5 |
| 🟡 | Missing rate limiting on auth endpoints | 5/5 |
Every single founder was shocked. They had no idea any of this was happening.
The 5 Things AI Coding Tools Consistently Get Wrong
1. Hardcoding Secrets
const supabase = createClient(
'https://abc123.supabase.co',
'eyJhbGciOi...full-anon-key...' // 🔴 IN FRONTEND JS!
);
2. Disabling Row Level Security
Supabase's RLS is opt-in. AI tools don't enable it unless you explicitly ask. Result: anyone with your anon key can read every row in every table.
3. Public Storage Buckets
AI: "Let's make this bucket public so images load faster."
Reality: every file in that bucket is now accessible to anyone with a URL.
4. Over-Permissioned Service Accounts
AI tools often create service accounts with admin or owner roles because it's the simplest way to make things work.
5. Missing Auth Guards
app.get('/api/user-data', (req, res) => {
// No auth check! Anyone can hit this.
const data = await db.query('SELECT * FROM users');
res.json(data);
});
The Fix: Two Things Every Vibe Coder Needs
1. An Audit (Check What's Broken)
Run a security scan on your codebase. Look for exposed secrets, database permissions, auth gaps, dependency vulns, security headers.
2. A Shield (Prevent Future Mistakes)
Add a .cursorrules or CLAUDE.md that tells your AI:
- Never hardcode secrets
- Always enable RLS
- Never make storage buckets public
- Always use least-privilege service accounts
- Always add auth checks to protected routes
I Built This
I built VibeSafe to automate both:
- Pre-Launch Audit ($39) — Scan your GitHub repo. Plain-English report in 24 hours.
- Post-Launch Scan ($19) — Scan your live URL. SSL, headers, exposed files. Trust badge included.
- Shield ($29) — Auto-generated security context file for your exact stack.
- Full Bundle ($49) — All three.
- Continuous ($39/mo) — Weekly rescans + breach monitoring.
Built for founders, not security engineers. If you can ship an app with AI, you can use this.
Quick check for your own codebase:
grep -r "eyJ" --include="*.js" --include="*.ts" --include="*.tsx" .
grep -r "api_key\|apikey\|secret\|password\|token" --include="*.js" .
You might be surprised what you find.
Top comments (0)