OWASP LLM Top 10 — the 10 most critical risks for LLM-powered applications (2025)
OWASP's LLM Top 10 is the canonical taxonomy for AI-feature security. Different from the regular OWASP Top 10, it covers the bug classes that only exist when you ship LLMs in production — prompt injection, insecure output handling, training-data poisoning, model DoS, supply-chain risks, and more. Here's each category with a real-world example and the Securie specialist that catches it.
If your app ships an LLM-powered feature — chatbot, RAG search, AI agent, copilot — the regular OWASP Top 10 covers about half of your attack surface. The other half is the OWASP LLM Top 10: ten categories that only exist when an LLM is in the loop. The 2025 edition (LLM01 through LLM10) is the canonical reference cited by every major AI-security report. This guide walks through each category with a one-line definition, a real-world example, and the Securie specialist that catches it on every PR.
What it is
The OWASP Top 10 for Large Language Model Applications is a community-curated list of the most critical security risks specific to LLM-powered applications. The 2025 edition was published in late 2024 and is the current version as of mid-2026. It complements the regular OWASP Top 10 (which still applies to your auth, data, and infrastructure) by covering the LLM-specific bug classes: prompt injection, insecure output handling, training-data poisoning, model denial-of-service, supply chain, sensitive information disclosure, insecure plugin design, excessive agency, overreliance, and model theft.
Vulnerable example
// Vulnerable: a customer-support chatbot that hits LLM02 (insecure output handling)
import OpenAI from "openai";
const llm = new OpenAI();
export async function POST(req: Request) {
const { question } = await req.json();
const r = await llm.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "You are a customer support assistant." },
{ role: "user", content: question }, // LLM01 injection surface
],
});
// LLM02: raw LLM output rendered as HTML on the page
return new Response(`<div>${r.choices[0].message.content}</div>`, {
headers: { "content-type": "text/html" },
});
// The model can be coaxed into emitting <script> tags. Stored XSS via LLM.
}Fixed example
import OpenAI from "openai";
import { sanitize } from "@securie/llm-safety";
import { escapeHtml } from "./escape";
const llm = new OpenAI();
export async function POST(req: Request) {
const { question } = await req.json();
// LLM01 defense: pre-classify input
const cleanInput = sanitize.input(question);
if (cleanInput.blocked) return new Response("blocked", { status: 400 });
const r = await llm.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "You are a customer support assistant. Output plain text only." },
{ role: "user", content: cleanInput.text },
],
});
// LLM02 defense: never trust raw LLM output as HTML
const safe = escapeHtml(r.choices[0].message.content ?? "");
return Response.json({ answer: safe });
}How Securie catches it
apps/web/lib/llm/chat.ts:34OWASP LLM Top 10
Securie's specialist roster maps category-by-category to the OWASP LLM Top 10. Prompt-injection (LLM01) -> llm-safety SafetyFilter wired around every Router::complete. Insecure output (LLM02) -> static-rules + intent-graph flag any LLM output rendered as HTML/SQL/eval without escaping. Training-data poisoning (LLM03) -> rag-guard poisoning_score on every ingested doc + AIBOM provenance tracking. Model DoS (LLM04) -> cost-firewall enforces per-tenant per-session compute caps. Supply chain (LLM05) -> AIBOM + dependency-vuln specialist + slopsquatting heuristic. Sensitive info disclosure (LLM06) -> secret_scanner + intent-graph audit of every prompt template. Insecure plugin design (LLM07) -> agent-scope crate's compile-time scope guards on tool catalogs. Excessive agency (LLM08) -> agent-scope + Plan-Mode-equivalent fail-closed. Overreliance (LLM09) -> fitness-of-confidence telemetry + audit logs. Model theft (LLM10) -> tenant isolator + signed model fingerprints.
import OpenAI from "openai";
import { sanitize } from "@securie/llm-safety";
import { escapeHtml } from "./escape";
const llm = new OpenAI();
export async function POST(req: Request) {
const { question } = await req.json();
// LLM01 defense: pre-classify input
const cleanInput = sanitize.input(question);
if (cleanInput.blocked) return new Response("blocked", { status: 400 });
const r = await llm.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: "You are a customer support assistant. Output plain text only." },
{ role: "user", content: cleanInput.text },
],
});
// LLM02 defense: never trust raw LLM output as HTML
const safe = escapeHtml(r.choices[0].message.content ?? "");
return Response.json({ answer: safe });
}Checklist
- LLM01 — Prompt injection: input sanitized + Llama Guard 4 input/output classifier wired
- LLM02 — Insecure output handling: LLM outputs are NEVER rendered as HTML / executed as SQL / eval'd without escaping
- LLM03 — Training data poisoning: every RAG-ingested document is poisoning-scored before reaching context
- LLM04 — Model denial-of-service: per-tenant compute caps + per-session sampling-call ceilings
- LLM05 — Supply-chain vulnerabilities: AIBOM emitted on every release + dependency-vuln scanned on every PR
- LLM06 — Sensitive info disclosure: prompt templates audited for hard-coded secrets / PII
- LLM07 — Insecure plugin design: tool catalogs scope-locked at credential issuance
- LLM08 — Excessive agency: agents have least-privilege scope; destructive tools require explicit approval
- LLM09 — Overreliance: confidence + provenance signals shown to users; audit log retains every decision
- LLM10 — Model theft: model artifacts signed (DSSE) + tenant-isolated; egress monitoring on training infra
FAQ
Is the OWASP LLM Top 10 the same as the regular OWASP Top 10?
No. The regular OWASP Top 10 covers web application security (broken access control, injection, etc.) and still applies. The LLM Top 10 covers risks specific to LLM-powered applications. Most production AI apps need both lists.
What changed in the 2025 edition?
The 2025 edition refined the categories and added more concrete attack examples. LLM01 (prompt injection) was expanded to cover indirect injection more thoroughly; LLM05 (supply chain) added AI-specific concerns like training-data provenance and model marketplace risks.
Where does MCP fit?
MCP-related attacks (tool poisoning, rug-pull, scope escalation) primarily map to LLM07 (insecure plugin design) and LLM08 (excessive agency). The lethal trifecta heuristic is a useful overlay across LLM01 + LLM07 + LLM08.
How do I prioritize?
If you ship a chatbot or RAG: start with LLM01 + LLM02 + LLM06. If you ship agents with tool use: add LLM07 + LLM08. If you fine-tune or accept training contributions: add LLM03 + LLM05.
Related guides
User input + LLM = prompt injection surface. Defense: pre-sanitize user input + Llama Guard 4 classify outputs + scope-bound egress.
Adversarial testing for LLMs and agents in production. Two layers: continuous automated red-team in CI (catches regressions on every release) + quarterly manual engagement (finds novel classes). This guide shows the harness, the corpus, and the threshold gates.
IDOR is the classic name for an authorization bug where a user can change an ID in a URL and access data they should not see. It is BOLA's older cousin and still ships in half of all new apps.
Your AI chatbot or tool-using agent can be tricked into leaking data, calling the wrong tools, or taking destructive actions — often through a single crafted email or document. Here is how prompt injection works and how to defend.