They often sanitise too early or trust a single library to cover every downstream render step. In multi-stage rendering chains, one plugin can reintroduce active HTML after an earlier filter has already run. Teams need to validate the final DOM after all Markdown, embed, and formatting transformations have completed.
Why sanitising model output fails in real applications
The mistake is treating sanitisation as a one-time filter instead of a property of the whole rendering path. Model output often passes through Markdown parsers, HTML sanitizers, embed resolvers, template engines, and client-side formatters, so a string that looked safe at one stage can become dangerous again later. The control has to be aligned to the final render boundary, not the first convenient interception point.
That is why teams get caught by “safe enough” library use. A library can remove active HTML from the raw output, but if another component later rewrites the DOM, rehydrates content, or allows embedded fragments, the original safety decision no longer holds. The real question is not whether the text was cleaned, but whether the final browser-visible DOM still contains executable or attacker-controlled content.
Sanitisation also fails when teams confuse formatting safety with context safety. Escaping for plain text is not the same as safe insertion into HTML, attributes, URLs, or rich text components. If the same model response is reused in multiple contexts, each context needs its own handling rules and the strictest one should govern the final display path.
What multi-stage rendering changes about the threat
The risk is not limited to obvious script injection. Any downstream step that interprets markup, expands links, or converts text into structured nodes can reintroduce unsafe behaviour after an earlier filter has already run. That includes plugins that support embeds, preview cards, rich text shortcuts, and client-side libraries that reconstruct HTML from sanitized fragments.
Security teams should assume an attacker is trying to place payloads that survive the first pass and activate later. The failure condition is usually trust in an intermediate representation, such as assuming the sanitized string is the final output when it is only one hop in a longer chain. Once that assumption breaks, validation must move to the point where the browser actually receives the finished DOM.
In practice, the dangerous pattern is transformation after trust. If a downstream renderer can add tags, attributes, event handlers, or unsafe URLs, then the earlier filter was only a partial control. The defensive goal is to ensure every transformation is either safe by construction or followed by re-validation at the final output boundary.
What teams should verify before they trust sanitisation
What matters most is the order of operations. Teams should verify which component has the last word on markup, which one can mutate the DOM, and whether any post-sanitization step can introduce new executable structure. If the answer is yes, the sanitization control is incomplete until the final stage is checked.
Another key judgement is scope. A single library may be appropriate for one rendering path, but it does not automatically cover server-side rendering, client-side hydration, mobile clients, email templates, or chat widgets that reinterpret the same content differently. The safer posture is to define the trust boundary by output context, then test each path that can reach a user.
Teams also need a validation habit, not just a filter. That means inspecting the rendered DOM, testing common bypasses, and confirming that no later plugin or formatter reintroduces active content after sanitisation. If you cannot observe the final structure, you have not actually proven the output is safe.
Risk and Threat Considerations
When sanitisation is applied too early, the remaining attack surface shifts to the downstream renderer. That creates a classic security gap: the first control succeeds on the intermediate string, but the final presentation layer still becomes exploitable if a later step expands or rewrites content.
Failure mechanism: An attacker supplies model output that is neutralised in one stage, then survives until a later Markdown, embed, or formatting step reintroduces active HTML or unsafe attributes in the final DOM.
Impact: The application can end up serving scriptable content, unsafe links, or attacker-influenced markup to users even though the original output passed an earlier sanitization check.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP ASVS, NIST SP 800-53 Rev 5 and CIS Controls v8 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V1 — Encoding and Sanitization | Covers safe output handling and context-aware encoding for rendered content. |
| V15 — Secure Coding and Architecture | Applies because the issue is architectural: multiple render stages can defeat a single filter. | |
| Recommendation — Validate output in the final context and enforce context-appropriate encoding before rendering. Design the rendering pipeline so no post-sanitization step can introduce unsafe content. | ||
| NIST SP 800-53 Rev 5 | SI-10 — Information Input Validation | Relevant to validating untrusted model output before it reaches the final presentation layer. |
| SC-18 — Mobile Code | Relevant where rendered content can become executable code or active browser content. | |
| Recommendation — Validate untrusted content at each trust boundary and before final display. Restrict active content and review any component that can turn text into executable behavior. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | Applies to securing application-layer rendering and input/output handling paths. |
| Recommendation — Test application rendering paths for unsafe content reintroduction after sanitization. | ||
Practitioner Guidance
What to verify: Confirm the exact component that owns the final DOM write, then test whether any transformation occurs after the last sanitization step. If there is more than one renderer, each boundary needs explicit review.
Common mistake: Do not treat “we use a sanitizer” as proof of safety when content still flows through Markdown, embed, or template logic later. The right control is final-render validation, not library adoption alone.
What good looks like: The safest implementation has a clear final output boundary, predictable rendering rules, and automated tests that compare the rendered DOM to the intended safe structure rather than the raw text alone.
Practitioner takeaway: Sanitize for the last transformation that can affect what the user actually sees, because every earlier filter is only provisional if a later stage can still turn text into code.
Related resources from NHI Mgmt Group
Deepen Your Knowledge
Free weekly newsletter
Subscribe to the NHI & AI Identity Journal
The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.
Bonus 33% off our NHI Course when you subscribe.
Reviewed and updated by the NHIMG editorial team on October 12, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org