XSS Explained
Cross-site scripting is a vulnerability where an application includes attacker-controlled data in a page without proper encoding, causing the victim's browser to execute it as script. Reflected XSS returns in the immediate response, stored XSS persists server-side and fires for other users, and DOM-based XSS never touches the server because the flaw is in client-side JavaScript.
The three types matter because they are found differently and they have different impact. Treating them as one bug is why testers miss the DOM-based ones entirely.
The three types
| Reflected | Stored | DOM-based | |
|---|---|---|---|
| Payload travels via | Request, returned immediately | Server storage | Never reaches the server |
| Victim | Whoever opens the link | Every user who views the content | Whoever opens the link |
| Requires user action | Yes, click a link | No | Yes, usually |
| Typical severity | Medium | High to critical | Medium to high |
| Found by scanners | Usually | Often | Frequently missed |
Reflected
Input in the request is echoed straight back into the response. Search boxes and error messages are the classic locations. Requires delivering a crafted link to the victim, which caps the impact but does not eliminate it.
Stored
The payload is saved server-side and served to every user who loads the affected content. Comments, profile fields, support tickets, product reviews. No link delivery needed, so this is almost always the most severe of the three.
The variant testers underrate: stored XSS in an admin-visible field. A payload submitted through a public support form that fires when an administrator opens the ticket queue is an account takeover of the highest privileged user in the application.
DOM-based
The vulnerability is entirely in client-side JavaScript. Data flows from a source such as the URL fragment into a dangerous sink such as innerHTML or eval, without ever being sent to the server.
This is missed most often because server-side testing sees nothing. If the payload is in the fragment after the hash, it never leaves the browser, so proxy logs and server logs are both clean.
How to find each one
Reflected and stored: inject a unique marker string into every parameter and field, then search the rendered response for it. Where it appears, examine the context. Is it inside an HTML body, an attribute, a script block, a URL? Context determines the payload, and this is the step people skip.
DOM-based: read the JavaScript. Trace sources into sinks.
| Sources | Sinks |
|---|---|
| location.hash, location.search | innerHTML, outerHTML |
| document.referrer | document.write |
| window.name | eval, setTimeout with a string |
| postMessage data | jQuery .html(), element.src |
Why context matters more than payload
The same input lands in different places and needs different escaping. Inside an HTML body, inside an attribute value, inside an existing script block, and inside a URL attribute are four different problems with four different payload shapes.
A tester who only tries one generic payload and moves on will report "not vulnerable" on applications that are. Identify where your marker landed first, then build the payload for that context.
Impact beyond the alert box
Reporting XSS as "an alert box popped" gets it downgraded and ignored. Demonstrate what an attacker actually gets:
- Session token theft where cookies are not HttpOnly
- Performing authenticated actions as the victim, which works even with HttpOnly set
- Credential capture through an injected fake login form
- Keylogging within the page
- Chaining to admin account takeover through stored XSS in an admin-visible field
Business impact framing is what gets the fix funded. Structure for writing it up is in how to write a VAPT report.
Defences that work
- Context-aware output encoding. The actual fix. Encode at the point of output, for the context it is being output into. Not at input.
- Avoid dangerous sinks. Use textContent instead of innerHTML wherever the content is not meant to be markup.
- Content Security Policy. Defence in depth, not a fix. A strict CSP limits what a successful injection achieves.
- HttpOnly cookies. Stops token theft. Does not stop the attacker acting as the user in the page.
- Framework defaults. Modern frameworks encode by default. Most XSS in framework applications comes from explicitly bypassing that, such as dangerouslySetInnerHTML.
Input filtering and blocklists are not on this list on purpose. They are bypassed routinely and they give teams false confidence.
Where XSS sits in testing
XSS is a standing item in web application assessment and appears in most Indian engagement scopes, since compliance testing routinely requires OWASP coverage. Context in CERT-In VAPT requirements, and it comes up regularly in hiring, covered in VAPT interview questions.
Practise this
Find all three types by hand before automating anything. Scanners find reflected XSS reliably, stored XSS often, and DOM-based XSS poorly, which is exactly why manual skill here still pays.
Hacklido is free and has web challenges covering all three. The TCVE VAPT program covers web application security in depth with live sessions.
Frequently asked questions
What are the three types of XSS?
Reflected, which returns in the immediate response; stored, which persists server-side and fires for other users; and DOM-based, where the flaw is in client-side JavaScript and the payload may never reach the server.
Which type of XSS is most dangerous?
Stored XSS, because it fires for every user who views the affected content with no link delivery needed. Stored XSS in an admin-visible field is often the most severe variant.
Why is DOM-based XSS hard to find?
Because the payload can stay entirely in the browser, often in the URL fragment, so server logs and proxy traffic show nothing. Finding it requires reading the client-side JavaScript and tracing sources into sinks.
Does Content Security Policy stop XSS?
It limits what a successful injection can do but does not fix the underlying flaw. The actual fix is context-aware output encoding at the point of output.
Do HttpOnly cookies prevent XSS?
They prevent session token theft via script but do not prevent the attacker performing authenticated actions as the victim within the page.
See the full VAPT syllabus
Live instructor led training, hands on labs and a verifiable certificate. Or start free on Hacklido before paying anyone.
See the full VAPT syllabus