OWASP TOP 10 FOR AI-GENERATED CODE: SECURITY RISKS & FIXES (2026)
OWASP risks mapped to how AI coding tools actually fail: broken access control, injection, crypto failures, and security misconfiguration in generated apps.
Why OWASP Matters for AI-Generated Code
The OWASP Top 10 is the standard classification of web application security risks. AI code generators are trained on vast codebases that include both secure and insecure patterns. When generating code, they optimize for functionality – not security. The result is code that works perfectly in development but ships with well-known vulnerabilities.
Research from Stanford and NYU found that developers using AI assistants produce significantly less secure code than those writing manually. The problem is not that AI writes uniquely bad code – it writes the same insecure patterns that human developers have written for decades, but faster and at greater scale. OWASP provides the framework to systematically identify and fix these issues.
Use this page as a priority map, not a trivia list. In AI-generated apps, A01 and A05 dominate real incidents; A03 still appears whenever SQL or HTML is string-built; A02 shows up as keys in the bundle. Agents and multi-file tools increase volume; they do not invent a parallel taxonomy. Mapping findings to OWASP also helps you talk to auditors and security reviewers who already think in these categories.
If you only remember one thing: AI multiplies classic web risk density. Your control strategy is still authz, secrets hygiene, safe defaults, and verification on the live URL — just applied more often, after every generative session.
A01: Broken Access Control in AI Code
Broken access control is the number one OWASP risk, and it is the most common vulnerability in AI-generated applications. AI tools generate routes, API endpoints, and database queries without proper authorization checks. Specific patterns include:
- Missing auth middleware – Express routes or Next.js API handlers with no session verification. Anyone with the URL can access protected data.
- No RLS policies – Supabase tables created without Row Level Security. The anon_key grants full read/write access to all rows.
- Open admin panels – Admin routes protected only by frontend conditional rendering, not server-side role checks. Navigating directly to /admin bypasses the “protection.”
- IDOR / BOLA vulnerabilities – API endpoints that accept a user ID parameter without verifying the authenticated user owns that resource.
- Mass assignment – clients set
isAdmin,role, orbalancebecause the handler saves the whole body. - Entity permissions left at
authorpublicon Base44-style platforms whenownerwas required.
Fix: every endpoint verifies identity and authorization before returning data. In Supabase apps, RLS on every table. In API apps, auth middleware plus ownership checks. Test with two users. See BOLA in AI-generated CRUD and mass assignment.
// Minimal ownership gate
const row = await db.item.findUnique({ where: { id } });
if (!row || row.ownerId !== session.userId) return res.status(403).end();
-- Supabase: enable RLS and scope rows
alter table public.projects enable row level security;
create policy "owner_all" on public.projects
for all using (auth.uid() = owner_id)
with check (auth.uid() = owner_id);
AI-specific note: models often implement “is the user logged in?” and stop. Ownership is a second sentence in the task prompt — add it deliberately.
A02: Cryptographic Failures
AI tools routinely generate code with cryptographic weaknesses. These are not exotic attacks – they are basic failures that automated scanners catch immediately:
- Hardcoded secrets – API keys, database URLs, and JWT secrets embedded directly in source files or frontend bundles.
- Weak hashing – MD5 or SHA-256 for passwords instead of bcrypt, scrypt, or Argon2.
- No HTTPS enforcement – missing HSTS / redirects; mixed content calling APIs over HTTP.
- Insecure randomness –
Math.random()for session tokens or reset codes. - JWT
alg: noneor weak secrets – custom auth from a prompt (JWT patterns). - Homegrown encryption — rolling AES wrappers instead of platform KMS / libsodium defaults.
Fix: env vars and secret managers; bcrypt/Argon2; HTTPS at the edge; crypto.getRandomValues / crypto.randomUUID; prefer maintained auth libraries. Scan with Token Leak Checker.
import { randomBytes, scryptSync, timingSafeEqual } from "node:crypto";
function hashPassword(password: string) {
const salt = randomBytes(16);
const hash = scryptSync(password, salt, 64);
return `${salt.toString("hex")}:${hash.toString("hex")}`;
}
Never accept completions that “simplify” password storage to a single SHA-256 hex string.
A03: Injection
Injection vulnerabilities remain common in AI-generated code despite decades of awareness:
- SQL injection – string concatenation in queries.
- NoSQL injection – Mongo operators from user JSON.
- XSS –
dangerouslySetInnerHTML, unescaped templates, LLM HTML rendered raw (LLM-rendered HTML). - Command injection –
exec/os.systemwith user paths. - Prompt injection into agent tools (browser, shell) when untrusted content is loaded (indirect prompt injection).
- Template injection in server-rendered strings built from user fields.
Fix: parameterized queries; schema validation (Zod); framework escaping; never shell out on user input; sanitize or don’t render HTML from models.
-- bad: '... where id = ${id}'
-- good:
select * from users where id = $1;
// bad
exec(`convert ${userPath} out.png`);
// good: allowlist basename, spawn without shell
AI-specific note: concatenation is over-represented in training data “quick examples.” Your rules and review should treat any `...${user}...` in a query or shell as a review blocker.
A04: Insecure Design
AI optimizes for the demo path. Insecure design is choosing an architecture that cannot be safe without heroics:
- Client-only “security” (hiding buttons, relying on obscurity).
- Trusting the client for prices, roles, or discount codes.
- Long-lived magic links without binding to device/session.
- Multi-tenant apps with only
user_idfilters in the app layer and a shared DB role that can read all rows. - Using Memberships / static gates for truly sensitive documents (Webflow soft-gate problem).
- “Security later” TODOs left in production because the agent marked the feature done.
Fix: threat-model the feature before prompting; put enforcement in the server/policy layer; assume every client input is hostile. Write non-goals into agent tasks: “Do not implement security only in the React layer.”
A short design gate before large prompts:
- What is the trust boundary? (browser vs server vs third party)
- Who can read/write each object?
- What happens if the client lies about price/role/id?
- Where do secrets live?
If you cannot answer, do not generate the feature yet.
A05: Security Misconfiguration
The dominant ops failure for AI deploys:
- Default Firebase test-mode rules; Supabase RLS off.
- CORS
*; open storage buckets; debug routes in prod. - Verbose errors and public source maps.
- Preview environments with production secrets (Vercel, Netlify).
- Missing security headers (Security Headers Checker).
- Public DB proxies (Railway, Neon).
NODE_ENV=developmentleft on hosted templates.- Open Graph / reverse-proxy rewrites that become open redirects.
Fix: infrastructure-as-code for rules; deny-by-default; separate env scopes; checklist per host; automated config probes on the live URL.
// Example: explicit security headers (Vercel / similar)
{
"headers": [{
"source": "/(.*)",
"headers": [
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
]
}]
}
Misconfiguration is where “the code looks fine in git” and production is still open — runtime scanning is mandatory.
A06: Vulnerable and Outdated Components
AI pastes dependency versions from training data and invents package names:
- Old Express/Next with known CVEs.
- Hallucinated packages pre-registered by attackers (Package Hallucination Scanner).
- Copy-pasted GitHub Gists as “utils.”
- Transitive deps pulled by “just add this helper package.”
- Unpinned
latesttags in Dockerfiles generated by agents.
Fix: npm audit / Dependabot / Snyk; pin versions; verify new packages on the registry; prefer standard libraries over novel helpers from chat.
npm audit --audit-level=high
npm view some-package time # does it even exist / when published?
Treat every agent-suggested dependency as untrusted until the registry and lockfile say otherwise.
A07: Identification & Authentication Failures
AI-generated authentication systems frequently have implementation flaws:
- Weak session management – no expiry; tokens in
localStorage. - Missing MFA unless prompted.
- Insecure password reset – eternal tokens; user enumeration.
- No brute force protection on
/loginand/auth/v1/token. - Disabled email verification and no leaked password protection.
- OAuth redirect URI wildcards or leftover tunnel URLs.
- JWT verification that trusts
algfrom the token header.
Fix: use Supabase Auth, Auth.js, Clerk, etc.; httpOnly cookies; rate limits; email confirm; HIBP checks; MFA for admin. Prefer not to invent auth from a single chat thread.
// Cookie-oriented sessions beat localStorage for XSS resilience
// (still fix XSS — cookies are not magic)
res.setHeader(
"Set-Cookie",
`session=${token}; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=604800`,
);
Test full flows: sign-up → verify → login → logout → reset → login again. See auth flows.
A08: Software and Data Integrity Failures
- Unverified webhooks marking orders paid (Stripe webhook pattern).
- Auto-updating agent skills / MCP servers without review.
- CI that deploys from PRs without review (poisoned pipelines — poisoned CI pattern).
- Unsigned software updates or fetch-and-eval of remote code.
- Trusting client-reported “paid” flags without server verification.
- MCP / tool plugins that execute with the developer’s full credentials.
Fix: verify signatures; lock MCP/skill sources; required reviews on main; no curl | sh in prod paths.
// Stripe: never trust raw body without constructEvent
const event = stripe.webhooks.constructEvent(
rawBody,
signature,
process.env.STRIPE_WEBHOOK_SECRET!,
);
Integrity failures often look like “business logic bugs” until the first fraudulent order.
A09: Security Logging & Monitoring Failures
AI almost never adds useful security telemetry:
- No audit logs for authz failures or admin actions.
console.logof full requests including tokens.- Stack traces to clients; silence on the server.
- No alerts on stuffing, 500 spikes, or anomalous exports.
- Preview and prod logs mixed without retention policy.
Fix: structured logs for auth events; redaction; centralize (Axiom, Datadog, Sentry); alert on thresholds; retain enough for incident response.
Log at least:
- Failed logins (with rate and IP)
- Authorization denials on sensitive objects
- Admin mutations
- Webhook verification failures
- Secret access errors (without logging the secret)
If you cannot detect a credential-stuffing burst, you do not operate the app — you host it.
A10: Server-Side Request Forgery (SSRF)
Common when AI adds “fetch this URL” features, link previews, or webhook testers:
- User-supplied URL fetched by the server → hits metadata
169.254.169.254or internal 6PN hosts. - Open proxy redirects on Netlify/Vercel rewrites.
- PDF/image converters that retrieve attacker URLs.
- “Import from URL” CMS features on marketing sites.
Fix: allowlist schemes/hosts; block link-local and private ranges; no user-controlled hosts in reverse proxies; network egress policies.
import { URL } from "node:url";
function assertSafeUrl(raw: string) {
const u = new URL(raw);
if (u.protocol !== "https:") throw new Error("https only");
// block localhost, RFC1918, link-local — use a maintained library in production
if (u.hostname === "localhost" || u.hostname.endsWith(".internal")) {
throw new Error("blocked host");
}
return u;
}
See SSRF / open redirect / OAuth.
How to Audit AI Code Against OWASP
A practical approach to auditing AI-generated code for OWASP compliance:
- Run automated SAST – Semgrep OWASP rulesets, secret scanners (gitleaks).
- Check every route – auth + authorization; no exceptions.
- Search for secrets – git history + deployed bundle.
- Test database access – anon key against every table (Supabase/Firebase rules).
- Verify input validation – malformed bodies on every write.
- Review auth flows – reset, session expiry, role escalation.
- Probe live deploy – Vibe Code Scanner for runtime gaps SAST misses.
- Confirm logging – failed login and 403s visible somewhere you watch.
- Review webhooks and SSRF features – signed webhooks; allowlisted fetches.
- Re-run after every agent feature – AI velocity makes one-time audits stale within a week.
Automated scanning catches roughly half of issues. Logic and access control need human or agentic dynamic tests.
Per-PR OWASP tick map
| If the PR touches… | Check categories |
|---|---|
| New CRUD / tables | A01, A03, A04 |
| Auth / sessions | A07, A02, A01 |
| Payments / webhooks | A08, A01, A04 |
| File upload / URL fetch | A03, A10, A05 |
| Dependencies | A06 |
| Hosting / env / CORS | A05, A02 |
| Admin / roles | A01, A04, A09 |
Print this table in your PR template for agent-authored work.
Priority matrix for vibe-coded apps
| Priority | Categories | Typical AI failure |
|---|---|---|
| P0 | A01, A02, A05 | Open DB / leaked keys / open preview |
| P1 | A03, A07 | SQLi/XSS, weak auth |
| P2 | A04, A08, A10 | Bad design, webhooks, SSRF |
| P3 | A06, A09 | Deps and logging debt |
Ship blockers: any P0 finding on a production URL with real users. P1 before public launch if you handle accounts. P2/P3 on a scheduled backlog with owners — do not pretend logging debt will self-heal.
Tooling mapped to categories
| Control | Helps most with |
|---|---|
| ESLint security / Semgrep | A03, parts of A02/A07 |
| Secret scanners + Token Leak Checker | A02 |
| npm audit / Snyk / Dependabot | A06 |
| Two-account manual or agent DAST | A01 |
| Host checklists (Vercel/Railway/…) | A05 |
| Webhook signature tests | A08 |
| Centralized logging product | A09 |
| URL allowlist libraries + egress policy | A10 |
No single tool covers the Top 10. Compose a thin pipeline and re-run it after generative sessions.
Related Resources
AI Code Vulnerability Taxonomy
Complete classification of vulnerabilities in AI code
Secure AI Coding Practices
Prompts and practices for secure code generation
AI Code Review Guide
Framework for reviewing AI-generated code
SAST Tools for AI Code
Static tooling that complements this map
Vibe Coding Security Risks
Catalogue of failure modes across tools
Agentic Code Review Guide
How to review large agent diffs against these risks
Example mapping: one Lovable app → full Top 10
Imagine a generated SaaS with Supabase, Stripe, and an AI summary button:
| Symptom on the live app | Category |
|---|---|
Anon reads invoices |
A01 |
sk_live in JS |
A02 |
| Markdown render XSS in notes | A03 |
Client-sent price trusted |
A04 |
CORS * + cookies |
A05 |
| Hallucinated npm package | A06 |
| Unlimited login attempts | A07 |
| Stripe webhook no signature | A08 |
| No auth failure logs | A09 |
| “Fetch URL for summary” SSRF | A10 |
Use this table in design reviews before the feature ships, not after the incident channel lights up.
Secure-by-default prompts that still need verification
Even with rules files that say “always use parameterized SQL,” models skip under pressure. Verification is the control that does not depend on model obedience: dual-user tests, secret scanners, live URL probes.
Team scorecard (monthly)
Track counts of: open RLS tables found in prod, secrets rotated after scans, agent PRs blocked for auth issues, time-to-fix critical findings. Publish the scorecard internally so velocity metrics are not the only dashboard.
Prompt library snippets that reduce Top 10 density
Paste into agent system rules (still verify):
- Never put secrets in NEXT_PUBLIC_, VITE_, or client bundles.
- Every data route checks auth and ownership (user B cannot read user A).
- Parameterized SQL only; no string-built queries or shell with user input.
- RLS enabled on every new table with owner policies; no USING (true).
- Webhooks verify signatures; clients cannot set paid/role/admin fields.
- Do not disable security tests or CI checks to make the build green.
Rules reduce frequency; dual-user tests and live scans catch obedience failures.
Mapping scanner findings to tickets
| Scanner class | OWASP | Ticket title pattern |
|---|---|---|
| Anon table dump | A01 | “Enable RLS + owner policy on {table}” |
| sk_live in JS | A02 | “Rotate Stripe key; move to server env” |
| innerHTML user HTML | A03 | “Sanitize markdown sink in {file}” |
| CORS * + cookies | A05 | “Allowlist origins on API” |
| Hallucinated npm pkg | A06 | “Remove {pkg}; verify registry” |
| Unlimited login | A07 | “Rate limit /auth” |
| Webhook no sig | A08 | “constructEvent + raw body” |
| No auth logs | A09 | “Ship failed-login metrics” |
| Fetch user URL | A10 | “Allowlist hosts for preview fetch” |
Agentic coding multiplies A01 and A05
Autonomous agents (Devin, Cursor Agent, Claude Code with tools) open more files per hour than a human. Empirically that increases density of:
- New routes without ownership checks (A01)
- Temporary open CORS / debug flags left on (A05)
- New dependencies without audit (A06)
It does not create a new OWASP category. Gate agent PRs with the same Top 10 map plus agentic code review for diff-scale issues (unrelated file “improvements,” CI disablement).
What this page is not
This is not the OWASP Top 10 for LLM applications (prompt injection, training data poisoning, model DoS). Those are real and orthogonal. When your product is an LLM feature, map:
- Prompt injection → A03/A08-ish integrity failures depending on tool use
- Insecure plugin/tool design → A04
- Excessive agency → A01 when tools can read all tenants
Keep web Top 10 for the HTTP app; add LLM-specific guidance for the model plane. Mixed apps need both.
Scan Your AI Code for OWASP Vulnerabilities
VibeEval automatically checks AI-generated apps against OWASP Top 10 categories on the live URL — broken access control, injection surfaces, crypto/key leaks, and misconfiguration — with findings you can paste back into Cursor, Claude Code, or Lovable.
COMMON QUESTIONS
MAP OWASP TO YOUR LIVE APP
Reading the Top 10 is research. We probe your deployed app for the same classes — with evidence you can fix today.
14-day free trial · No credit card · Cancel anytime