The Vibe Coding Security Checklist (20 Points)
>This covers the 20-point security audit. Claude Code for Beginners walks you through building, polishing, and shipping a complete app in 48 hours, including this security hardening step.

Summary:
- AI code tools write functional code, not secure code. Five vulnerability types appear in nearly every vibe-coded project.
- Full 20-point security checklist organized by category: Authentication, Input Validation, Data Access, Infrastructure.
- Copy-paste grep commands that find hardcoded secrets in 30 seconds.
- The XSS test you can run right now to see if your app is vulnerable.
A Reddit post titled “Why the majority of vibe coded projects fail” hit 7,600 upvotes and 690 comments on r/ClaudeAI. The top-voted responses weren’t about bugs or UX. They were about security. One commenter put it bluntly: “A vibe coded product using sensitive info like bank details is asking for a security breach that will get your ass sued.”
That post didn’t go viral because security is abstract. It went viral because 7,600 people recognized themselves. They’d shipped AI-generated code without checking it. They’d seen the gaps after the fact.
This checklist exists so you check before shipping. It’s practical security hygiene, not enterprise security engineering. Ten minutes, twenty checks, and you’ll know exactly where the gaps are.
Where does AI-generated code actually leak data?
Five places. The same five, every single project. AI code tools optimize for “does it work?” They do not optimize for “is it safe?” That gap creates the same vulnerabilities on repeat.
1. Authentication that looks right but isn’t. Sessions work. Logins work. But session tokens might be in regular cookies instead of httpOnly cookies (JavaScript can steal them). The auth secret might be a placeholder value. There’s no rate limiting on login, so an attacker can try a thousand passwords per second.
2. Input validation that doesn’t exist. The form accepts whatever the user types. The database stores it. The page renders it. No sanitization, no length limits, no server-side checks.
3. Database queries that trust user input. Insecure Direct Object References (IDOR) are the most common variant. If your API fetches a record by ID without checking ownership, anyone who guesses the ID can read someone else’s data. Raw SQL without parameterized inputs is the other variant.
4. Environment variables that aren’t environment variables. API keys, database URLs, auth secrets sitting in source code instead of .env files. Or worse, .env files that were committed to git history.
5. Dependencies with known vulnerabilities. Your node_modules has hundreds of packages. Some have published CVEs. npm audit checks all of them against a vulnerability database in five seconds.
How do you test for XSS right now?
Open your app. Find any text input field. Type this as the value:
<script>alert('hacked')</script>
Submit the form. If you see an alert box pop up, your app has a cross-site scripting vulnerability. Anyone can inject JavaScript through your input fields.
If the text renders as plain text on the page (you see the literal <script> tag as characters, not as executed code), your inputs are sanitized. You pass this check.
This takes ten seconds. It catches the single most common vulnerability in AI-generated frontend code. If your app fails this test, every other input field is suspect too.
What’s the full 20-point checklist?
Run this on every project before real users touch it. Each item gets a PASS, FAIL, or N/A.
Authentication (5 points)
| # | Check | What to look for |
|---|---|---|
| 1 | Passwords hashed | bcrypt or argon2, never plain text storage |
| 2 | Session tokens in httpOnly cookies | Not accessible by client-side JavaScript |
| 3 | Auth secret is real | Random value, not a placeholder like “secret123” |
| 4 | Login rate limiting | Max 5 attempts per minute per IP |
| 5 | Password reset tokens expire | Within 1 hour of issuance |
Input Validation (5 points)
| # | Check | What to look for |
|---|---|---|
| 6 | Server-side validation on all inputs | Client-side alone is not security |
| 7 | HTML sanitized from text inputs | Prevents XSS (run the script tag test) |
| 8 | Input lengths limited | Prevents memory exhaustion attacks |
| 9 | File uploads validated | Type and size checked, if applicable |
| 10 | Unexpected API parameters rejected | Endpoints don’t silently accept extra fields |
Data Access (5 points)
| # | Check | What to look for |
|---|---|---|
| 11 | Every query includes userId check | No fetching records by ID alone |
| 12 | No raw SQL, or parameterized inputs | Prisma/ORM queries preferred |
| 13 | API responses don’t leak sensitive data | No password hashes in JSON responses |
| 14 | Admin endpoints require role verification | If applicable |
| 15 | Deleted data is actually deleted | Not just hidden with a soft-delete flag |
Infrastructure (5 points)
| # | Check | What to look for |
|---|---|---|
| 16 | .env in .gitignore | Never committed to git |
| 17 | No hardcoded secrets in source | Use the grep commands below |
| 18 | npm audit shows zero high/critical | Run weekly |
| 19 | HTTPS enforced | Vercel/Netlify handle this automatically |
| 20 | CORS configured | Allow only your domain, block all other origins |
Score: 20/20 is a solid baseline to ship with confidence. Anything less means fix the failures before real users touch it.
How do you find hardcoded secrets in 30 seconds?
Three commands. Copy them, run them, read the output.
# Find hardcoded secrets in source files
grep -r "sk_\|pk_\|password=\|secret=" src/ --include="*.ts" --include="*.tsx"
# Check if .env was ever committed to git history
git log --all -- .env .env.local .env.production
# Find API keys or tokens in any file
grep -rn "Bearer \|apiKey\|API_KEY" src/
If any of those return results, you have secrets in your source code. Here’s the full cycle: I ran the first grep on a project and found password="admin123" in a seed file and sk_test_abc123 in a Stripe integration file. Both were placeholders Claude created during setup that never got moved to .env. Fix: moved both values to .env.local, replaced the hardcoded strings with process.env.DB_SEED_PASSWORD and process.env.STRIPE_SECRET_KEY, and added .env* to .gitignore. Two minutes. Two critical vulnerabilities closed.
The git log command is the one people miss. Your .env file might be in .gitignore now, but if it was ever committed, the secrets are in your git history. Anyone who clones the repo can see them. If you pushed to a public repo with secrets in history, those secrets are compromised. Generate new ones.
How does AI code security compare to manual code security?
The vulnerabilities are the same. The difference is frequency.
| Vulnerability | Hand-written code | AI-generated code | Why the gap |
|---|---|---|---|
| Missing input validation | Common | Nearly universal | AI skips validation unless prompted |
| Hardcoded secrets | Occasional | Frequent | AI uses placeholder values during setup |
| IDOR (broken access control) | Common | Very common | AI fetches by ID without ownership checks |
| Outdated dependencies | Varies | Same | Both depend on npm audit discipline |
| XSS | Declining (frameworks help) | Common | AI sometimes bypasses framework protections |
| SQL injection | Rare (ORMs help) | Rare | Both benefit from parameterized queries |
| Missing rate limiting | Common | Nearly universal | AI never adds rate limiting unprompted |
| Weak session handling | Occasional | Frequent | AI defaults to basic cookie settings |
The pattern is clear: same vulnerability types, higher frequency. A human developer might forget rate limiting. An AI tool will never add it unless you ask. That one difference turns “common” into “nearly universal” across three of the eight categories.
How do you fix the five most common failures?
Each fix is a single prompt to your AI code tool.
Missing input validation (checklist items 6-10):
Add server-side input validation to all API endpoints and server
actions. Sanitize HTML from all text inputs. Limit titles to 200
characters, descriptions to 2000 characters. Return clear error
messages for invalid input. Validate on the server, not just
the client.
Broken access control (checklist item 11):
Verify that every database query that fetches user data also
checks that the record belongs to the authenticated user. If
any query fetches by ID alone without a userId check, add the
check. Show me every query you changed.
Hardcoded secrets (checklist items 16-17):
Search the entire codebase for hardcoded API keys, database
URLs, auth secrets, and tokens. Move all of them to environment
variables. Ensure .env is in .gitignore. Show me what you found
and where you moved it.
Missing rate limiting (checklist item 4):
Add rate limiting to all API endpoints and server actions.
Max 5 attempts per minute per IP for login. Max 30 requests
per minute per user for write operations. Max 60 per minute
for reads.
Dependency vulnerabilities (checklist item 18):
npm audit
# Then tell your AI tool:
# "Run npm audit and fix any vulnerabilities. For vulnerabilities
# that can't be auto-fixed, tell me what they are and the risk level."
How should you test AI-generated code?
Start with integration tests, not unit tests. AI generates complete features, not individual functions. Your most valuable test verifies the whole path: create a record, confirm it appears, change its status, confirm the update.
Use a real test database, not mocks. Mocked tests confirm your code calls the right functions. Integration tests with a real database confirm data actually saves and retrieves correctly. I’ve seen AI-generated code pass all mocked tests and fail with a real database because the migration was wrong.
How many tests: 20-25 total for a standard CRUD app.
- 3-4 per CRUD operation (create, read, update, delete)
- 1-2 per auth scenario (login success, login failure, unauthenticated access)
- 1 per input validation rule (max length, required fields, sanitization)
The test suite should run in under 10 seconds. You don’t need 100% coverage. You need 100% confidence that the critical paths work.
What should you actually do?
- If you haven’t run ANY security check: start with the three grep commands and the XSS test. Five minutes, and you’ll know whether you have urgent problems.
- If you’re about to deploy: run the full 20-point checklist. Copy the prompts above to fix every FAIL. The audit takes ten minutes. The fixes take another ten.
- If you’re already live with users: run
npm auditfirst (dependency vulnerabilities are the fastest to exploit remotely), then the grep commands (hardcoded secrets are the most damaging), then the full checklist. - If you want ongoing protection: run
npm auditweekly. Re-run the 20-point checklist after every major feature. Add integration tests that double as security tests (a test for “unauthenticated user gets 401” is also an auth security test).
bottom_line
- AI code tools write code that works. They do not write code that’s secure. Five vulnerability types appear in nearly every vibe-coded project: missing validation, broken access control, hardcoded secrets, no rate limiting, and weak session handling.
- The 20-point checklist catches all five. Run it before any real user touches your app. Aim for 20/20 as your shipping baseline.
- Three grep commands find hardcoded secrets in 30 seconds. One XSS test in any input field tells you if validation exists. These two checks alone catch the majority of critical vulnerabilities in AI-generated code.
Frequently Asked Questions
Is AI-generated code safe to deploy without a security review?+
No. AI code tools optimize for 'does it work,' not 'is it safe.' They skip input validation, hardcode secrets, and leave auth gaps unless you explicitly ask. A 20-point audit catches the five most common vulnerability types.
How long does a vibe coding security audit take?+
About ten minutes per project. Run the grep commands to find hardcoded secrets, test XSS with a script tag in any input field, and walk through the 20-point checklist. Most fixes are one-line changes.
What's the most common security flaw in vibe-coded apps?+
Missing input validation. AI tools rarely add server-side validation unless you ask for it. Forms accept anything, databases store anything, pages render anything. One XSS test exposes the gap in seconds.
More from this Book
5 Claude Code Mistakes Every Beginner Makes
Five mistakes that waste hours in Claude Code and the fix for each. Includes before/after prompts, a CLAUDE.md template, and the 3-line prompt formula.
from: Claude Code for Beginners
How to Use Claude Code Dispatch and Remote Control
Reference guide to Claude Code's power features: dispatch, remote control, channels, and LSP. Includes the adoption timeline and dispatch planning method.
from: Claude Code for Beginners
How to Cut Your Claude Code Bill in Half
Six token sinks that drain your Claude Code budget and the exact fix for each. Real cost math for every subscription tier plus a copy-paste effort function.
from: Claude Code for Beginners
How to Fix Ugly AI-Generated UIs with Claude Code
The screenshot verification loop that fixes ugly AI-generated UIs in Claude Code. Four steps, three rounds, eight minutes to a UI that doesn't embarrass you.
from: Claude Code for Beginners