DOM-Based Attacks

Overview

DOM-based attacks happen when attacker-controlled input reaches browser-side JavaScript that updates the Document Object Model without proper validation or sanitization. In modern frontend-heavy applications, this can lead to DOM XSS, client-side open redirect, authorization bypasses, and other client-side trust failures even when the backend does not directly reflect the payload. These notes cover the DOM model, SPA behavior, the source-and-sink mindset, and the practical difference between conventional and DOM-based XSS.

What the DOM Is

The Document Object Model is the browser’s programmatic representation of the loaded page. Once HTML is parsed, JavaScript can inspect and modify elements, attributes, text, and layout through that structure.

<html>
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1>Hello Moon!</h1>
        <p>The earth says hello!</p>
    </body>
</html>

If an attacker can influence how JavaScript modifies that DOM, they can alter what the user sees or how the application behaves in the browser.

Why Modern Frontends Matter

Traditional web apps often rebuilt the full DOM on each server response. Modern single-page applications instead load the frontend once and then mutate the DOM continuously with JavaScript based on API responses and browser state.

That shift makes client-side logic much more security-relevant because important rendering and workflow decisions now happen after the page is already loaded.

Security Boundary Confusion

A common frontend mistake is treating client-side controls as if they were real security controls. For example, disabling an “edit” button in JavaScript may improve user experience, but it does not enforce authorization. A user can re-enable the button in the browser and still make the request.

Server-side authorization checks are still mandatory, even in a polished SPA.

Frontend Validation Gaps

Another common issue is responsibility drift between frontend and backend teams. The frontend assumes the backend will sanitize; the backend assumes the frontend already sanitized. In practice, neither side takes full ownership, and unsafe data reaches the DOM.

This is how modern apps end up with DOM XSS, client-side redirects, and frontend trust issues even when the API layer appears clean.

Source and Sink

The most useful way to analyze DOM-based attacks is with the source and sink model.

If attacker-controlled data can move from a source to a dangerous sink without safe handling, a DOM-based vulnerability may exist.

Common Sources

Common Sinks

DOM-Based Open Redirect

A simple DOM-based attack is open redirect. Suppose JavaScript reads a fragment from the URL and uses it as a navigation target:

goto = location.hash.slice(1)
if (goto.startsWith('https:')) {
    location = goto;
}

An attacker can then craft a URL such as:

https://realwebsite.com/#https://attacker.com

Once the page loads, the browser-side code redirects the user to the attacker-controlled site.

DOM XSS

DOM XSS is the most dangerous DOM-based attack because it allows attacker-controlled JavaScript execution in the browser without the backend necessarily reflecting the payload directly in the HTML response.

The usual pattern is a controllable source, such as a fragment in the URL, reaching a dangerous sink such as HTML insertion or a permissive JavaScript selector.

jQuery Example

Consider the following fragment-driven jQuery behavior:

$(window).on('hashchange', function() {
    var element = $(location.hash);
    element[0].scrollIntoView();
});

If attacker-controlled content is fed into the $() sink unsafely, a payload in the fragment may become executable, depending on the environment and exact jQuery behavior.

The browser-side code is the vulnerable part here, not the server-side response template.

Why Weaponisation Is Harder

Many DOM XSS proofs only execute in the attacker’s own browser first. That alone is not useful. The real challenge is delivery: getting another victim’s browser to receive the attacker-controlled source value in a realistic workflow.

That usually means combining the DOM sink with a reflected or stored delivery path, such as:

DOM XSS vs Conventional XSS

The key difference is where the sink lives.

This distinction matters because the remediation is different. Server-side HTML encoding may fix one class of issue while leaving the client-side sink untouched.

Testing Workflow

What To Look For

Mitigation

Key Takeaways