flawopen.com/XSS/Types of XSS
Reflected vs. stored vs. DOM-based XSS: what's the difference?
Reflected, stored, and DOM-based describe different paths from untrusted input to an unsafe browser context. They can overlap: the key questions are where the value enters, whether it persists, which code renders it, and which user context receives it.
The three types
A request value is included in the response without context-appropriate encoding, and the browser interprets it as markup or script. An attacker may send a crafted link to a victim, but the underlying flaw is the unsafe rendering of request data. Fix the output context at the rendering sink.
Untrusted content is saved and later rendered unsafely to other users, for example in a comment or profile field. Each visitor who loads the affected content may receive the same unsafe browser context until the stored value or rendering path is corrected.
Client-side JavaScript reads an untrusted source (such as location.hash, a query parameter, or data returned by the server) and sends it to an unsafe DOM sink such as innerHTML. The value may never reach the server, but that is not required: DOM-based XSS describes the client-side source-to-sink path and can overlap with reflected or stored delivery. Fix the client-side data flow.
Why the distinction matters for fixing it
Fix XSS at the rendering sink with context-appropriate output encoding or a safe DOM API. Reflected and stored XSS often involve server-rendered output, but client-side rendering can also create the unsafe sink. For DOM-based XSS, prefer textContent over innerHTML for text; if rich HTML is required, use a maintained sanitizer with an explicit policy. Do not treat server-side encoding as a substitute for reviewing client-side source-to-sink flows.
These labels can overlap
Reflected and stored describe how input reaches a page and whether it persists. DOM-based describes a client-side source-to-sink path. They are not mutually exclusive: persisted profile text inserted by client code into innerHTML can be both stored and DOM-based XSS.
DOM-based XSS: unsafe sink and text-only rendering
const value = new URLSearchParams(location.search).get("q") ?? "";
target.innerHTML = value;
const value = new URLSearchParams(location.search).get("q") ?? "";
target.textContent = value;
References
- OWASP XSS Prevention Cheat Sheet
- OWASP DOM-based XSS Prevention Cheat Sheet
- flawopen.com — Cross-Site Scripting (all languages)