PromptFu
03 Offense: Agentic3.10Core16 min

Improper output handling

Sink enumeration and the structured-intent pattern.

LLM10:2026Where does the output land?

Model output is not an answer. It is a string on its way somewhere, and the somewhere decides what it becomes. The same sentence is text in a chat bubble, a command in a shell and a script in a browser.

The reframe that makes this ordinary

OWASP's framing turns an unfamiliar problem into a familiar one in a single line.

Since LLM-generated content can be controlled by prompt input, this behavior is similar to providing users indirect access to additional functionality.
OWASP LLM10:2026

So a model connected to a shell is a shell with an extra input box. Everything application security already knows applies, and the mitigation says so outright.

Treat the model as any other user, adopting a zero-trust approach, and apply proper input validation on responses coming from the model to backend functions.
OWASP LLM10:2026, mitigation 1

Where it sits next to the neighbouring entries

Three entries touch model output and they divide cleanly. Getting this wrong is the most common misfiling in reports.

OWASP's own boundaries
LLM01  Prompt Injection        the INPUT side. Validation of what goes in.

LLM07  Misinformation          output that is incorrect or misleading.
                               The content is wrong.

LLM10  Improper Output         unsafe USE of output before it is passed
       Handling                downstream. The content may be perfectly
                               correct and still take down the system.

The distinction that matters: LLM07 is about the answer being wrong, LLM10 is about where the answer goes. A correct SQL query executed unparameterised is an LLM10 finding.

Take the inventory

This entry does not reward clever payloads. It rewards listing every place output lands and noticing which of them interpret what they are given.

Where does the output land?

0/7 present

Seven sinks, from OWASP's own risk list. Tick the ones that exist in a system you know, then read what each one turns model output into.

Remote code execution

LLM output is entered directly into a system shell or similar function such as exec or eval, resulting in remote code execution.

The fixTreat the model as any other user, adopting a zero-trust approach, and apply proper input validation on responses coming from the model to backend functions. (Mitigation 1)

Risks and fixes quoted from OWASP LLM10:2026 Common Examples of Risk and its numbered Prevention and Mitigation Strategies.

The impact set is unglamorous and familiar, which is the point. OWASP lists XSS and CSRF in browsers, plus SSRF, privilege escalation and remote code execution on backend systems.

The two sinks added in 2026

Both are already elsewhere in this course, and they are worth naming here because they are the two that rarely appear on anyone's sink list.

The first is the terminal. Control characters written to a terminal, log viewer or IDE pane get interpreted, and OWASP names the consequences: visual spoofing, clipboard hijacking through OSC 52, and exploitation of known terminal emulator bugs. Module 2.4 covers the character classes.

The second is any renderer that fetches. A chat UI that auto-renders Markdown images or link previews will send an outbound request to whatever host the model named, carrying whatever the model put in the query string. Module 3.2 runs that as a full chain.

Deep diveScenario #6, and why coding agents concentrate this entry

OWASP's sixth scenario is short: an application automatically compiles and deploys LLM-generated code without human review or security testing, so insecure code reaches production and is exploited.

A developer machine is the densest collection of sinks in this course. A shell, a browser, a terminal, an IDE that renders panes, a config file that changes behaviour, a package manifest and a deploy pipeline, all reachable by one agent.

That is the ground module 3.11 covers, and it is why CVE-2025-53773 from module 3.3 is an LLM10 finding as much as an LLM01 one. OWASP cites it under both.

The pattern that fixes this by construction

The reliable version stops asking the model for the finished artefact. Ask it for a decision, in a shape the application can check, and build the artefact from the decision.

Structured intent
Fragile:  model emits  ->  "DELETE FROM invoices WHERE id = 42"
                        ->  db.execute(thatString)

Sound:    model emits  ->  { action: "void_invoice", id: 42 }
                        ->  validate against a schema
                        ->  check the caller may void invoice 42
                        ->  the application writes the query

The model still chooses. It no longer writes the thing that executes, so the sink never receives model-authored syntax and there is nothing to escape.

Bounds blast radius· survives adaptive attack

Context-aware encoding at each sink, parameterised queries, and structured intent where an artefact would otherwise be model-authored. These hold under adaptive attack because they do not depend on recognising a hostile string.

Sources