TL;DR: Browser quirks in tag parsing, attribute handling, and DOM transforms can be chained into working XSS payloads that bypass blocklists and WAF signatures, according to PortSwigger research. The practical lesson is that canonicalisation, context-aware encoding, and browser-side testing matter more than pattern matching alone.
At a glance
What this is: NHI Mgmt Group's analysis, drawing on PortSwigger's blog post: HTML parsing quirks can still be turned into XSS payloads that evade blocklists and WAF signatures.
Why it matters: This matters because application security teams still need to validate how browsers actually interpret markup, not just how filters classify strings.
Context
Modern XSS defence often fails when teams assume the browser will treat malformed or unusual markup the same way a security filter does. HTML parsing is permissive, context sensitive, and full of transformation steps that can turn apparently inert text into executable script or fresh markup.
That gap matters for application security, input validation, and WAF design. Where browser behaviour becomes the source of truth, canonicalisation and context-aware encoding must be tested against real rendering behaviour, not just against regex-style blocklists.
Key questions
Q: What breaks when HTML input filtering only checks the raw string?
A: Raw-string filtering breaks when the browser reinterprets the same input into a different structure than the security control expected. Tag names, attributes, and separator characters can transform during parsing, which means a blocked string may still become executable after rendering. Defences have to inspect the browser-relevant context, not only the request body.
Q: Why do browser parsing quirks make XSS harder to stop than scanners suggest?
A: Scanners usually look for obvious script execution paths, but browsers interpret HTML in context. Features like innerHTML and iframe srcdoc can change how content is parsed, and that can create execution paths that appear cosmetic in static review. The result is a control gap between isolated vulnerability detection and real-world exploit composition.
Q: How can security teams find XSS issues that WAFs miss?
A: They should test with real browser rendering paths, not only with signature scans or static payload lists. Focus on places where data reaches executable sinks, then try unusual characters, transformed tag names, and DOM APIs that can reshape the input. If the browser accepts a form that the filter did not model, you have a control gap.
Q: Should organisations prioritise sanitisation or safer DOM APIs for XSS defence?
A: Safer DOM APIs should come first because they reduce the number of places where untrusted input can become executable. Sanitisation is still useful, but it is easier to get wrong when one input can be reused in multiple contexts. The strongest programme combines context-specific encoding with sink reduction and browser-based verification.
Technical breakdown
How tag-name parsing becomes an XSS primitive
Browsers normalise tag names in ways that defenders often do not model. In this research, the lowercased localName property became a useful source for recovering attacker-controlled text, while uppercase conversion and parsing transformations changed how payloads appeared to downstream logic. Once an attacker can influence a tag name and reach DOM properties that preserve or transform it differently, the tag itself can become a carrier for script-like material. The key technical issue is not that the browser is buggy in isolation, but that application filters and WAFs frequently inspect the wrong representation of the input.
Practical implication: test the rendered DOM representation, not just the raw request payload, before trusting a filter decision.
Why attributes and event handlers can reassemble blocked payloads
HTML attributes can be coerced into values that support execution paths even when direct script injection is blocked. The article shows that attributes can be read and repurposed through properties such as value, textContent, nodeValue, and getAttributeNode, then chained into event-handler execution. Because event handlers are already executable contexts, the attacker only needs a path to move data from a transformed attribute state into a callable JavaScript constructor or handler chain. This is a canonicalisation problem as much as an XSS problem: the browser and the security control are evaluating different strings.
Practical implication: review every place user input is reused inside executable attributes, not only inside obvious script blocks.
How obscure characters and DOM APIs defeat pattern matching
Line separators, paragraph separators, and other unusual characters can survive differently through browser parsing than through server-side sanitisation or signature checks. The article also shows that APIs such as setHTMLUnsafe and properties such as part or classList can create unexpected transform chains, where a benign-looking token becomes markup, a URL, or executable code. The security lesson is that the browser exposes multiple equivalent views of the same input, and blocklists usually only understand one of them. That gap is what makes bypasses durable.
Practical implication: validate sanitisation against browser-specific parsing behaviour and dangerous DOM sinks, not against a single input form.
Threat narrative
Attacker objective: The objective is to execute arbitrary JavaScript in the victim browser while evading content filters and signature-based defences.
- Entry occurs when attacker-controlled HTML reaches a browser context that relies on weak filtering or unsafe markup reuse.
- Credential or payload access is gained by placing executable material into tag names, attributes, or DOM-accessible properties that transform differently from the original input.
- Escalation happens when the transformed value is fed into event handlers, constructors, or unsafe DOM APIs that convert it into active JavaScript.
- Impact is cross-site scripting that bypasses blocklists and WAF signatures and executes in the victim's session context.
Breaches seen in the wild
- Shai Hulud npm malware campaign: Shai Hulud campaign: npm malware exposed secrets on GitHub.
Read and download The State of NHI & AI Agent Breach Report 2026, covering 200+ breaches impacting Non-Human Identities including AI Agents.
NHI Mgmt Group analysis
Parsing differentials are the real control gap: this article shows that the browser's parsed representation and the defender's filtered representation are often not the same object. That mismatch is why blocklists fail so often against modern XSS payloads. Teams that only test input strings miss the transformation layer where bypasses are created. Practitioners should treat canonicalisation as part of the attack surface, not just a preprocessing detail.
XSS resilience depends on sink awareness, not string hygiene: the examples work because user input is reused inside contexts that can become executable, including event handlers and unsafe DOM setters. This is an application-security governance problem, not just a developer mistake. Security teams need to map inputs to dangerous sinks and verify that each sink is either removed or strictly context-encoded. Practitioners should prioritise sink control over broader but weaker pattern matching.
HTML parsing quirks create a durable bypass class: once defenders assume that unusual characters, transformed tag names, and DOM properties are harmless, attackers gain room to build payloads that look broken to humans but valid to browsers. The article sharpens a useful concept here: representation gap exploitation, where the security layer inspects one form of data and the browser executes another. That concept belongs in application-security reviews and red-team test design. Practitioners should test for representation gaps explicitly.
WAF tuning alone cannot close this class of exposure: signatures are too brittle when the payload can be distributed across tag names, attributes, separators, and DOM properties. This does not make WAFs useless, but it does define their limit. The operational answer is secure output encoding, safe DOM APIs, and browser-driven testing in development and assurance workflows. Practitioners should expect bypasses to reappear whenever controls rely on textual matching alone.
What this signals
Representation gap exploitation: XSS controls fail when the application, the filter, and the browser each see a different version of the same input. That means assurance needs browser-accurate test cases, not just payload lists.
Security teams should assume that unusual tag names, attribute coercion, and unsafe DOM setters will continue to generate bypasses until the underlying rendering paths are removed or tightly constrained.
For practitioners
- Strengthen output encoding by context Encode data for the exact HTML, attribute, URL, or JavaScript context where it is rendered, rather than applying one generic escaping rule across all sinks.
- Inventory dangerous DOM sinks Identify places where application data reaches innerHTML, setHTMLUnsafe, event handlers, or other executable DOM APIs, then replace or constrain those sinks.
- Test browser parsing behaviour directly Build security tests around real browser rendering, including odd tag names, attribute coercion, and separator characters that may survive server-side sanitisation.
- Treat WAF rules as secondary controls Use WAF signatures as a detection and delay layer, but assume that parsing quirks will produce bypasses unless the application itself is fixed.
Key takeaways
- Browser parsing quirks still give attackers room to turn malformed HTML into executable script, which makes input shape alone an unreliable defence.
- The bypasses work because filters often inspect a different representation of the data than the browser actually executes.
- Application teams should reduce dangerous sinks, encode for context, and test against real browser parsing behaviour rather than trusting blocklists.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
MITRE ATT&CK addresses the attack and risk surface, while OWASP ASVS and NIST CSF 2.0 set the governance and control requirements practitioners need to meet.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V1 — Encoding and Sanitization | The article centres on output encoding and sanitisation failures across browser contexts. |
| V8 — Authorization | Unsafe DOM sinks can create execution paths that bypass intended application control boundaries. | |
| V15 — Secure Coding and Architecture | The research exposes design weaknesses in how applications route data into dangerous browser contexts. | |
| Recommendation — Apply V1 controls to encode untrusted data for each rendering context before it reaches the browser. Use V8 to prevent untrusted input from reaching executable DOM paths and privileged UI actions. Design out unsafe rendering patterns so untrusted input never reaches script-capable sinks. | ||
| NIST CSF 2.0 | PR.DS-10 — Confidentiality and Integrity Protection | XSS bypasses undermine the integrity of client-side processing and delivered content. |
| Recommendation — Protect client-side data flows so browser interpretation cannot subvert expected content integrity. | ||
| MITRE ATT&CK | TA0001;TA0002 — Initial Access; Execution | The payloads describe a path from injected input to browser-side code execution. |
| Recommendation — Map these payload patterns to TA0001 and TA0002 to improve detection and testing coverage. | ||
Key terms
- Canonicalisation: Canonicalisation is the practice of normalising output into a consistent, predictable form before it is exposed to callers. In privacy and security design, it helps remove hidden entropy, reduce ambiguity, and prevent internal implementation details from becoming externally observable signals.
- Dangerous DOM Sink: A dangerous DOM sink is a browser API or markup location where untrusted data can become executable code, active markup, or a security-sensitive action. Examples include event handlers and unsafe HTML insertion methods that interpret input rather than display it.
- Resolution Gap: The resolution gap is the distance between identifying a security issue and actually eliminating the risk it creates. In AppSec, it appears when scanners produce findings faster than teams can triage, fix, test, and deploy them. The gap is operational, not theoretical.
- Context-Aware Encoding: A defensive practice that transforms output based on where it will be used. HTML, SQL, shell, and template destinations each require different handling, and applying the wrong encoding can leave dangerous characters or instructions executable.
Deepen your knowledge
NHI Mgmt Group covers identity security, NHI governance, and agentic AI through independent research, practitioner guides, and the NHI Foundation Level course. Explore nhimg.org for resources that connect identity governance to the broader security disciplines your programme depends on.
Published by the NHIMG editorial team on August 25, 2026.
Updated on October 11, 2026.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org