[The page](https://portswigger.net/web-security/dom-based/dom-clobbering/lab-dom-xss-exploiting-dom-clobbering) uses a risky fallback pattern.
### What’s happening
This page renders comments client-side:
```html
<script src="/resources/js/domPurify-2.0.15.js"></script>
<script src="/resources/js/loadCommentsWithDomClobbering.js"></script>
<script>loadComments('/post/comment')</script>
```
`loadCommentsWithDomClobbering.js` sanitizes comment HTML with DOMPurify, injects it into the DOM, and uses a dangerous pattern like:
```js
let defaultAvatar = window.defaultAvatar || { avatar: '/resources/images/avatarDefault.svg' }
```
Because browsers can expose elements with `id="defaultAvatar"` as `window.defaultAvatar`, attacker HTML can **clobber** that global and control what `defaultAvatar` becomes.
---
## Steps to solve
### 1) Post the clobbering payload (first comment)
On any blog post, submit a comment with:
```html
<a id=defaultAvatar><a id=defaultAvatar name=avatar href="cid:"onerror=alert(1)//">
```
**Why it works (tight):**
* Two elements with the same `id=defaultAvatar` → Chrome exposes `window.defaultAvatar` as a **DOM collection**.
* `name=avatar` on the second anchor → creates `window.defaultAvatar.avatar`.
* That `.avatar` resolves to the anchor element, and when later used as a string, Chrome effectively uses its **href**.
* DOMPurify allows `cid:` and keeps `"`, which becomes a real `"` at runtime:
* `cid:"onerror=alert(1)//` → `cid:"onerror=alert(1)//`
So the app ends up consuming an “avatar URL” that contains an injected quote.
---
### 2) Trigger a re-render (second comment)
Add a **second** comment with any text (e.g., `test`).
This forces the comment rendering code to run again **after** the global is already clobbered.
---
### 3) Observe XSS
On the next render/load cycle, when the app uses the clobbered `defaultAvatar.avatar` to build an image element (e.g., `img src="...")`, the injected `"` breaks out of the `src` attribute and injects:
`onerror=alert(1)//`
→ `alert(1)` fires.
---
## Key takeaway
The root bug isn’t “DOMPurify failed.” It’s that the app treats `window.defaultAvatar` as trusted configuration (`window.defaultAvatar || {...}`), so user-controlled DOM can override it (DOM clobbering).