Course B · Module B1 Production · Lesson 9 of 18

Security Basics deep dive

A handful of silent mistakes account for most vibe-coded app breaches. Learn to spot them before you ship.

~18 min · Have your app and its environment variables open · Prereq: B5 API Keys, B6 Auth, B8 Payments

Security feels abstract until your database gets wiped, your API key runs up a $4,000 bill, or a stranger reads every customer's private data. The uncomfortable truth about AI-generated apps is that the AI writes functional code — but it rarely writes defensive code unprompted. It doesn't know that your database rules let anyone read everything, or that an API key is sitting in a public file. You have to check. Your single win: by the end you'll know the four silent vulnerabilities that catch vibe-coded apps most often, and you'll have a concrete pre-launch checklist to work through before your app goes live.

The four silent vulnerabilities

These four problems are "silent" because the app works perfectly in development — nothing crashes, no warning appears. The damage only shows up when someone finds and exploits them.

1 · Exposed API keys

An API key checked into a public GitHub repo, or hardcoded into client-side JavaScript, is visible to anyone — and bots scan GitHub constantly. Within minutes of a key appearing publicly, it can be used to rack up charges, send spam, or exfiltrate data in your name. See B5 for the right pattern: environment variables only, never in code.

2 · Database with no access rules

Most AI-scaffolded projects spin up a database where any authenticated — or worse, unauthenticated — request can read or write any row. Your customer's orders, messages, and profile data are visible to every other customer. Supabase calls these Row Level Security (RLS) policies; Firebase has Security Rules. They default to open. You must turn them on.

3 · Trusting user input blindly

When your app takes text from a user and passes it directly into a database query or an AI prompt without any checks, an attacker can craft input that does something completely different — deleting data, extracting records, or hijacking the AI's instructions. The fix is usually small: validate and sanitize input on the server side, and use your database library's parameterized queries instead of raw string concatenation. Ask your AI to review every place user input touches the database or an API call.

4 · Admin pages with no auth

It's common to build an admin panel quickly — a page to view all users, delete records, send test emails — and forget to protect it. If the route exists and isn't behind an auth check, it's publicly accessible to anyone who guesses or finds the URL. Check every internal route: does it verify that the requester is logged in and has the right role?

Think of your app as a building. Authentication (B6) is the front door lock. Database access rules are the internal doors — between the lobby and the server room, between one tenant's office and another's. An API key is the master key to the whole building. Trusting user input blindly is like a staff member who follows any instruction written on a sticky note, even one left by a stranger.

You can have a great front door and still be wide open inside. Security is layers, not a single lock.

Pre-launch security checklist

Work through this before every launch — or before sharing a URL publicly for the first time. It takes under an hour on a typical vibe-coded app and catches most of the common issues.

Pre-launch security checklist
  1. Grep your repo for secrets. Search the codebase for the words sk_, pk_, secret, password, api_key. If any of those appear as literal values in code files (not in .env), move them to environment variables immediately.
  2. Check your .gitignore. Confirm your .env file is listed there. Run git status and verify no .env file appears in the list of files to be committed.
  3. Review database access rules. If you're using Supabase, open the RLS section and confirm policies are enabled on every table that holds user data. If Firebase, read your Security Rules file. If you're not sure, ask your AI: "Show me the access rules on my database tables and tell me if any table is readable without authentication."
  4. List every route that takes user input. For each one, ask your AI: "Does this route sanitize input before using it in a database query or an API call? If not, fix it."
  5. List every admin or internal route. Visit each one while logged out. If you can see it, it needs an auth check.
  6. Check for overly permissive CORS. If your backend API accepts requests from any origin (*), tighten it to your specific frontend domain before going live.
  7. Verify error messages don't leak internals. Stack traces, database schema details, and file paths should never appear in responses visible to users. In production mode, show a generic error message and log the details privately.

When to ask an expert

The checklist above handles the most common issues. But some situations call for a real security review by a professional:

Handling paymentsIf you go beyond Stripe Checkout into custom card flows, have a security engineer review the implementation before going live.
Storing health or legal dataHIPAA, GDPR, and similar regulations carry fines and legal liability. An expert review is not optional if you're in these domains.
Before a meaningful fundraise or acquisitionInvestors and acquirers routinely run security due diligence. Getting ahead of it is far cheaper than fixing it under pressure.
Anything over ~1,000 usersAt low user counts, a breach is painful. At scale, it's existential. The cost of a one-day security audit is almost always worth it at this point.
Ask your AI to play attacker. Once your app is running, prompt it: "You are a security researcher. Review this codebase for vulnerabilities — focus on exposed secrets, unauthenticated routes, database access, and unsanitized user input. List every issue you find with its severity." It won't catch everything a human expert would, but it catches a surprising amount — and it's free.

Check yourself

Answer before opening — recalling it is what makes it stick.

Your Supabase database has a "profiles" table with user data. You haven't configured any RLS policies. Who can read it?

Anyone — including unauthenticated users. Supabase tables default to open when RLS is not enabled. Any request, authenticated or not, that knows the table name can read every row. Turn on RLS and define policies that restrict reads to the row's owner or to authenticated users with the right role.

A user submits a form with the value: '; DROP TABLE orders; --. What kind of attack is this, and what's the defence?

SQL injection. The attacker is trying to sneak a destructive database command inside your query by closing the intended string early. The defence is to use parameterized queries (your database library's built-in method of passing values separately from the query text) — the value is then treated as data, never as executable SQL.

You notice your API key for OpenAI has appeared in a public GitHub commit. What do you do first?

Revoke the key immediately in the OpenAI dashboard — before doing anything else. A key in a public repo is compromised the moment it lands there. Rotation is the only fix; git history rewrites don't help because bots cache commits in seconds. Then create a fresh key, store it in your environment variables, and add .env to .gitignore.

Read this next (primary source)

OWASP Top Ten — the security industry's canonical list of the most critical web application vulnerabilities, maintained by a nonprofit. You don't need to read every item in depth — scan the category names and descriptions. You'll recognise several from this lesson. It's the same list professional security engineers use as their baseline. See RESOURCES.md for more.

I'm your teacher — paste me your checklist results. Work through the seven-point checklist above, then tell me what you found: which items you're confident about, which feel unclear, and any issues the AI audit surfaced. I'll help you prioritise and fix before you go live.

New terms this lesson — SQL injection, Row Level Security, CORS, parameterized query, OWASP — are in the course glossary. Keep it open.