DOM-based XSS
No server involved — the payload never leaves the browser. innerHTML, document.write, eval on a URL fragment — the client-side sink is the only boundary.
No server involved — the payload never leaves the browser. innerHTML, document.write, eval on a URL fragment — the client-side sink is the only boundary.
DOM-based XSS is a purely client-side variant of cross-site scripting. Unlike reflected or stored XSS, the server is never directly involved in the injection — the vulnerability exists entirely in the browser's own JavaScript code. The payload is read from a client-side source such as the URL fragment or window.nameand written to an HTML sink like innerHTML or document.write.
DOM XSS exploits the separation between server-rendered HTML and client-side JavaScript. A page may be served safely from the server, but if its JavaScript reads from a browser-controlled source and writes to an HTML sink, an attacker can inject code that the server never detects. The URL hash fragment (#payload) is the most popular source because it is not sent to the server at all — server-side defences and web application firewalls cannot inspect it.
Common vulnerable patterns include single-page applications that read route parameters from the hash, page preview features that write a user-supplied name into the DOM, and search widgets that update the page content via innerHTML based on URL parameters. The attack surface grows with every third-party script and browser extension that has access to the DOM.
Type a payload into the URL hash field below. The profile page reads the hash and writes it into the page using innerHTML. In vulnerable mode the browser executes whatever HTML you supply. Safe mode uses textContent instead, which treats the payload as plain text.
Member since 2024
// VULNERABLE — innerHTML parses HTML
element.innerHTML = hash;In 2014, security researcher Patrik Hultqvist discovered a DOM-based XSS vulnerability in eBay's listing description page. eBay's server-side code rendered the listing safely, but a JavaScript widget on the page read the URL hash and wrote it into the DOM via innerHTML. An attacker could craft a URL like /item/123#<script>… and the payload would execute in the context of the eBay domain. Because the hash fragment never reaches the server, eBay's server-side filters and WAF could not detect or block the attack.
This case highlights a critical blind spot: server-side security measures — input validation, output encoding, WAF rules — are invisible to client-side JavaScript that reads from sources the server never sees. Modern single-page applications that rely on hash-based routing are particularly susceptible because every route change triggers DOM manipulation from a client-side source.
// VULNERABLE — reads hash and writes to innerHTML
const name = location.hash.slice(1);
document.getElementById('greeting').innerHTML =
'Hello, ' + name + '!';
// SAFE — uses textContent instead of innerHTML
document.getElementById('greeting').textContent =
'Hello, ' + name + '!';
// SAFE — sanitise before using innerHTML
import DOMPurify from 'dompurify';
document.getElementById('greeting').innerHTML =
'Hello, ' + DOMPurify.sanitize(name) + '!';The most effective defence against DOM XSS is to avoid dangerous DOM sinks altogether. Replace innerHTML with textContent and document.write with safe DOM manipulation APIs. When sinks are unavoidable — for example, rendering rich text — pass the value through a dedicated sanitisation library like DOMPurify that strips dangerous tags and attributes.
Treat every client-side source as untrusted. Validate URL fragments against a whitelist of expected formats before using them in any DOM operation. For hash-based routing in SPAs, decode and validate the path component before rendering it. And because third-party JavaScript runs with the same privileges as first-party code, vet every script your application loads — a compromised CDN or widget can introduce DOM XSS without touching your own code.
innerHTML with textContent wherever possible.1.What makes DOM XSS different from reflected and stored XSS?
2.Which of the following is a DOM XSS sink?
3.Why was the eBay 2014 DOM XSS vulnerability difficult for server-side defences to detect?