RSS Amplifier

AI Weekender · Mar 30, 2026

8 Ways Vibe-Coded Apps Leak Data

0
Sign in to vote or save

Claudia Ng · AI Weekender

Note: AI Weekender has moved. New posts are published at ai-weekender.com, and this Substack is now an archive.

To keep receiving weekly issues, please subscribe at ai-weekender.com instead of here.

Security researchers scanning apps built with Lovable found 303 unauthenticated endpoints across 170+ projects.

In March 2026, VibeWrench scanned 100 public GitHub repos built with Lovable, Bolt.new, Cursor, and v0.dev, and found 318 vulnerabilities, 89 critical with 70% missing CSRF protection and 41% had exposed secrets or API keys.

These were deployed applications with real users, and most had passed an automated security scan before shipping.

As a data scientist building AI products, I learned most of this from shipping. The fix that works is baking constraints into how you work, not asking the agent to be “more secure” in the next prompt.

Access and secrets, abuse and overload, and LLM-specific gaps in vibe-coded apps (image generated by author)
  • A report scanning 100 public GitHub repos found 318 vulnerabilities, 89 of which were critical.

  • The common failures can be grouped into broken trust boundaries, missing adversarial thinking, and the LLM-specific attack surface.

  • Paste-ready files (audit prompt + project rules + checklist) to protect against these is in the paid section.

A common issue in vibe-coded apps is that authentication is implemented, but object-level authorization is not.

The code proves who is calling the API, but it does not restrict which rows or resources it may touch. Any logged-in user can then read or update data that belongs to another account, known as Broken Object-Level Authorization (BOLA).

Examples include:

  • Supabase (RLS): a policy that only checks auth.uid() IS NOT NULL instead of matching the row’s owner column (e.g. auth.uid() = user_id).

  • Django: a view with @login_required that returns an object by primary key without verifying request.user is allowed to see or change that instance (no ownership check, no get_queryset() scoped to the user).

  • Node / Express: a valid JWT is verified on Authorization, but the handler loads req.params.id (or similar) with no filter tying that record to the authenticated subject.

The second issue is secrets. AI coding agents may shove your API keys into VITE_ or NEXT_PUBLIC_ variables just to get a feature working. These prefixes are functionally a “make public” flag, instructing the build tool to bake those values directly into your client-side bundle. If your key is in there, you’re exposing your billing account to anyone who knows how to open DevTools.

The third risk is unauthenticated endpoints, a gap where “demo-friendly” code often survives into production. Researchers recently identified 303 endpoints (ranging from internal health checks to debug routes) accessible without a login across projects generated by a single agent. This is a critical vulnerability because any route that modifies or reads sensitive data without an explicit middleware check (like authenticateToken) allows anyone with the URL to bypass your entire security model.

This failure mode occurs when an agent builds for the “Happy Path” of a good user, but completely ignores the adversarial tactics a malicious actor may use to break the system.

Cross-Site Request Forgery (CSRF) is a silent hijack where a malicious website triggers a hidden request to your app using a logged-in user’s own browser cookies. It is the most common vulnerability in vibe-coded apps, and was found in 70% of scanned projects! This is a critical problem because an attacker can force a user to perform state-changing actions, like deleting an account, without the user ever clicking a button on your site.

Rate limiting is a resource-control layer that restricts how many requests a single user or IP can make within a specific timeframe. Without this safeguard, an attacker could run a simple script making numerous recursive calls to an AI endpoint, costing you a massive API bill in minutes.

Every app that calls a language model has a new attack surface that didn’t exist in traditional web apps.

Prompt injection: This is ranked #1 safety risk on OWASP’s LLM Top 10. The agent passes user input directly to the model without validation, for example:

The model cannot reliably distinguish an instruction from text passed as data, because both are tokens in the same stream.

RAG apps: indirect injection is the subtler version. A user uploads a document containing text designed to look like a system instruction. The retrieval pipeline surfaces that chunk as context, and the model treats it as a legitimate input without any explicit prompt submission from the user.

Unsafe rendering: Vibe-coded apps often pass AI output directly to the HTML renderer because it’s the default path for formatted responses. An attacker asks the chatbot to produce content containing a malicious script tag. If the app renders the response without sanitization, that script executes in every browser loading the page and one prompt could compromise every active session for multiple users.

To guard against these vulnerabilities, there are three layers of prevention rules:

  1. Audit prompt: run once in Claude Code to find what vulnerabilities exist in your repo.

  2. Global rules: a single file each tool reads every session, covering all three failure modes as a baseline.

  3. Path-scoped rules: four context-specific files (database, API, frontend, LLM) that load only when the agent is editing matching files.

New repo: skip step 1 and add steps 2 and 3 before you start building.

Existing repo: run step 1 first, fix the findings, then add 2 and 3 to prevent regression.

If you are vibe-coding features from prompts alone, these files are the difference between “it works in the demo” and “it survives the next session.” Without them, the agent forgets the threat model the moment you change files. The fix is not louder instructions in chat; it is shipping the constraints with the repo.

In section below: the full audit prompt, the global rules, and the four path-scoped rules files. Just paste and drop them into your repo; no custom setup needed.

Note: AI Weekender has moved. New posts are published at ai-weekender.com, and this Substack is now an archive.

To keep receiving weekly issues, please subscribe at ai-weekender.com instead of here.

Read the original on aiweekender.substack.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.