The Limitations of Legacy Security Scanners in a Vibe-Coded World

By Gehan Chopade··7 min read

The way software gets built changed faster than the way it gets secured. In 2024, "vibe coding" entered the mainstream — developers describing features in natural language and letting AI generate the implementation. Cursor, Claude Code, Windsurf, Bolt, and Lovable made it possible for a single developer to ship in a weekend what previously took a team a sprint.

But the security tools meant to protect these applications haven't changed at all. The same SAST, DAST, and SCA scanners that were built for hand-written PHP applications are now being pointed at AI-generated TypeScript apps running on serverless infrastructure. The results are predictably bad.

The Vibe Coding Security Gap

When a developer vibe-codes an application, they describe what they want: "Build a job board with user profiles, employer dashboards, and application tracking." The AI coding tool generates everything — frontend components, API routes, database schema, authentication flows.

The generated code works. Users can sign up, post jobs, apply, and track applications. But the security model is an afterthought at best, absent at worst. Common patterns we see in vibe-coded applications:

Permissive by default. AI-generated RLS policies tend to be too broad. We've seen policies that allow any authenticated user to read any row in any table, because the AI optimized for "make it work" rather than "make it secure."

Client-side authorization. The frontend hides admin features from non-admin users, but the API endpoints accept requests from anyone. The AI built the UI correctly but didn't implement server-side authorization checks.

Exposed infrastructure credentials. Supabase anon keys, API endpoints, and project URLs are embedded in client-side code. This is sometimes intentional (Supabase is designed this way), but without proper RLS policies, it's a direct path to the database.

No input validation on critical flows. Users can modify fields that should be server-controlled — subscription tiers, application statuses, pricing — because the API accepts whatever the client sends.

Why Legacy Scanners Can't Catch This

Traditional security scanners were built with specific assumptions about how applications work. Those assumptions no longer hold.

Assumption: The Application Has a Server

DAST scanners send HTTP requests to a server and analyze responses. They look for reflected input, error messages, missing headers, and known vulnerability signatures in the response.

Modern vibe-coded apps often have no traditional server. They're a static frontend on Vercel or Netlify that talks directly to Supabase (PostgREST + Auth) and a few edge functions. The DAST scanner probes the CDN serving the static frontend and finds... nothing. The actual attack surface — the Supabase API, the RLS policies, the edge function authorization — is invisible to it.

Assumption: Vulnerabilities Are in the Code

SAST scanners analyze source code for dangerous patterns: unsanitized SQL queries, eval() calls, hardcoded secrets, known insecure functions. These patterns were the bread and butter of early-2000s web security.

In a vibe-coded application, the security-critical decisions aren't in the code — they're in the configuration. The RLS policy that grants SELECT on every row. The Supabase dashboard setting that allows public sign-ups. The edge function that doesn't verify the calling user's role. SAST can't see any of this because it's looking at TypeScript while the security model lives in SQL policies and platform settings.

Assumption: Known Vulnerabilities Are the Main Threat

SCA tools check your package.json against CVE databases. They'll tell you that lodash has a prototype pollution issue or that jsonwebtoken has a known bypass. This is useful but increasingly irrelevant to the actual threat model.

The vulnerabilities that matter in vibe-coded applications are bespoke. They're unique combinations of business logic, authorization gaps, and architectural decisions that no CVE database will ever catalog. They're not bugs in dependencies — they're bugs in how the application itself works.

Assumption: Testing Once Is Enough

Many organizations run security scans quarterly or before major releases. This model assumed that code changes were infrequent and well-reviewed.

Vibe-coding inverts this. A developer can generate, deploy, and iterate on an application multiple times per day. Each generation potentially introduces new authorization logic, new API endpoints, and new business rules that weren't present in the last scan. The attack surface is fluid, and periodic scanning captures a single snapshot of a constantly changing target.

Real-World Examples

Here are patterns we've found in real vibe-coded production applications. None of these were caught by scanners.

The Self-Approving Marketplace

A freelance marketplace built with Lovable and Supabase. Contractors could apply for projects. The employer was supposed to approve or reject applications. But the RLS policy on the applications table allowed UPDATE for any user where user_id = auth.uid(). A contractor could update their own application status to "approved." The scanner found zero issues. The business impact was total bypass of the employer approval workflow.

The Role Escalation via Metadata

A SaaS application using Supabase Auth. User roles were stored in user_metadata — a field that Supabase allows users to modify via the client SDK by default. Any user could call supabase.auth.updateUser({ data: { role: 'admin' } }) and become an admin. The new role was embedded in their JWT. No scanner tested this because it requires understanding how Supabase Auth works specifically.

The Public Database

An AI app builder where every generated application shared the same Supabase project. The anon key was in client code (expected for Supabase), but RLS was either misconfigured or not enabled on key tables. Any application's API key could read data from every other application. 3.5 million applications were potentially exposed. The scanner found "informational: API key in source code."

What Needs to Change

The security industry needs tools that match how applications are actually built today:

Architecture-aware testing. The tool needs to understand that a Vercel + Supabase application has its security boundary in RLS policies and edge functions, not in HTTP response headers. It needs to test the actual attack surface, not the deployment surface.

Business logic reasoning. The tool needs to understand what the application does — this is a job board, this is a marketplace, this is a SaaS dashboard — and then test whether the authorization model actually enforces the intended access control.

Continuous testing. With vibe-coded apps changing daily, testing needs to be continuous. Every deployment should be assessed. The feedback loop between introduction and detection needs to be hours, not months.

Fix-ready output. When a vulnerability is found in a vibe-coded application, the remediation should be a prompt that the same AI coding tool can execute. Found a broken RLS policy? Generate the corrected SQL. Found a missing authorization check? Generate the middleware code. Keep the fix in the same workflow as the build.

Adversarial methodology. The most effective approach is to test the way an attacker would — by exploring, adapting, and chaining findings into real attack scenarios. Pattern matching finds the easy wins. Adversarial reasoning finds the critical issues.

The Security Stack for 2026

For engineering teams building with modern tools, the effective security stack looks different from what most security vendors sell:

  • SCA (keep it): Still useful for dependency vulnerabilities. Run it on every commit. It's table stakes.
  • SAST (limited value): Catches some code-level issues but misses most of what matters in modern architectures. Keep it if you have it; don't rely on it.
  • DAST (declining value): Less effective with every architectural shift toward serverless and edge. Still catches some basic issues but provides false confidence on the important ones.
  • AI-powered adversarial testing (essential): The only approach that tests business logic, authorization boundaries, and application-specific attack vectors. This is where the critical findings live.

The vibe-coding revolution made it 10x easier to build applications. The security tooling industry needs its own revolution to keep up. Until then, the gap between what scanners find and what attackers exploit will keep growing.

Contramachine deploys adversarial AI agents that attack your application from the outside in. Get early access to see what's exposed before real attackers do.