Skip to content

All lessons

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

Analogy

A home inspector carries a checklist: wiring, damp, roof, gas, locks. Not every item applies to every house (a flat has no roof of its own), but walking the list stops them forgetting the obvious. The OWASP list is that checklist for LLM apps.

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

  1. 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.
  2. Learn the ten (2026 edition), each with where it's covered in this course:
IDRiskIn plain wordsMain controls
LLM01Prompt InjectionInput text overrides your instructionsInjection defences, least privilege
LLM02Sensitive Information DisclosureThe app leaks personal or confidential dataPII and leakage, RAG access control
LLM03Excessive AgencyToo many tools, permissions or autonomyLeast privilege, approval
LLM04Supply ChainUntrusted models, packages, pluginsSupply chain, MCP trust
LLM05Data and Model PoisoningBad data planted in training, fine-tuning or RAGPoisoning
LLM06Unbounded ConsumptionRunaway cost or resource useDenial of wallet
LLM07MisinformationConfident, wrong answers people rely onHallucinations, citations
LLM08Hidden Context ExposureHidden prompts and context leak outKeep secrets out of prompts, output checks
LLM09Vector and Embedding WeaknessesRAG stores leak or get manipulatedRAG access control
LLM10Improper Output HandlingOutput used unsafely in HTML, SQL, shellOutput validation, escaping
  1. 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.
  2. 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.
  3. For agents, also use the OWASP Top 10 for Agentic Applications (December 2025), which starts with agent goal hijack and tool misuse.
  4. 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_checklist.py
# 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)}")
Output
public support bot   10 of 10: LLM01 LLM02 LLM03 LLM04 LLM05 LLM06 LLM07 LLM08 LLM09 LLM10
internal summariser   3 of 10: LLM01 LLM02 LLM07

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

  1. 01Which risk is number one on the OWASP LLM list?
  2. 02What does "excessive agency" mean?
  3. 03An LLM's output is inserted into a web page without escaping. Which risk is this?
  4. 04Which risk covers attackers running up your bill or exhausting resources?
  5. 05What's the best way to use the list?

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.