Stored XSS
Payload gets saved server-side (a comment, a profile field) and fires for every visitor who views that page later. Highest impact, hits anyone who views the page.
Reflected XSS
Payload comes back in the response immediately, usually from a URL parameter or search box. Needs a victim to click a crafted link.
DOM-based XSS is really a third axis, not a competitor to the above: the payload never touches the server at all, a client-side script reads attacker-controlled data (
location.hash, document.URL, a URL parameter) and writes it into a dangerous sink (innerHTML, eval, document.write) itself. It can be either stored or reflected in terms of where the data originates, but the vulnerability lives entirely in JavaScript, not server-side templating.Basic Payloads
Start simple and work up, a bare<script> tag confirms the sink executes JavaScript at all before worrying about filters.
<script> itself gets stripped or blocked, an event handler on a tag that’s still allowed does the same job.
Context Matters
Where your input lands changes which payload works. Check which context you’re in before reaching for a generic script tag.- HTML Body
- HTML Attribute
- JavaScript String
- URL / href Attribute
Input renders as a plain HTML tag, inject a new element directly.
Filter and WAF Bypasses
No <script> tag allowed
No <script> tag allowed
Event handlers on tags that often survive a blocklist:
Keywords like 'alert', 'script', or quotes are blocked
Keywords like 'alert', 'script', or quotes are blocked
Avoiding the literal string If quotes are stripped entirely,
alert with bracket notation or fromCharCode:String.fromCharCode and backticks both avoid needing any:Spaces are filtered
Spaces are filtered
Browsers (Gecko especially) tolerate a surprising range of non-alphanumeric characters between an event name and
=:javascript: protocol is filtered
javascript: protocol is filtered
Tabs, newlines, and carriage returns can be inserted inside the word “javascript” without breaking how the browser parses the protocol, since only those three characters get silently stripped from a URL scheme:
Encoding-based bypasses
Encoding-based bypasses
HTML entity encoding (decimal or hex, with or without the trailing semicolon) slips past filters that only check for a literal
javascript: string:Polyglot payload
Polyglot payload
Built to fire regardless of exactly which context (HTML, attribute, JS string, URL) it lands in, useful when you’re blind-testing many injection points at once and don’t want to craft a payload per field:
See also Polygot XSS - Payloads All The Things for more commands
Stealing Cookies
Loading a remote script is the cleanest way to deliver a larger payload without cramming everything into the injection point itself.<script> loads but still renders images.
1
Stand up a collector
A tiny PHP page logs every cookie it receives, keyed by the victim’s IP.
2
Write the stealer script
3
Deliver it through the injection point
DOM-Based XSS and Local File Read
When the vulnerable code lives entirely client-side, the usual suspects are reading from a source the attacker controls and writing it into a dangerous sink without sanitizing in between.| Sources (attacker-influenced input) | Sinks (dangerous if unsanitized) |
|---|---|
location.hash, location.search | innerHTML, outerHTML |
document.URL, document.referrer | document.write() / document.writeln() |
window.name | eval(), setTimeout(string), setInterval(string) |
| URL parameters read via JS | element.setAttribute() on event/href attributes |
HTML injection inside a server-rendered PDF (via a headless browser like wkhtmltopdf or a Chrome-based renderer) is a DOM-XSS-adjacent bug worth knowing: if user input reaches the HTML that gets rendered into a PDF, the renderer’s own JavaScript engine can be abused for local file read or SSRF, since the renderer often runs with far fewer restrictions than a normal browser tab. See SSRF to local file read through HTML injection in a PDF and finding SSRF via HTML injection inside a PDF on AWS EC2 for real-world writeups.
XMLHttpRequest against the file:// scheme (several headless PDF renderers historically did), this reads a local file and writes its contents straight into the rendered output.
Automated Tools
- XSStrike
- XSSer
Fuzzes a parameter intelligently, builds its own payloads based on what the app reflects back rather than just throwing a static list.
Quick Reference Tools
HackTricks: XSS
Deep, continuously updated collection of payloads and bypasses by context.
PayloadsAllTheThings: XSS
Large categorized payload collection.
xss-payload-list
Flat all-in-one payload list, good for quick fuzzing.
OWASP XSS Filter Evasion Cheat Sheet
The canonical reference for encoding and filter-bypass tricks.
XSStrike
Context-aware XSS detection and fuzzing.
XSSer
Automated XSS detection with an optional GTK UI.

