A second DOM pass can reintroduce risk even when the original sanitizer was strong. If the application inserts elements, serializes the DOM, and then renders it again, parser differences may mutate the markup and revive blocked payloads. That can turn a supposedly safe message into active script execution inside the browser context.
What happens when sanitized HTML is modified and rendered again?
Sanitization is only reliable for the exact DOM or string state you actually render. If an application sanitizes HTML, then later re-serializes, mutates, or reparses it and renders it again, browser parsing differences can change the markup enough to bring back dangerous elements or attributes. The result is a second-pass injection problem, not a failed first pass.
Why a second DOM pass can undo earlier protection
The main failure mode is that sanitization happens on one representation of the content, while rendering happens on another. A library may remove a payload from the initial HTML string, but a later DOM insertion, serialization, or template pass can normalize the markup in a way the original sanitizer did not anticipate. That is why “sanitized once” is not the same as “safe throughout the flow.”
Parser behavior matters here. When markup is inserted into the DOM, then read back out and rendered again, the browser may repair broken tags, move nodes, decode entities, or reinterpret contexts. A payload that looked inert after the first pass can become executable once the application hands the content back to the browser in a different form.
What practitioners should verify before treating sanitized content as safe
What to verify: confirm whether the application ever round-trips user content through the DOM, innerHTML, a rich-text editor, server-side rendering, or a client-side template after sanitization. If it does, the security question is not only “Was it sanitized?” but also “Was it sanitized at the final render boundary?”
Decision rule: if content can be modified after sanitization, treat each re-render as a new trust boundary. Keep untrusted HTML as text or as a strictly controlled node model, and avoid rehydrating sanitized fragments into a context that can reinterpret them. The safest design is to sanitize as late as possible and render once.
Practitioner takeaway: The control fails when teams assume sanitization is permanent; in practice, the last parse before display is the one that matters most.
Risk and Threat Considerations
Re-rendering sanitized HTML creates an integrity gap between the content you inspected and the content the browser actually executes. That gap can reintroduce script execution, event handlers, or other active browser behavior even when the original payload was successfully blocked.
Failure mechanism: The application mutates, serializes, or reparses the content after sanitization, and browser parser differences or context changes transform previously inert markup into executable input.
Impact: Attackers can turn a trusted content flow into stored or reflected cross-site scripting, leading to session compromise, data theft, or unauthorized actions in the user’s browser context.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP API Security Top 10 and MITRE ATT&CK address the attack and risk surface, while 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 handling of untrusted HTML and output encoding at the render boundary. |
| V3 — Web Frontend Security | Addresses browser-side rendering behavior where sanitized markup can change on reparse. | |
| V15 — Secure Coding and Architecture | Applies to architectural decisions that prevent multi-pass HTML handling flaws. | |
| Recommendation — Apply V1 controls to keep untrusted HTML from being reinterpreted after sanitization. Validate frontend rendering flows so sanitized content is not reparsed into active script. Design a single-pass content flow that avoids reserializing sanitized HTML before display. | ||
| NIST SP 800-53 Rev 5 | SI-10 — Information Input Validation | Relevant because untrusted HTML must be validated and constrained before use. |
| SC-18 — Mobile Code | Relevant to controlling active browser content that may be reintroduced through parsing. | |
| SI-3 — Malicious Code Protection | Applies when modified HTML can revive script execution in the browser. | |
| Recommendation — Enforce input validation and context-aware handling for user-supplied HTML. Restrict active content so reparsed HTML cannot execute unintended code. Detect and block active script content that survives or reappears after processing. | ||
| CIS Controls v8 | CIS-16 — Application Software Security | Supports secure handling of user input and browser-facing content flows. |
| Recommendation — Test application content flows for HTML reparse and XSS reintroduction paths. | ||
| OWASP API Security Top 10 | API8 — Security Misconfiguration | Relevant when rendering and sanitization controls are configured unsafely across the application flow. |
| Recommendation — Harden content-processing configuration so sanitized HTML is not reintroduced as executable. | ||
| MITRE ATT&CK | T1059 — Command and Scripting Interpreter | Applicable when revived HTML payloads execute script in the browser context. |
| Recommendation — Map browser script execution paths to T1059 and hunt for injected active content. | ||
Practitioner Guidance
Where to start: Inventory every code path that touches user-controlled HTML after sanitization, including editor previews, WYSIWYG transforms, markdown conversion, DOM diffing, and client-side hydration. The highest-risk paths are the ones that silently move content between string and DOM forms.
What good looks like: Sanitized content should have a single, well-defined rendering path, with no later pass that can reinterpret it as richer HTML than originally allowed. If product requirements force re-rendering, the application should preserve a strict node allowlist and avoid free-form HTML reconstruction.
Common mistake: Teams often test the sanitizer in isolation and miss the later rendering step, which is where the payload can become active again. A passing sanitizer test is not enough if the application still performs a second parse before output.
Practitioner takeaway: Treat round-tripped HTML as untrusted until the final render boundary, because safety can be lost after the sanitizer has already done its job.
Related resources from NHI Mgmt Group
- What breaks when HTML is sanitized and then parsed or modified again before rendering?
- What happens when a privileged account, a local login path, and plaintext credentials exist in the same application?
- What happens when attackers combine open redirects, CAPTCHA gates, and spoofed login pages in the same phishing flow?
- What happens when an attacker can combine file disclosure, reflected XSS, and code injection in the same application?