Example finding How it works Coverage PENTEST METHODOLOGY DOCS PRICING FAQ MCP CONTACT LOG IN SIGN UP →

OWASP Top 10 for AI-Generated Code: A01-A10 Risks and 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 codebases that mix secure and insecure patterns, and they optimize for code that works. The result runs fine in development and ships with well-known vulnerabilities.

A Stanford study (Perry et al., “Do Users Write More Insecure Code with AI Assistants?”) found that participants with an AI assistant wrote less secure code than those without one. AI writes the same insecure patterns humans have written for decades, only faster. OWASP gives you a framework to find and fix them.

Use this page as a priority map. Check A01 and A05 first. A03 appears whenever SQL or HTML is string-built, and A02 shows up as keys in the bundle. Mapping findings to OWASP also helps with auditors who already think in these categories.

The control strategy is unchanged: authorization, secrets hygiene, safe defaults, and verification on the live URL, repeated after every generative session.

A01: Broken Access Control in AI Code

Broken access control is the number one OWASP risk. AI tools generate routes, API endpoints, and database queries without authorization checks. Specific patterns:

  • 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, or balance because the handler saves the whole body.
  • Entity permissions left at auth or public on Base44-style platforms when owner was 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 check that the user is logged in and stop. Ask for the ownership check explicitly in the prompt.

A02: Cryptographic Failures

AI tools generate code with basic cryptographic weaknesses that automated scanners flag:

  • 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: none or 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")}`;
}

Reject completions that simplify password storage to a single SHA-256 hex string.

A03: Injection

Injection patterns in AI-generated code:

  • 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.system with 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: quick examples often concatenate strings. Treat any `...${user}...` in a query or shell command as a review blocker.

A04: Insecure Design

AI optimizes for the demo path. Insecure design is an architecture that cannot be made safe without rework:

  • 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_id filters 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:

  1. What is the trust boundary? (browser vs server vs third party)
  2. Who can read/write each object?
  3. What happens if the client lies about price/role/id?
  4. Where do secrets live?

If you cannot answer, hold off generating the feature.

A05: Security Misconfiguration

Common misconfigurations in 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=development left 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" }
    ]
  }]
}

The code can look fine in git while production is open, so scan the running app.

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 latest tags 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 confirm it.

A07: Identification & Authentication Failures

Common flaws in AI-generated authentication:

  • Weak session management: no expiry; tokens in localStorage.
  • Missing MFA unless prompted.
  • Insecure password reset: eternal tokens; user enumeration.
  • No brute force protection on /login and /auth/v1/token.
  • Disabled email verification and no leaked password protection.
  • OAuth redirect URI wildcards or leftover tunnel URLs.
  • JWT verification that trusts alg from 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!,
);

A09: Security Logging & Monitoring Failures

AI-generated apps rarely include useful security telemetry:

  • No audit logs for authz failures or admin actions.
  • console.log of 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)

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.254 or 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

  1. Run automated SAST: Semgrep OWASP rulesets, secret scanners (gitleaks).
  2. Check every route: auth + authorization; no exceptions.
  3. Search for secrets: git history + deployed bundle.
  4. Test database access: anon key against every table (Supabase/Firebase rules).
  5. Verify input validation: malformed bodies on every write.
  6. Review auth flows: reset, session expiry, role escalation.
  7. Probe live deploy: Vibe Code Scanner for runtime gaps SAST misses.
  8. Confirm logging: failed login and 403s visible somewhere you watch.
  9. Review webhooks and SSRF features: signed webhooks; allowlisted fetches.
  10. Re-run after every agent feature: one-time audits go stale.

Automated scanning does not cover logic or access control. Those 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

Add this table to 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 go on a scheduled backlog with owners.

Tooling mapped to categories

Control Covers
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. Combine several and re-run them after generative sessions.

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

Symptoms in a hypothetical 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.

Prompt rules that reduce Top 10 findings

Paste into agent system rules. Models still skip rules, so verify with dual-user tests, secret scanners, and live URL probes:

- 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.

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) touch more files than a human, which adds more of:

  • New routes without ownership checks (A01)
  • Temporary open CORS / debug flags left on (A05)
  • New dependencies without audit (A06)

No new OWASP category is involved. Gate agent PRs with the same Top 10 map plus agentic code review for diff-scale issues (unrelated file “improvements,” CI disablement).

Relation to the OWASP Top 10 for LLM applications

This page covers the web Top 10. The OWASP Top 10 for LLM applications (prompt injection, training data poisoning, model DoS) is separate. When your product has 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

Use the web Top 10 for the HTTP app and LLM-specific guidance for the model layer.

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

Does the official OWASP Top 10 cover AI-generated code?
The OWASP Top 10 classifies web risks regardless of how the code was written. AI tools do not invent a new Top 10 - they reproduce the same classes faster and more uniformly. This page maps each category to patterns we see in Cursor, Copilot, Lovable, Bolt, and similar tools.
What is the most common OWASP risk in vibe-coded apps?
A01 Broken Access Control - especially missing RLS, IDOR/BOLA on CRUD, and admin UI without server checks.
Can SAST cover the whole Top 10 for AI apps?
No. SAST helps on injection, secrets, and some crypto issues. Access control, misconfiguration, and logging gaps need runtime tests and operational controls.
How should teams use this list?
As a PR and launch checklist: for each new AI-generated feature, mark which OWASP categories it touches and what control you added. Pair with a live scan before production.
Is prompt injection part of OWASP Top 10?
Classic Top 10 is web-app focused. Prompt injection shows up as injection/integrity/misconfig depending on architecture. See also agentic and LLM-specific OWASP guidance for model-layer risks.
Where do Lovable and Supabase fit?
Missing RLS is A01. Leaked service_role keys are A02/A05. Open Storage is A01/A05. Map your stack to categories so fixes are prioritized by impact.

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

SCAN AGAINST OWASP →