Run a Security Pass Before Real Users
A project-based journey: inventory your attack surface, close the failures AI code ships by default, add scanning to CI, and rotate what may have leaked.
A documented attack-surface inventory, every default AI security failure checked off or fixed, scanning in CI, and rotating credentials issued.
A working app with accounts and data you would not want public, and Git history you can act on.
Any web stack. Examples assume Git, a CI provider, and a server-rendered or API app.
The project
Go through one app the way an attacker would, in the order an attacker would, and close what you find. This is not a theoretical review; the goals are concrete: no leaked secrets, no cross-account access, no injection, no unverified dependencies.
By the end you will have: an attack-surface inventory, a checked-off list of the default generated-code failures, scanning that runs on every push, and every credential that might have leaked rotated.
Before you start
- The app deployed and reachable, ideally with accounts.
- Access to its Git history, CI, and hosting dashboards.
- The 15 Security Failures Your AI Coding Assistant Ships by Default open — it is the checklist underneath this journey, and InfoSec for Vibecoders is the hub.
- How to Think Like an Owner When AI Writes the Code — the mindset that keeps security decisions with the person accepting the generated code.
Work in the order below. Attackers start with secrets and access control because those give the widest access for the least effort, and so should you.
Milestone — Write down what you are protecting
Build: an inventory of entry points, data, credentials, and third parties.
You cannot defend a surface you have not described. Twenty minutes of inventory removes most of the “I forgot that endpoint existed” surprises.
Do it
- Ask your agent to enumerate every route, webhook, and background job, and mark each as public, authenticated, or admin.
- List the sensitive data: credentials, personal data, payment identifiers, API tokens.
- List every secret the app uses, where it lives, and who can read it.
Done when the inventory has no blanks and every credential has an owner. What Is a Non-Human Identity? explains why the machine credentials on that list matter as much as the human ones.
Milestone — Assume your secrets leaked, then rotate them
Build: no secrets in the repo, and every previously committed one reissued.
Generated projects leak keys constantly — in .env, in source, in frontend bundles. Assume every secret that ever touched the repo is compromised.
Do it
- Scan the whole history, not just the current tree, with a secret scanner.
- Rotate every key the scanner finds — deleting from Git does not un-leak it.
- Move live values into the platform’s secret store and keep only a
.env.examplein the repo.
Done when a history scan is clean and the rotated keys work in production. Follow How to Scan Your Codebase for Hardcoded Secrets and How to Find and Remove Secrets From Git History, then How to Manage Secrets and Environment Variables Properly. If you have many keys, How to Automate API Key Rotation makes it routine.
Milestone — Break your own access control
Build: a two-account test that proves data isolation for reads, updates, and deletes.
This is the highest-severity bug in generated apps and the fastest one to test. Do it early, because it often changes what the rest of the work looks like.
Do it
- Create two accounts. As account B, create a record and note its id.
- As account A, request that id directly for a read, an update, and a delete.
- Repeat for any admin-only endpoint, with a non-admin token.
Done when every cross-account attempt fails, and the ownership filter is in the query, not a guard after it. What Is Broken Access Control (IDOR)? and How to Test Your App for Broken Access Control are the guides.
Milestone — Close the injection gaps
Build: parameterised queries, escaped output, validated paths, and an allow-list for outbound requests.
Four injection classes account for most generated-code vulnerabilities. Each has a specific fix, and each has a test you can run now.
Do it
- SQL: confirm every query is parameterised, not string-concatenated — SQL Injection and AI-Generated Code.
- Path traversal: check any file-serving endpoint for
../escapes — Path Traversal in AI-Generated Code. - SSRF: for any endpoint that fetches a user-supplied URL, allow-list hosts and block internal addresses — What Is SSRF?.
- CSRF: confirm state-changing requests are protected by tokens or a strict SameSite cookie — What Is CSRF?.
Done when each of the four has been attempted against your app and failed. What Is the OWASP Top 10? is the map of the wider category list.
Milestone — Check what is exposed to the browser
Build: an audit of everything shipped to the client, plus the response headers.
Anything in frontend JavaScript is public, and missing headers leave easy attacks open. Both are quick to verify and quick to fix.
Do it
- Read the built frontend bundle and list every key or endpoint in it.
- Move anything sensitive behind a server-side proxy — see Why Your Frontend API Keys Are Not Secret.
- Add the standard headers, including HSTS and a content security policy.
Done when the bundle contains no secret, and a header check shows HSTS, a CSP, and the rest. What Are Security Headers (and How Do You Add Them)?, What Is HSTS?, and What Is Content Security Policy (CSP)? cover each.
Milestone — Audit your dependencies
Build: a dependency scan, a lockfile, and a check against hallucinated packages.
Generated code installs packages the model half-remembers. Some of those names belong to nobody — until someone registers them.
Do it
- Commit a lockfile so installs are deterministic.
- Run a dependency vulnerability scan and triage the critical findings.
- For each package your assistant added, confirm the name, publisher, and download count match a real project.
Done when the lockfile is committed and no dependency is an unverified name. What Is Slopsquatting? and What Is a Software Supply Chain Attack? explain the risk.
Milestone — Make scanning automatic
Build: secret, dependency, and static analysis running on every pull request.
A manual pass decays the moment you generate the next feature. Put the checks in CI so the app fails closed.
Do it
- Add secret scanning, dependency scanning, and SAST to the pipeline.
- Configure it to block on critical findings.
- Open a pull request with an intentionally insecure line and confirm it is blocked.
Done when a vulnerable PR cannot merge. Follow How to Add SAST Scanning to a GitHub Repo, How to Add Security Scanning to Your CI/CD Pipeline, and What Is Static Application Security Testing (SAST)?.
Ship checklist
- Attack surface inventoried: routes, data, credentials, third parties.
- Git history scanned; every found secret rotated, not just deleted.
- Two-account test passes for reads, updates, and deletes.
- Queries parameterised; file paths and outbound URLs validated.
- CSRF protection on state-changing requests.
- Frontend bundle contains no secrets; security headers present.
- Lockfile committed; dependencies verified against real packages.
- Secret, dependency, and SAST scanning block bad merges in CI.
- You can describe how you would revoke a leaked credential in five minutes.
Where this journey goes wrong
- Deleting a secret without rotating it. The key still works for anyone who copied it.
- Trusting a hidden button. Access control lives on the server, not in the UI.
- Fixing the symptom endpoint. Injection is a pattern, so grep for the whole class.
- Adding headers without testing. A broken CSP can take the site down; verify.
- Treating this as a one-time pass. New generated code reintroduces old defects; the CI gate is what makes it stick.
FAQ
Is this a penetration test?
No — this is the work that makes a pentest worth paying for. It removes the known, default failures in generated code. A pentest finds the clever app-specific weaknesses; it is largely wasted on an app that still ships SQL injection and missing ownership checks.
My app has no users yet. Why start now?
Because these failures are cheap to fix before there is data to lose and expensive after an incident. Secrets still need rotating, ownership checks still need adding, and the gap between “no users” and “real users” is usually much shorter than planned.
Related guides
- Authentication for AI Builders — if the auth layer itself needs review.
- What Is Zero Trust? — the mindset behind least privilege.
- How to Think Like an Owner When AI Writes the Code — why the human must own the risk decision even when AI wrote the implementation.
- What the Moltbook Breach Teaches About Shipping Vibecoded Apps — what skipping this journey looks like in the news.
- Journey: Add Accounts and Login to Your App — the auth work this assumes.
- Journey: Add an AI Feature Without Adding an Attack Surface — the extra surface once your app calls a model.