"It runs" is not "it ships"
AI-generated code has one defining property: it almost always runs. That is precisely the problem — running masks everything, so there's no signal telling you to look twice.
Veracode's 2025 analysis put the security-defect density of AI-generated code at roughly 2.74× that of comparable human-written code. Not an outrageous multiple — but the volume of AI-generated code is growing fast, so the absolute count is not small.
You don't need to be a security specialist. The checks below take about twenty minutes and catch most real incidents.
1. Are secrets hardcoded in the frontend?
The most frequent, most immediately damaging category.
// If this line ships in a file the browser can load, the key is already public
const client = new SomeAPI({ apiKey: "sk-live-xxxxxxxx" });
How to check: grep the project for sk-, api_key, secret, password, token, and confirm each hit lives in a server file, not a client component.
Next.js projects deserve extra care: anything prefixed NEXT_PUBLIC_ is compiled into the client bundle, no matter how private you wanted it.
2. Is there actually a backend?
Most AI builders emit a frontend shell. The form appears to submit; nothing is persisted.
How to check: submit once, then look in the database or inbox and confirm it arrived. Don't trust the success toast — it's frequently hardcoded.
3. Where is authorisation enforced?
The easiest one to miss, because it's invisible in the interface.
// Hiding the button is not access control
{user.isAdmin && <DeleteButton />}
The button is hidden; the endpoint is not. Anyone calling it directly can delete data.
How to check: for every "admins only" action, open the corresponding server route and confirm it checks identity and permission there too. Hiding UI is a visual suggestion, not a control.
4. How is user input handled?
- Is input validated on the server? (Client validation is UX, not security.)
- Is user-submitted content rendered back as HTML anywhere?
- Are database queries parameterised rather than string-concatenated?
5. Do the dependencies exist?
AI imports packages that were never published. Worse, attackers now register those hallucinated names on purpose.
How to check: watch for install errors, and for unfamiliar packages check weekly downloads and last publish date on npm. Very low downloads plus a recent first publish deserves suspicion.
6. Performance low-hanging fruit
Generated code tends to be heavy. Skip deep optimisation; check three things:
- Images — is a 4MB original sitting in the hero?
- Bundle weight — the whole of moment.js for one date format?
- Request count — open the Network panel and see whether the first paint costs dozens of requests or hundreds
Run Lighthouse; it will point straight at the biggest offender.
7. Error handling
AI writes the happy path.
- What does the user see when a request fails?
- Is an empty dataset a blank page or a message?
- Do server errors leak internal details into the UI?
How to check: disconnect from the network and walk through the site.
The twenty-minute checklist
[ ] Grep for secrets; none in client code
[ ] Submit a form; confirm the data actually lands
[ ] Admin-only server routes enforce permission
[ ] User input is validated server-side
[ ] Every dependency exists on npm with credible download numbers
[ ] Lighthouse run; performance and accessibility reviewed
[ ] Offline walkthrough; error states are handled
One sentence
You published it, you own it. "The AI wrote it" is not a defence — not to your users, not to your client, not to a regulator.
Prompts on MotionSites pin the stack and the dependency list explicitly, which cuts down both hallucinated packages and leaked keys.