Reflected XSS returns malicious input immediately in the server response, usually through a crafted link. Stored XSS saves the payload first and serves it later to other users. DOM-based XSS never needs the backend at all, because unsafe client-side JavaScript places untrusted input into the DOM in a way the browser can execute.
How reflected, stored, and DOM-based XSS differ in practice
Reflected XSS, stored XSS, and DOM-based XSS are all cross-site scripting variants, but they differ in where the payload is handled and when execution happens. That difference matters because it changes where you look for the flaw, how the payload reaches the victim, and which controls must be correct to stop it.
Reflected XSS is usually tied to a single request-response flow, so the attacker’s input is sent to the server and reflected back in the page immediately. Stored XSS persists in an application data store or content repository, so the malicious input becomes part of the normal page content for later visitors. DOM-based XSS is a client-side issue: the browser executes unsafe JavaScript that reads untrusted data and writes it into the DOM in an executable way.
The practical distinction is not just where the payload sits, but where the trust boundary is broken. Reflected and stored XSS are often visible in server-side rendering or content handling, while DOM-based XSS often survives even when the server response looks harmless because the browser-side code creates the dangerous sink after page load.
Why the execution path changes the defence
Each XSS type points to a different inspection path. For reflected XSS, test inputs that return in HTML, attributes, scripts, or error messages, especially where the application echoes query parameters or form values. For stored XSS, inspect every place user-controlled content is saved, transformed, and later displayed, including comments, profiles, tickets, chat messages, and admin views. For DOM-based XSS, review JavaScript sources and sinks together, because the bug may only appear once client-side code combines data from the URL, fragment, storage, or message events with an unsafe sink.
That is why the best fix depends on the execution context. Output encoding must match the destination context, HTML sanitisation is relevant when user-generated markup is allowed, and dangerous DOM sinks must be removed or wrapped in safer APIs. For DOM-based XSS, server-side filtering alone is often insufficient if the browser script still turns data into executable markup.
Good defensive design also depends on narrowing where untrusted data can flow. The strongest pattern is to treat all user-controlled input as inert data until it is explicitly validated, encoded, sanitised, or placed into a non-executable DOM context. Browser-side protections such as Trusted Types and a well-tuned Content Security Policy can reduce the blast radius, but they do not replace correct handling in the application code.
What to verify when you classify the XSS variant
Start by asking where the payload becomes dangerous. If the malicious input is returned directly in the server response, you are dealing with a reflected path. If it is stored first and later rendered to another user, it is stored XSS. If the server response is not the execution point and the browser-side script creates the attack surface, the issue is DOM-based XSS.
Also verify whether the vulnerable behaviour is in rendering, storage, or client-side mutation. A page can contain more than one XSS type at the same time, and a fix for one path does not necessarily close the others. This is especially common in applications that mix server-rendered HTML with heavy front-end scripting, where one route is corrected but another sink remains reachable.
When triaging, preserve the evidence needed to prove the execution path, including the exact input, where it was reflected or persisted, and the JavaScript sink involved. That evidence is what separates a generic scripting issue from a specific remediation plan.
Risk and Threat Considerations
XSS is dangerous because it turns ordinary application trust into attacker-controlled execution in a victim’s browser. Reflected XSS often supports quick phishing-style delivery through a crafted link, stored XSS can scale to many victims over time, and DOM-based XSS can be harder to spot because the server response may appear clean while the browser still executes the payload.
Failure mechanism: The application places untrusted data into an executable context without correct context-aware encoding, sanitisation, or safe DOM handling, allowing attacker-supplied JavaScript to run in the victim’s origin.
Impact: The attacker may steal sessions, perform actions as the user, alter content, trigger sensitive requests, or pivot into higher-value accounts and workflows that trust the browser session.
Standards & Framework Alignment
This section maps relevant standards and security frameworks to the operational risks and controls described in this guidance.
OWASP ASVS provides the primary governance reference for this topic.
| Framework | Control / Reference | Relevance |
|---|---|---|
| OWASP ASVS | V1 — Encoding and Sanitization | XSS mitigation depends on correct output encoding and sanitisation in the target context. |
| V3 — Web Frontend Security | DOM-based XSS is a client-side execution flaw in browser-facing code and DOM handling. | |
| V16 — Security Logging and Error Handling | XSS testing and verification benefit from logging the input path and error conditions that expose sinks. | |
| Recommendation — Apply V1 controls to encode and sanitise untrusted content before it reaches executable contexts. Review browser-side code paths and eliminate unsafe DOM sinks that execute untrusted data. Log suspicious input handling and sink failures so XSS attempts can be detected and investigated. | ||
Practitioner Guidance
What to verify: Check both the server response and the front-end code path before declaring a fix complete. If the payload can still reach an executable sink through client-side JavaScript, the application remains vulnerable even if the initial HTML response looks escaped.
Decision rule: If user input must be displayed, use the safest context-specific encoding or sanitisation available for that destination. If the code must write dynamic content into the DOM, prefer non-executable DOM APIs and restrict dangerous sinks such as raw HTML insertion.
Practitioner takeaway: Treat the XSS category as three different execution paths, not one generic bug, because the right remediation depends on where untrusted data first becomes executable.
Related resources from NHI Mgmt Group
- Guide: Cross-Site Scripting (XSS) Prevention Guide
- Dom-based Xss
- What are the signs that a web application may be vulnerable to reflected or DOM-based XSS?
- Why do stored XSS and DOM-based XSS become especially dangerous when an application uses session-based authentication?
- Should teams prioritise DOM-based XSS or stored XSS first?
Deepen Your Knowledge
Free weekly newsletter
Subscribe to the NHI & AI Identity Journal
The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.
Bonus 33% off our NHI Course when you subscribe.
Reviewed and updated by the NHIMG editorial team on October 31, 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org