Vibe coding 101: shipping fast without shipping CVEs
Vibe coding doesn't have to mean vibe security. Six principles for keeping the speed advantage without the disaster.
Vibe coding doesn't have to mean vibe security.
The argument about whether developers should be vibe-coding is over. They are. Every day. For production codebases. The interesting question now is how to keep the speed advantage without shipping a CVE in week two.
Here are the six principles that separate "moved fast and shipped" from "moved fast and got pwned." None of them slow you down meaningfully. All of them are cheap to start doing today.
1. Frame the assistant before you ask it anything.
The single highest-leverage move you can make. The assistant doesn't know what framework
you're on, which helpers handle your CSRF, or that $db is a UserSpice DB
object and not a raw PDO handle. It will guess — and the guess will be the average of every
PHP tutorial it has ever seen, which is not good.
Fix this with a CLAUDE.md at the project root (or whatever your assistant's
equivalent is). Three things go in it:
- What framework / stack you're on, by name and version.
- Which helpers it should reach for first — escaping, CSRF, SQL, redirects, hashing. Cite the function names.
- What it should not do — concrete anti-patterns. "Never call
md5for tokens, userandom_bytes." "Never echo a variable without escaping."
On UserSpice, this is what the AI Prompts plugin automates — it drops a folder of agent-readable docs into your project so the assistant reads the framework's conventions before it writes a line. On any other stack, write it yourself. A 200-line CLAUDE.md is the cheapest security upgrade you'll do this year.
2. Generate small things.
"Build me a SaaS product" is not a prompt. "Build me a contact form on this stack, posting
to parsers/contact.php, with CSRF and validation" is a prompt.
The bigger the chunk you ask for in one shot, the less of it you'll actually read, and the more it'll lean on training-data defaults to fill in the gaps you didn't specify. Small chunks let you review what came back. Reviewed chunks compound. Unreviewed chunks rot.
A rough heuristic: if the output is more than ~150 lines, the part of it past line 80 is almost certainly not getting a real look. Split it.
3. Read the diff like an adult.
Even if you don't understand every line, even if you don't speak the framework fluently — run your eyes over what the assistant wrote before you commit it. You're not trying to catch sophisticated bugs. You're trying to catch the dumb-obvious ones.
The dumb-obvious red flags, in roughly the order they appear in real code:
$_POST[...] // going into a query — uh oh "SELECT ... " . $var // string-concat SQL — almost always wrong header('Location: ' . // open redirect — usually wrong md5(uniqid()) // weak token — always wrong echo $row['anything'] // unescaped output — check the context $_COOKIE[unserialize] // unserialize on user data — code execution
Six patterns, ten seconds of grep per file, catches most of the actual bugs people ship. The 10 most common security holes in vibe-coded PHP has the full set if you want to print it on a sticky.
4. Audit before merge.
Pattern-matching by eye catches the obvious. An actual audit catches the rest. There are two ways to do this and you should do at least one:
Ask a fresh AI session to review what just got written. A new conversation, with the diff and a security checklist as the prompt. Different context window, different priors, different things noticed. This catches more than people expect; it's basically free.
Run an automated security checker. On UserSpice, this is
/userspice-audit — a Claude Code skill that walks the changed files against a
12-rule checklist and reports findings with file:line citations. On any stack, Semgrep with
a PHP rule pack does the equivalent and runs in under 30 seconds.
The audit step is what turns "code my assistant wrote" into "code I'm willing to put my name on."
5. Scan before deploy.
Auditing catches what your tools and your eyes notice during development. Scanning catches what got through anyway — including categories your tools don't model yet (CVEs in dependencies, leaked secrets in old commits, missing security headers on the deployed site).
The pre-deploy scan is non-negotiable for any project handling real user data. Free tools exist. They're fast. They run in Docker. There is no good excuse not to have one in your pipeline.
On UserSpice, the Security Scanner
bundles seven of them (Semgrep, Psalm, Trivy, Gitleaks, ZAP, PHPStan, headers) with
framework-aware rule packs into one bash entry point. Run it once locally to baseline.
Wire it into CI with --threshold high to gate merges.
6. Treat secrets like the loaded gun they are.
The #1 way a fast-built project ends up on a "leaked credentials" Twitter thread: someone pasted an API key into a chat window, the assistant put it in the source file, the file got committed, the repo went public.
Rules:
- Never paste a live key into a chat. Not even "just for testing." That conversation is logged somewhere.
- Env vars from day zero. Even if it's a side project. Even if it's "just running locally."
getenv('STRIPE_KEY')is one extra character of typing. - If a key has already touched a public mirror, rotate it. Don't "scrub the git history" and feel safe. The moment a key sits on a public remote, assume it's compromised — even if nobody noticed yet.
- Run a secrets scanner. Gitleaks. Once. Before your first push. It scans the working tree and the full history.
The TL;DR
Three minutes of setup (CLAUDE.md). Thirty seconds of reading per diff. One scan before deploy. One secrets check at the start.
That's it. That's the difference between "shipped fast" and "shipped fast and didn't regret it." Anyone who tells you keeping a vibe-coded project secure is some heavyweight enterprise process is selling enterprise process. It isn't.
The faster you start treating these as muscle memory, the more compounded the speed advantage gets. The slow part of building software has never been the typing. It's been the rework when something blows up two weeks after launch. Vibe code with discipline and you keep all the upside without the rework.