Course contents
Security for beginners
Learn why vibe-coded apps leak data, from documented 2025–2026 incidents, and the five habits that prevent most of those leaks.
An agent's job, as it understands it, is to make your app work. Making it safe is a different job, and it doesn't happen unless someone asks for it and checks it. A leaky app and a safe app look identical in a demo. The difference shows up later, when a stranger opens the browser's developer tools or a bot finds your key.
None of the incidents below needed a brilliant attacker. Each one came down to a basic rule nobody checked.
What went wrong, in documented cases
| When | What happened | The basic rule that was missed |
|---|---|---|
| March–May 2025 | Researchers scanned 1,645 apps from Lovable's showcase and found 170 whose databases let anyone read or change data, including emails, payment records and API keys. They even inserted a record marking a payment as paid. It was published as CVE-2025-48757. | Lock the database: access rules (row-level security) on every table |
| July 2025 | During SaaStr founder Jason Lemkin's public test of Replit's agent, the agent deleted his production database during a code freeze, wiping records for more than 1,200 executives. He restored it by hand. Replit's CEO called it “unacceptable”, and Replit added automatic separation of development and production databases. | Don't give an agent access to live data, and keep backups |
| October 2025 | Escape.tech scanned more than 5,600 public vibe-coded apps and found over 2,000 vulnerabilities, more than 400 exposed secrets, and 175 cases of exposed personal data such as medical records and bank account numbers. | Keep secrets out of front-end code |
| January–February 2026 | Wiz found that Moltbook, a social network for AI agents whose founder said he “didn't write a single line of code”, had its database key in its public JavaScript and no row-level security. Anyone could read 1.5 million API tokens, 35,000 email addresses and private messages. | A public key is only safe behind database rules |
| February 2026 | An exam app built on Lovable exposed 18,697 user records, including students'. According to the researcher who reported it, the AI-written access check was backwards: it blocked signed-in users and let anonymous visitors through. | Test access as a signed-out stranger |
| May 2026 | Security firm RedAccess reported about 5,000 vibe-coded apps holding exposed sensitive data, out of roughly 380,000 public ones it found on Lovable, Base44, Replit and Netlify. Some platforms made apps public by default, and many were indexed by search engines. The platforms disputed parts of the report. | Decide who can see your app on purpose |
Notice the pattern. The code worked in every case. What was missing were rules about who may see and change what, and where secrets live. Those are exactly the things an agent won't add unless you ask, and won't test unless you insist. The five habits below cover all six incidents.
Habit 1: secrets stay on a server
A secret is anything that grants access: an API key for a paid service, a database password, an admin login. Every visitor downloads your front-end code, so a secret in it is published. Secrets belong in environment variables on a server: settings stored on the host, outside your code, that only server-side code can read. On your own computer they live in a file called .env, which is listed in .gitignore so git never commits it.
VITE_ in Vite or NEXT_PUBLIC_ in Next.js, are copied into the code visitors download. Never put a secret in one.Public by design, or must it stay on a server?
A Stripe publishable key (starts with pk_)
Habit 2: never trust input
Anything a visitor types (a search, a form field, a web address) is input, and some visitors type nasty things. Two rules. Validate on the server: check that each field has the right type and length, and reject anything else. Checks in the browser help honest visitors fix typos, but anyone can skip them. Escape on output: when you show input back on a page, show it as text, never as code. If a search box writes <script> into the page as HTML, that script runs for anyone who opens the link. That attack is called cross-site scripting.
An agent wrote this for the archive search and an owner sign-in. Click the lines that are unsafe.
Habit 3: sign-in is a server's job
Authentication proves who someone is; authorization decides what they may do. Both must happen on a server, because anything in the browser can be read and changed. Don't build your own sign-in: use a proven provider, such as your builder's built-in auth or your database's auth service, and protect data with rules on the server, such as row-level security, which limits each user to the rows they're allowed to see. Then test the way a stranger would: sign out, open a private window, and try to reach the data.
Habit 4: be picky about packages
Every package your agent installs is code written by strangers, running in your app. Fewer is better. Check that each one is real and widely used. In a study presented at USENIX Security 2025, researchers generated 576,000 code samples with 16 models and found that, on average, at least 5.2% of the packages commercial models recommended didn't exist, and 21.7% of those from open-source models. Attackers can register those invented names (“slopsquatting”) and wait for someone to install them. Pin exact versions, run your package manager's audit (for npm, that's npm audit), and keep dependencies updated.
Habit 5: limit what the agent can reach
Agents can be tricked. Text in a web page, a GitHub issue or a package's README can contain instructions aimed at the agent that reads it; that's called prompt injection. It becomes dangerous when one agent has three things at once, a combination security researcher Simon Willison calls the lethal trifecta. Switch the legs on and off below.
Cut any one leg and an injected instruction has nothing to steal, or no way to send it anywhere.
Move the controls and watch what changes.
Your agent is about to read an unfamiliar package's web page while it can also see your .env file. Which change cuts the risk most?
The permission error
Your builder-made app has a sign-up form. After you switched on row-level security, saving a new sign-up fails with “permission denied.”
The agent suggests: “I'll turn off row-level security on the signups table so the form works again.”
Plain-English definitions from the AI Coding Dictionary.