All Posts

5 Security Risks Every Vibe Coder Should Know

February 21, 20264 min readVibeSafe Team
vibe-codingsecurityai-toolsvulnerabilities

What Is Vibe Coding?

Vibe coding is building software by describing what you want to an AI tool and letting it write the code. Tools like Cursor, Bolt, Lovable, v0, Replit, and Claude Code have made it possible for anyone to ship a web app in hours.

The problem? Every AI coding tool optimizes for functionality — not security. They generate code that works, but that code often has serious security vulnerabilities baked in.

We've scanned thousands of vibe-coded apps at VibeSafe. Here are the 5 most common security risks we find.

1. Exposed API Keys in Client-Side Code

How common: Found in ~40% of scans

AI tools store API keys wherever they're needed. They don't always distinguish between server-side and client-side code. The result: your OpenAI key, Stripe secret key, or Supabase service_role key ends up in the JavaScript bundle that anyone can read.

What can go wrong:

  • Your OpenAI bill spikes to thousands of dollars
  • Someone steals your Stripe key and creates fraudulent charges
  • Your entire database is readable and writable

Fix: Move all secret keys to server-side environment variables (no NEXT_PUBLIC_ prefix) and call APIs through your own backend routes.

2. Missing Security Headers

How common: Found in ~70% of scans

No AI tool adds security headers by default. Headers like Content-Security-Policy, Strict-Transport-Security, and X-Frame-Options protect against XSS, man-in-the-middle attacks, and clickjacking.

What can go wrong:

  • XSS attacks inject malicious scripts into your app
  • Your app can be embedded in an iframe and used for phishing
  • Browser doesn't enforce HTTPS

Fix: Add a security headers configuration to your next.config.ts or middleware:

// next.config.ts
async headers() {
  return [{
    source: "/(.*)",
    headers: [
      { key: "X-Frame-Options", value: "DENY" },
      { key: "X-Content-Type-Options", value: "nosniff" },
      { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
      { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
    ],
  }];
}

3. No Auth Checks on API Routes

How common: Found in ~35% of scans

AI tools generate API routes that handle data — create, read, update, delete — but they almost never add authentication checks. Anyone who knows the endpoint URL can call it.

What can go wrong:

  • Unauthorized users access or modify data
  • Admin functions are available to everyone
  • Data exfiltration through unprotected endpoints

Fix: Check the user's session at the top of every API route handler. In Next.js with Supabase:

export async function POST(req: Request) {
  const supabase = createServerClient();
  const { data: { user } } = await supabase.auth.getUser();

  if (!user) {
    return Response.json({ error: "Unauthorized" }, { status: 401 });
  }

  // Now safe to process the request
}

4. CORS Wildcard Configuration

How common: Found in ~25% of scans

When AI tools need to handle cross-origin requests, they set Access-Control-Allow-Origin: * — allowing any website to call your API. This is especially dangerous if your API uses cookies or session tokens.

What can go wrong:

  • Malicious websites can make API calls on behalf of your users
  • Session hijacking through cross-origin requests
  • Data theft from your API

Fix: Set specific allowed origins instead of wildcard:

const allowedOrigins = ["https://yourapp.com"];

if (allowedOrigins.includes(origin)) {
  response.headers.set("Access-Control-Allow-Origin", origin);
}

5. Database Security Misconfigurations

How common: Found in ~20% of scans

When using Supabase or Firebase, AI tools often skip Row Level Security (RLS) policies. They create tables and insert data, but they don't add policies that restrict who can read or write what.

What can go wrong:

  • Any user can read all data in all tables
  • Users can modify other users' records
  • Sensitive data (emails, addresses, payment info) is publicly accessible

Fix: Enable RLS and create policies for every table:

ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users see own todos"
  ON todos FOR SELECT
  USING (auth.uid() = user_id);

CREATE POLICY "Users create own todos"
  ON todos FOR INSERT
  WITH CHECK (auth.uid() = user_id);

How to Check Your App

You can manually audit each of these, or run an automated scan:

  1. Go to vibesafe.tech
  2. Paste your deployed URL
  3. Get your security grade in 60 seconds

VibeSafe checks for all 5 of these risks — plus 50 more — and gives you step-by-step fix instructions for each finding.

The Bottom Line

Vibe coding is great for speed. But speed without security is a liability. Build fast, then scan. Fix the issues before your users find them — or worse, before an attacker does.

Is your app vulnerable?

Run a free security scan and find out in 60 seconds.

Scan Your App Free