Cross Site Scripting (DOM Based)
ID |
cross_site_scripting_dom_based |
Severity |
critical |
Kind |
Cross-Site Scripting |
CWE |
79 |
Description
DOM-based Cross-Site Scripting (XSS) is a client-side vulnerability that occurs when JavaScript in a web page reads data from an attacker-controllable source (such as the URL, document.referrer, or window.name) and passes it to a dangerous sink that supports dynamic code execution (such as eval(), innerHTML, or document.write()). Unlike reflected or stored XSS, the malicious payload never reaches the server; instead, the attack modifies the DOM environment in the victim’s browser so that legitimate client-side scripts execute in an unexpected manner. This makes DOM-based XSS particularly difficult to detect with server-side security controls, since the page response itself does not change — only the client-side execution differs due to the malicious modifications.
Non-persistent attacks and DOM-based attacks require a user to either visit a specially crafted link laced with malicious code, or visit a malicious web page containing a web form, which when posted to the vulnerable site, will mount the attack. Using a malicious form will oftentimes take place when the vulnerable resource only accepts HTTP POST requests. In such a case, the form can be submitted automatically, without the victim’s knowledge (e.g. by using JavaScript). Upon clicking on the malicious link or submitting the malicious form, the XSS payload will get echoed back and will get interpreted by the user’s browser and execute. Another technique to send almost arbitrary requests (GET and POST) is by using an embedded client, such as Adobe Flash.
Rationale
Because the malicious JavaScript executes in the context of the trusted domain, an attacker can hijack user sessions by stealing session cookies via document.cookie, perform actions on behalf of the victim through authenticated API calls, capture keystrokes, redirect users to phishing pages, or deface the application’s content in real time. Common exploitation vectors include crafting URLs with malicious fragments or query parameters that are read by client-side code and passed unsafely into the DOM, making the attack easy to deliver via phishing emails, social engineering, or malicious advertisements. The client-side nature of DOM-based XSS means it can bypass server-side web application firewalls and input filters entirely, increasing the risk that the vulnerability remains undetected while actively exploited.
Remediation
Use safe DOM output methods. The most effective fix for DOM-based XSS is to avoid dangerous sinks altogether. Instead of using innerHTML, prefer innerText or textContent, which treat inserted content as plain text and do not parse HTML tags. This prevents injected scripts from executing.
Avoid dangerous JavaScript functions. Never pass user-controlled input to functions such as eval(), new Function(), setTimeout() with string arguments, or setInterval() with string arguments. These functions interpret strings as executable code and open the door to remote code execution. If you find yourself needing eval(), it is usually an indication of a design problem that should be addressed differently.
Sanitize when dynamic HTML is unavoidable. In limited cases where innerHTML or similar sinks must be used, sanitize all untrusted data with a well-established library such as DOMPurify before inserting it into the DOM. Never rely on custom sanitization routines, as they are prone to bypasses.
Apply context-aware output encoding. Encode user-controllable data directly before it is written to the page. Values inside a JavaScript string require different escaping than values in an HTML context. Consult the OWASP XSS Prevention Cheat Sheet for the specific encoding rules applicable to each output context.
Leverage modern browser security features. Adopt a strict Content Security Policy (CSP) that disallows inline scripts and restricts script sources to trusted origins. Where supported, use the Trusted Types API to restrict dangerous DOM sinks so they only accept content that has been explicitly approved through a Trusted Types policy, forcing developers to centralize and sanitize all dynamic HTML generation.
Set the HttpOnly and Secure flags on session cookies. Marking cookies as HttpOnly prevents client-side scripts from accessing them via document.cookie, reducing the impact of any XSS exploitation. The Secure flag ensures cookies are only transmitted over HTTPS.
Validate all input on the server side as well. Even though DOM-based XSS occurs on the client, server-side validation of inputs using an allow-list approach reduces the overall attack surface and provides defense in depth. Do not rely exclusively on deny lists, as they are easily bypassed by encoding tricks and filter evasion techniques.
References
-
Cross-Site Scripting, in OWASP Community.