Strobesstrobes
Platform
Solutions
Resources
Customers
Company
Pricing
Book a Demo
Strobesstrobes

Strobes connects every exposure signal to autonomous action, so security teams fix what matters, prove what works, and stop chasing noise.

Book a DemoTalk to an expert
ISO 27001SOC 2CREST
  • Platform
  • Platform Overview
  • Agentic Exposure Management
  • AI Agents
  • Integrations
  • API & Developers
  • Workflows & Automation
  • Analytics & Reporting
  • Solutions
  • Exposure Assessment (EAP)
  • Attack Surface Management
  • Application Security Posture
  • Risk-Based Vulnerability Management
  • Adversarial Exposure Validation (AEV)
  • AI Pentesting
  • Pentesting as a Service
  • CTEM Framework
  • By Industry
  • Financial Institutions
  • Technology
  • Retail
  • Healthcare
  • Manufacturing
  • By Roles
  • CISOs
  • Security Directors
  • Cloud Security Leaders
  • App Sec Leaders
  • Resources
  • Blog
  • Customer Stories
  • eBooks
  • Datasheets
  • Videos & Demos
  • Exposure Management Academy
  • CTEM Maturity Assessment
  • Pentest Health Check
  • Security Tool ROI Calculator
  • Company
  • About Strobes
  • Meet the Team
  • Trust & Security
  • Contact Us
  • Careers
  • Become a Partner
  • Technology Partner
  • Partner Deal Registration
  • Press Release

Weekly insight for security leaders

CTEM research, agentic AI trends, and what's actually moving the needle.

© 2026 Strobes Security Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyAccessibilitySitemap
Back to Blog
XSS Explained: Types, Testing, and Prevention
Application SecurityOWASP

XSS Explained: Types, Testing, and Prevention

Likhil ChekuriFebruary 9, 20257 min read

Table of Contents

  • What is cross site scripting (XSS)?
  • What are the types of XSS?
  • How do you test for XSS?
  • Why is stored XSS more dangerous than reflected?
  • How do you prevent XSS?
  • Frequently asked questions
  • Sources and references

Authors

L
Likhil Chekuri

Share

Table of Contents

  • What is cross site scripting (XSS)?
  • What are the types of XSS?
  • How do you test for XSS?
  • Why is stored XSS more dangerous than reflected?
  • How do you prevent XSS?
  • Frequently asked questions
  • Sources and references

Authors

L
Likhil Chekuri

Share

TL;DR
  • ✓Cross Site Scripting (XSS) is the injection of attacker-controlled script into a page so it runs in another user's browser, in their session and origin.
  • ✓There are three core types: reflected (payload echoed from the request), stored (payload persisted and served to others), and DOM-based (sink reached entirely client-side).
  • ✓XSS sits inside A03:2021 Injection in the OWASP Top 10 and is tested under WSTG-INPV-01 (reflected), -02 (stored), and WSTG-CLNT-01 (DOM).
  • ✓Test with Burp Suite plus dalfox or XSStrike for fuzzing, and read JavaScript by hand for DOM sinks like innerHTML and document.write.
  • ✓Prevention is context-aware output encoding, a strict Content-Security-Policy, and safe DOM APIs like textContent instead of innerHTML.

Cross Site Scripting (XSS) is one of the oldest and still most common web vulnerabilities, consistently appearing across bug bounty programs and pentest reports because almost every app handles user input that ends up rendered in a browser. At its core, XSS means your script runs in someone else's browser, inside their origin and with their session, which is enough to steal cookies, perform actions as them, or rewrite the page.

This guide covers the three types of XSS with concrete vectors, how to test each one with Burp Suite, dalfox, and XSStrike, how they map to the OWASP Top 10 and WSTG, and the encoding and CSP controls that genuinely prevent it. XSS lives under A03:2021 Injection and WSTG-INPV-01/02 and WSTG-CLNT-01.

What is cross site scripting (XSS)?

XSS is a vulnerability that lets an attacker inject client-side script into content served to other users, so the browser executes attacker code as if the site wrote it. Because the script runs in the victim's origin, it can read cookies and DOM-stored tokens, make authenticated requests, log keystrokes, or fully rewrite the page for phishing.

The root cause is always the same: untrusted input reaches an output context (HTML, an attribute, a JavaScript string, a URL) without the right encoding for that context. The differences between XSS types come down to where the payload travels before it executes, which is why understanding the types changes how you test. XSS is a fixture of the OWASP Top 10 under A03 Injection.

What are the types of XSS?

There are three primary types of XSS, separated by how the payload reaches the victim: reflected, stored, and DOM-based. A fourth label, blind XSS, is just stored XSS that fires in a context you can't see, like an admin log viewer.

  • Reflected XSS (WSTG-INPV-01): the payload is in the request (a query parameter, for example) and echoed straight back in the response. It needs the victim to click a crafted link.
  • Stored XSS (WSTG-INPV-02): the payload is saved server-side (a comment, profile field, support ticket) and served to every user who views it. Highest impact because no per-victim link is needed.
  • DOM-based XSS (WSTG-CLNT-01): the vulnerability is entirely in client-side JavaScript; a source like location.hash flows into a sink like innerHTML without the server ever seeing the payload.
Reflected vs Stored vs DOM-based XSS
TypeWhere payload livesUser interactionWSTG ID
ReflectedIn the request, echoed in responseVictim clicks crafted linkWSTG-INPV-01
StoredPersisted server-side, served to allNone neededWSTG-INPV-02
DOM-basedClient-side JS source to sinkOften via crafted URL fragmentWSTG-CLNT-01

How do you test for XSS?

Test by injecting context-breaking payloads into every input and observing whether they execute, then tailor the payload to the exact output context. Start with a unique marker string, find where it lands in the response, and craft a payload that breaks out of that context. XSS testing also fits inside the broader OWASP WSTG methodology.

# Classic probes by context
<script>alert(document.domain)</script>        # raw HTML body
"><svg onload=alert(1)>                       # break out of an attribute
';alert(1);//                                  # inside a JS string
javascript:alert(1)                            # href/src sink

# Automated fuzzing
dalfox url "https://target/search?q=FUZZ"
python3 xsstrike.py -u "https://target/search?q=test"

For DOM XSS, skip the server and read the JavaScript: trace sources (location, document.referrer, postMessage) to sinks (innerHTML, eval, document.write). Burp Suite ties it together for proxying and manual replay, and dalfox or XSStrike accelerate the fuzzing. These belong in your web app test cases.

Why is stored XSS more dangerous than reflected?

Stored XSS is generally the most severe type because the payload is served to every user who views the affected content, with no need to trick anyone into clicking a crafted link. A single injected comment or profile field can hit thousands of sessions automatically.

That changes both impact and exploitability. Reflected XSS requires social engineering to deliver the malicious URL and is often dampened by browser-side filters or short-lived links. Stored XSS spreads on its own and frequently lands in privileged contexts (an admin dashboard rendering user-submitted data), where stealing a session means account takeover of staff. In CVSS terms, stored XSS routinely scores higher because the attack complexity and user-interaction requirements drop.

How do you prevent XSS?

Prevent XSS with context-aware output encoding as the primary control, then layer a Content-Security-Policy and safe DOM APIs on top. Encode every piece of untrusted data for the exact context it lands in: HTML-entity-encode for body text, attribute-encode inside attributes, and JavaScript-encode inside script. Modern frameworks like React and Angular do most of this automatically as long as you avoid escape hatches like dangerouslySetInnerHTML.

For DOM XSS, prefer textContent over innerHTML and never feed untrusted input to eval or document.write. Add a strict CSP (for example script-src 'self' with nonces, no unsafe-inline) so even an injected script is blocked from running, and consider Trusted Types to lock dangerous sinks. Encoding stops the bug; CSP limits the blast radius if one slips through.

Strobes insight
A WAF that blocks