DOM-based Cross-Site Scripting occurs when JavaScript reads data from a controllable source (like URL parameters, hash, or localStorage) and writes it to a dangerous sink (like innerHTML) without proper validation.
Unlike reflected or stored XSS, DOM-based XSS happens entirely in the browser's DOM - the server is not involved. The vulnerability exists in client-side code.
This page reads content from the URL hash (location.hash) and displays it.
Modify the URL to inject malicious code.
Add these to the URL hash or use the input field above:
#<img src=x onerror=alert('DOM XSS')>
#<script>alert('DOM-based XSS!')</script>
#<iframe src="javascript:alert('XSS')"></iframe>
Vulnerable Code:
// โ VULNERABLE: Reading from location.hash and using innerHTML
window.addEventListener('hashchange', function() {
const hash = location.hash.substring(1); // Remove # symbol
document.getElementById('display').innerHTML = hash;
});
The problem: User-controlled data from location.hash is directly inserted into
the DOM using innerHTML, allowing HTML and JavaScript execution.
Secure Code:
// โ
SECURE: Using textContent instead
window.addEventListener('hashchange', function() {
const hash = location.hash.substring(1);
document.getElementById('display').textContent = hash;
});
// โ
SECURE: Or sanitize input
const sanitized = DOMPurify.sanitize(hash);
document.getElementById('display').innerHTML = sanitized;
location.hash - URL fragment (after #)location.search - URL query parametersdocument.referrer - Referring page URLwindow.name - Window name propertylocalStorage / sessionStorage - Browser storagedocument.cookie - HTTP cookieselement.innerHTML - Parses and executes HTML/JSelement.outerHTML - Similar to innerHTMLdocument.write() - Writes to document streameval() - Executes JavaScript codesetTimeout() / setInterval() - With string argumentsFunction() constructor - Creates functions from stringselement.setAttribute('onclick', ...) - Event handlers