Area 06 // AI SecurityLesson 94 / 14014 min read
The OWASP Top 10 for LLM apps
The OWASP Top 10 for LLM Applications is a community list of the ten most important security risks in apps built on language models, from prompt injection to unbounded consumption, and it works best as a checklist for threat-modelling your own app.
Think of it like this
The problem it solves
Teams new to AI security don't know what they don't know. They worry about the model saying something rude while missing that their agent can delete files, their RAG index leaks HR documents, or a script can run up a five-figure bill overnight. A shared, ranked list of the main risks gives everyone the same vocabulary and a starting checklist.
How it works, step by step
- Know the source: the OWASP GenAI Security Project publishes the Top 10 for LLM Applications; as of November 2026 the current edition is 2026 (published August 2026). It ranks risks using community input and real incident data.
- Learn the ten (2026 edition), each with where it's covered in this course:
| ID | Risk | In plain words | Main controls |
|---|---|---|---|
| LLM01 | Prompt Injection | Input text overrides your instructions | Injection defences, least privilege |
| LLM02 | Sensitive Information Disclosure | The app leaks personal or confidential data | PII and leakage, RAG access control |
| LLM03 | Excessive Agency | Too many tools, permissions or autonomy | Least privilege, approval |
| LLM04 | Supply Chain | Untrusted models, packages, plugins | Supply chain, MCP trust |
| LLM05 | Data and Model Poisoning | Bad data planted in training, fine-tuning or RAG | Poisoning |
| LLM06 | Unbounded Consumption | Runaway cost or resource use | Denial of wallet |
| LLM07 | Misinformation | Confident, wrong answers people rely on | Hallucinations, citations |
| LLM08 | Hidden Context Exposure | Hidden prompts and context leak out | Keep secrets out of prompts, output checks |
| LLM09 | Vector and Embedding Weaknesses | RAG stores leak or get manipulated | RAG access control |
| LLM10 | Improper Output Handling | Output used unsafely in HTML, SQL, shell | Output validation, escaping |
- Notice the changes from 2025: Excessive Agency rose to 3rd and Unbounded Consumption to 6th (agents and reasoning models raise both), System Prompt Leakage was broadened into Hidden Context Exposure, and Improper Output Handling dropped to 10th.
- Threat-model your app: for each feature, mark which risks apply (see the code), then name the control and the test that proves it works.
- For agents, also use the OWASP Top 10 for Agentic Applications (December 2025), which starts with agent goal hijack and tool misuse.
- Revisit at every major feature and when a new edition appears.
See it in code
- Needs
- Nothing: plain Python 3.
A threat-model starter: describe each app, and see which of the ten risks apply.
# OWASP Top 10 for LLM Applications 2026: which risks apply to MY app? (a threat-model starter)
OWASP_2026 = {
"LLM01 Prompt Injection": lambda a: True,
"LLM02 Sensitive Information Disclosure": lambda a: a["private_data"],
"LLM03 Excessive Agency": lambda a: a["tools_that_change_things"],
"LLM04 Supply Chain": lambda a: a["third_party_models_or_plugins"],
"LLM05 Data and Model Poisoning": lambda a: a["fine_tunes"] or a["rag"],
"LLM06 Unbounded Consumption": lambda a: a["public_users"],
"LLM07 Misinformation": lambda a: True,
"LLM08 Hidden Context Exposure": lambda a: a["secret_system_prompt"],
"LLM09 Vector and Embedding Weaknesses": lambda a: a["rag"],
"LLM10 Improper Output Handling": lambda a: a["output_rendered_or_executed"],
}
apps = {
"public support bot": dict(private_data=True, tools_that_change_things=True, third_party_models_or_plugins=True,
fine_tunes=False, rag=True, public_users=True, secret_system_prompt=True,
output_rendered_or_executed=True),
"internal summariser": dict(private_data=True, tools_that_change_things=False, third_party_models_or_plugins=False,
fine_tunes=False, rag=False, public_users=False, secret_system_prompt=False,
output_rendered_or_executed=False),
}
for name, app in apps.items():
applies = [risk.split()[0] for risk, check in OWASP_2026.items() if check(app)]
print(f"{name:20} {len(applies):2} of 10: {' '.join(applies)}")public support bot 10 of 10: LLM01 LLM02 LLM03 LLM04 LLM05 LLM06 LLM07 LLM08 LLM09 LLM10
internal summariser 3 of 10: LLM01 LLM02 LLM07A public bot with RAG and tools touches every risk; a small internal tool only a few. The next step is a table: risk → control → test → owner.
A real example
Example
A threat-modelling session before launch
Before launching a customer support agent, a team spent two hours walking the OWASP list. Three findings changed the design: the refund tool had no amount limit (excessive agency, so a cap and approval were added), the bot's answers were rendered as Markdown that could load external images (improper output handling plus an exfiltration path, so external images were disabled), and the public endpoint had no per-user budget (unbounded consumption, so quotas were added).
Each risk got an owner and an automated test in the eval suite, and the table became part of the release checklist.
The easy way
Start here
Copy the ten risks into a table with three columns: "applies to us?", "our control", "how we test it". Fill it in as a team for your app. Any row with "applies" but no control is your to-do list.
When you grow: the production setup
Security teams fold the list into formal threat modelling (alongside frameworks such as MITRE ATLAS and the agentic Top 10), map risks to controls and automated tests in CI, assign owners, run red-team exercises per risk, and review the model at each major release and when OWASP publishes a new edition.
Trade-offs
What you gain
- Shared vocabulary across engineering, security and product.
- Quick way to spot obvious gaps.
- Maps well to controls and tests.
What it costs you
- Generic: it can't know your app's specific risks.
- Rankings change between editions.
- Easy to treat as a box-ticking exercise.
When not to use it
- Don't use it as your only security review for high-stakes systems; add app-specific threat modelling and testing.
Common mistakes
- Assuming the model provider handles all ten.
- Ticking risks off without a test that proves the control works.
- Forgetting non-chat paths (batch jobs, tools, admin features).
- Using an old edition's numbering without noticing the changes.
- Treating misinformation as "not security" when people act on wrong answers.
Interview questions
Try answering out loud first, then open the model answer.
Name some risks from the OWASP Top 10 for LLM apps and their mitigations.
Model answer
Prompt injection (least privilege, policy checks, approval, classifiers), sensitive information disclosure (redaction, access-controlled retrieval, output filters), excessive agency (minimal tools and scopes, approvals), supply chain (trusted sources, pinned hashes, safetensors), data and model poisoning (data provenance and validation), unbounded consumption (rate limits, token caps, budgets), improper output handling (treat output as untrusted, escape and validate before HTML, SQL or shell).
What is improper output handling and how do you prevent it?
Model answer
Passing model output to another system without validation, e.g. rendering it as HTML (XSS), building SQL or shell commands from it, or auto-fetching URLs it contains. Prevent it by treating output as untrusted user input: escape for the target context, validate against schemas, use parameterised queries, avoid executing generated code outside sandboxes, and block auto-loading of external resources.
How would you use the OWASP list in a real project?
Model answer
Run a threat-modelling session per feature: decide which risks apply, define a control for each, write a test that demonstrates the control (in CI where possible), assign an owner, and revisit at each release. Supplement it with app-specific risks and the agentic Top 10 for tool-using agents.
Quiz
Pick an answer to see whether it’s right and why.
0 of 5 answered
Key terms
- OWASP
- The Open Worldwide Application Security Project, a non-profit community that publishes free security guides, including Top 10 lists of risks for web apps and for LLM applications.
- Prompt injection
- An attack where text in the input (typed by a user or hidden in a document, web page or tool result) tries to override the system's instructions.
- Excessive agency
- When an AI system has more tools, permissions or autonomy than its job needs, so a mistake or attack can do real damage. LLM03 in the OWASP 2026 list.
- Threat model
- A structured look at what you're protecting, who might attack it, how, and which controls stop each attack. Done before building and revisited as the system changes.
- Supply chain (AI)
- Everything your AI system is built from that others made, such as pre-trained models, datasets, packages, plugins and MCP servers, each of which can be a way in for attackers.
Before and after
Progress is saved in this browser only.