Vulnerability
DOM-based XSS occurs entirely within client-side code.
Instead of the server receiving malicious input and reflecting or storing it in an HTTP response, the browser's own JavaScript takes attacker-influenced data from a client-side source and passes it into a dangerous sink without applying the appropriate context-specific handling.
Common sources include values the browser exposes to JavaScript, such as:
Dangerous sinks include APIs that parse attacker-controlled data as HTML or execute it as code, such as:
innerHTML
outerHTML
insertAdjacentHTML()
eval()
A simple vulnerable example:
// Vulnerable client-side code
const name = location.hash.substring(1);
// Example attacker-controlled value:
// #<img src=x onerror=alert(document.cookie)>
document.getElementById('greeting').innerHTML = 'Hello, ' + name;
An attacker can construct a URL such as:
https://example.com/page#<img src=x onerror=alert(document.cookie)>
The important difference is what happens to the data.
Attacker controls the URL fragment
β
Victim opens the URL
β
Browser loads: https://example.com/page
β
The fragment after # is NOT sent in the HTTP request
β
Client-side JavaScript reads: location.hash
β
Attacker-controlled data flows into: innerHTML
β
Browser interprets the injected content
The critical detail is that the URL fragmentβeverything after #βis not sent to the server as part of the HTTP request.
The server may therefore receive a request that appears completely harmless:
GET /page HTTP/1.1
Host: example.com
while the victim's browser is actually processing:
#<img src=x onerror=alert(document.cookie)>
entirely on the client side.
This has important implications for detection.
If the attacker-controlled value exists only in the fragment, server-side request logging cannot record that value because the browser never sends it. Likewise, a server-side WAF or input-validation layer cannot inspect or sanitize data that never reaches the server in the first place.
Attacker-controlled fragment
β
Not sent to server
βββ Server logs cannot see it
βββ Server-side validation cannot process it
βββ Server-side filtering cannot directly remove it
β
Browser JavaScript receives it
β
Potentially dangerous source β sink flow
That does not mean every DOM-based XSS vulnerability is invisible to every server-side defense. Some DOM XSS sources, such as query parameters, may originate in data that does pass through the server before becoming available to client-side code.
The important point is more precise:
A DOM-based XSS vulnerability can exist entirely in the browser, and when the attacker-controlled input never reaches the server as with location.hash server-side controls cannot inspect that input at all.
Finding these vulnerabilities therefore requires examining the client-side application itself.
The key question is:
Can attacker-influenced data flow from a browser-controlled source into a dangerous sink?
SOURCE
location.hash
document.referrer
window.name
URL parameters
postMessage data
other attacker-influenced input
β
Client-side JavaScript
β
SINK
innerHTML
outerHTML
insertAdjacentHTML()
eval()
or another dangerous browser API
β
Potential DOM-based XSS
This is what distinguishes DOM-based XSS from the other two major categories.
Reflected XSS:
Attacker input
β
Sent to server
β
Server reflects it into the response
β
Browser executes it
Stored XSS:
Attacker input
β
Server stores it
β
Later included in a response
β
Browser executes it
DOM-Based XSS:
Attacker-controlled data
β
Client-side JavaScript reads it
β
JavaScript inserts it into a dangerous sink
β
Browser executes or interprets it
The vulnerability is still fundamentally about the same thing: untrusted data reaching an executable browser context without appropriate handling.