Improper Output Handling covers every case where output from a model reaches another component without adequate validation or sanitisation. The principle is one sentence long: model output is untrusted input to whatever consumes it.
The reason is mechanical, not philosophical. Because model output can be influenced by prompt
input, passing it unvalidated into a downstream component is equivalent to giving users indirect
access to that component’s functionality. A user who cannot call your shell directly, but can steer a
model whose response is passed to exec, has a shell. Successful exploitation reaches XSS and CSRF
in browsers. On the server side the reachable outcomes run from forged internal requests to
escalated privilege, and to code executing on the backend outright.
Two boundaries keep this entry separate from its neighbours:
| Concern | Entry |
|---|---|
| Unsafe use of model output downstream | LLM10:2026 (this entry) |
| Output that is incorrect or misleading | LLM07:2026 Misinformation |
| Validation and sanitisation of model inputs | LLM01:2026 Prompt Injection |
From fifth to tenth, and what that means
This is the entry that moved furthest in the 2026 edition. OWASP’s own summary: “Improper Output Handling fell the furthest, from fifth to tenth.” It closes the list.
The demotion is not a claim that the risk got smaller. The 2026 ranking weights a community practitioner vote at three-quarters and an incident record at one quarter, and the moves at the top of the list went to agency and context: Excessive Agency climbed to third, described by the editors as the most consequential move, because vote and record agree that agentic deployments are where the damage is landing. Unbounded Consumption rose four places. Output handling did not get safer; the field’s attention moved toward risks that are newer and less well understood, and output handling is the entry with the most mature, most transferable defences: context-aware encoding, parameterised queries, CSP. These are decades-old web-application controls applied to a new source of untrusted data. A team that already does output encoding properly is most of the way there, which is precisely why the vote ranks it low.
The entry also grew while falling. OWASP folded in “the insecure code that assistants generate at scale”, which appears here as the sixth attack scenario: pipelines that compile and deploy model-generated code without review. The demotion and the expansion happened in the same release.
Note the caveat the editors attach to the whole ranking exercise: incident data is one noisy year, it carries a quarter of the weight deliberately, and it is “not enough to let imperfect data rewrite the list on its own”. Read rank ten as a statement about relative attention, not about whether you can skip this.
Conditions that raise the impact
The source lists the conditions that make an output-handling flaw worse. They are worth reading as a checklist against your own deployment:
- Excessive application privileges granted to the LLM, enabling privilege escalation or remote code execution.
- Susceptibility to indirect prompt injection that can grant an attacker privileged access to a target user’s environment.
- Unvalidated inputs from third-party tools.
- Output encoded for no particular destination, when HTML, JavaScript and SQL each need their own.
- Nothing recording what the model emitted, so nobody can reconstruct an incident afterwards.
- No ceiling on usage and no alert when the shape of it changes.
- Terminal, log or IDE sinks that render model output without neutralising control characters such as ANSI escape sequences.
- Client renderers (browser, chat UI, IDE, terminal) that automatically fetch external resources referenced in model output, such as Markdown images, link previews and iframes, enabling exfiltration of context data through outbound requests.
The last two are the ones most often missing from a threat model built around web output. A model response is not only rendered; it is also logged, printed to a developer’s terminal, and displayed in an IDE pane. Each of those is a sink with its own interpretation rules.
The sinks
The risk is best understood by enumerating where output lands and what that consumer does with it.
| Sink | What the model output becomes | Resulting class |
|---|---|---|
exec, eval, a system shell |
A command | Remote code execution |
| Browser DOM, chat UI | HTML / JavaScript / Markdown | XSS, and CSRF against the user’s session |
| Database driver | A query, concatenated rather than parameterised | SQL injection |
| HTTP client, URL fetcher, Markdown image renderer | A URL the server or client retrieves | SSRF, and data exfiltration |
| Filesystem API | A path | Path traversal |
| Email template | Message body | Phishing, and XSS in vulnerable mail clients |
| Terminal, log viewer, IDE pane | Control characters and ANSI escape sequences | Visual spoofing, clipboard hijacking, terminal-emulator exploits |
| Build and deploy pipeline | Source code | Insecure code reaching production |
Remote code execution is the shortest path: model output entered directly into a system shell or a
function such as exec or eval.
XSS arises when the model generates JavaScript or Markdown that is returned to a user and interpreted by the browser. CSRF follows from the same primitive, since script executing in the victim’s origin can issue authenticated requests. The email-template variant is the same bug at one remove: LLM-generated content used in email templates without proper escaping leads to phishing, and to XSS on recipients whose mail client is vulnerable.
SQL injection occurs where LLM-generated SQL is executed without proper parameterisation. This is
worth separating from the “the model wrote a destructive query” case. Both appear in the source, and
they need different fixes. Parameterisation stops injected syntax; it does nothing about a
syntactically perfect DROP TABLE. That case needs privilege restriction on the database role and a
human approval step.
SSRF and exfiltration through auto-fetched resources is the subtlest of the set. Rehberger (2024a) is cited for the case where a chat UI auto-renders Markdown images or link previews from model output, allowing an attacker who controls part of the model context to exfiltrate conversation data through the image URL’s hostname or query string. Nothing is executed. The request itself is the channel.
Control characters. Model output containing ANSI escape sequences or other control characters, written to a terminal, log viewer or IDE pane that interprets them, enables visual spoofing, clipboard hijacking (OSC 52, for example) or exploitation of known terminal-emulator vulnerabilities (Rehberger, 2024b). This one bites developer tooling hardest, because CLI agents and log pipelines are exactly the places where output is assumed to be diagnostic text, not attacker-controlled content.
Path traversal. LLM output used to construct file paths without sanitisation.
Mitigations
Treat the model as an untrusted user
Treat the model as untrusted and validate what it returns as strictly as anything else arriving from the model into backend functions. This is the framing that makes the rest follow: the model sits on the same side of the boundary as the end user, not on the application’s side.
Encode for the specific sink
Encode model output before returning it to users, to prevent undesired execution of JavaScript or Markdown, and implement context-aware encoding based on where the output will be used: HTML encoding for web content, JavaScript encoding for browser script contexts. OWASP directs readers to the Application Security Verification Standard (ASVS) for both input validation and output encoding guidance; nothing about this problem requires new controls, only their application to a new source of untrusted data.
The trade-off is genuine and should be decided deliberately: encoding output correctly means a model that legitimately produces Markdown tables, code blocks or links will have them rendered inert unless you build a constrained renderer that permits a known-safe subset. Rendering rich output and being safe are in tension. The resolution is an allowlisted renderer, not a blocklist of dangerous patterns.
Parameterise database access
Every database call carrying model output goes through a parameterised query or a prepared statement, without exception. The model supplies values; it does not supply syntax.
Constrain the browser
Employ strict Content Security Policies to mitigate XSS from LLM-generated content. CSP is the defence in depth for the case where encoding is missed on one path. In an application with many rendering paths, one will be missed.
Sanitise control characters
Strip ANSI escape sequences, BEL, OSC, backspace, carriage return and other non-printable bytes from model output before it is written to terminals, log files or any other interpreting sink. Where they must be preserved, encode them visibly so they are displayed rather than executed.
Stop renderers making outbound requests
In chat UIs, IDEs, email clients and mobile apps, prevent model output from triggering automatic outbound requests to attacker-controlled endpoints. Disable auto-rendering of Markdown images, link previews, iframes and similar elements by default. Where rendering is required, restrict fetches to an explicit allowlist of origins, or proxy them through a server-side fetcher that strips data-bearing query parameters. Note that the allowlist must be of origins, not of schemes or file types: the exfiltration channel is the hostname and query string, so any fetch to an attacker origin succeeds regardless of what is returned.
Log and monitor output
Implement logging and monitoring to detect unusual patterns in model output that might indicate exploitation attempts. Output-side logging is under-built in most deployments relative to input-side logging, and it is where several of these attacks are actually visible - a response containing an ANSI escape sequence, or a Markdown image pointing at an unfamiliar host, is anomalous on its face. Sanitise before logging, or the log viewer becomes the sink.
Attack scenarios
Privileged tool invocation. An application uses an LLM tool to generate chatbot responses. The same tool also offers administrative functions intended for a separate, privileged model. The general-purpose model passes its response to the tool without output validation, and the tool shuts down for maintenance. No injection payload was required in the classical sense; the output simply reached a function it should never have been able to invoke.
Website summariser exfiltration. A user runs an LLM-powered summariser over an article. The page contains a prompt injection instructing the model to capture sensitive content from the page or from the user’s conversation, encode it, and send it to an attacker-controlled server. With no output validation or filtering, it does. This is the case where LLM01 and LLM10 chain: injection supplies the instruction, missing output handling supplies the channel.
Destructive generated SQL. An LLM lets users compose SQL against a backend database through a chat feature. A user requests a query that deletes every table. The generated query is not scrutinised, and the tables are dropped.
XSS from generated content. A web application generates content from user prompts with no output sanitisation. A crafted prompt makes the model return an unsanitised JavaScript payload, which executes when rendered in a victim’s browser.
Email-template XSS. A marketing system has the model write the email bodies it sends. An attacker steers it into planting JavaScript in one of them. Nothing sanitises the output on its way out, so the script travels with the message and runs for every recipient whose client renders it.
Unreviewed generated code. An application automatically compiles and deploys LLM-generated code with no human review or security testing. Because the output is trusted and executed without validation, insecure code reaches production and is exploited. This is the scenario added in the 2026 edition. Its blast radius scales with how much of your codebase an assistant writes.
Related entries
- LLM01:2026 Prompt Injection - supplies the attacker control over output that makes this entry exploitable; covers validation of inputs, where this covers outputs.
- LLM08:2026 Hidden Context Exposure - leaked output-formatting rules let an attacker produce structurally valid output carrying manipulated values, defeating schema checks.
- LLM09:2026 Vector and Embedding Weaknesses - poisoned retrieval is one route by which an attacker shapes the output this entry is about.
- AI security overview - the full 2026 list and how the entries relate.