XSS hunting
Find every reflection, name the context, then execute. XSS is a gadget until it reads a session, a token, or an admin UI.
Playbooks
- Web Cache Poisoning & Deception - Get a malicious response cached and served to other users, or trick the cache into storing sensitive pages.
- Prototype Pollution (client & server) - Inject properties into Object.prototype to change app behavior - client-side DOM XSS or server-side RCE via gadget chains.
- XSS Hunting (reflected, stored, DOM) - Find every reflection, name the context, then execute. XSS is a gadget until it reads a session, a token, or an admin UI.
- CSP Bypass - CSP is not the bug. It is the reason a reflection does not fire. Parse it, then look for a gadget on an allowed origin.
- postMessage & DOM gadgets - Map every message listener and every wildcard sender. SPA auth and payment widgets live and die here.
- Open Redirect Chains - Do not report the bounce. Report where the victim's code, token, or script execution goes.
Gadgets
- Open redirect - Low alone. High when it leaks an OAuth code, a session token, or feeds a server-side fetch.
- postMessage wildcard - Listener with origin '*' or a weak startsWith check plus a DOM / auth sink is a classic SPA gadget.
- Unkeyed header / cache key - If a header changes the response but is not in the cache key, you poison everyone who shares that key.
- Leaked token in URL, JS, or Referer - A password-reset or OAuth token in a URL is an ATO gadget if it is reusable, long-lived, or logged.
- DOM sink (innerHTML / html() / v-html) - A sink without a source is inventory. A sink plus any attacker-controlled source is XSS.
- JSONP / callback parameter - Legacy JSONP with a reflected callback and cookies is an XSS/CORS-bypass gadget on old APIs.
Payloads
- Polyglots - Single strings that fire across multiple contexts - ideal for one-shot fuzzing when you don't yet know the sink. The 0xsobky XSS polyglot survives most encoding contexts; the SQLi polyglot triggers error/union/boolean at once.
- Cross-Site Scripting (XSS) - Context-driven: pick by where your input lands. Start with a benign marker (vulnsXSS) to find reflection, then break the context - HTML body, attribute, JS string, URL, or SVG. Last entries are common WAF/filter bypasses.
- CRLF / Header Injection - Inject %0d%0a to split responses - set cookies, poison caches, or land reflected XSS via an injected body. Test in params reflected into Location or Set-Cookie headers.
- Prompt Injection / LLM - Probes for LLM-backed features (chat, RAG, agents). Start with a benign marker to prove the model follows injected instructions, then escalate to system-prompt leak, insecure output handling (output → XSS/SSRF/command sink), and tool/agent abuse. Indirect probes go inside data the model ingests (docs, pages, emails, filenames). Keep PoCs benign - use OAST callbacks, never real exfil. See the /bypasses/ ai-guardrails sheet.
Bypasses
- XSS bypass (by sink) - Modern frameworks (React/Angular/Vue) auto-escape text, so the wins are unescaped attribute/href/src sinks, dangerous APIs, and framework-specific gadgets. Pick by where your input lands and what's filtered.
- CORS misconfiguration - Find an origin the server will trust with credentials. Confirm with the CSP/CORS checks on /utils/.
- CSP bypass gadgets - You already have a reflection. These are why it still executes.
- Cache key / deception bypass - Make the CDN store a response the next user should never see, or store your poison under a popular key.
Checklists
- JavaScript review - Treat the frontend as source. Most P1s on modern apps start here.
- XSS - Marker first. Context second. Execute third. Cookie/CSP last.
- Cache - Two clients. One poisons. The other must receive it.
Tools
- dalfox - Fast, powerful XSS scanner and parameter analyzer. Verifies reflections and builds working payloads.
- gf - A wrapper around grep with reusable pattern packs (xss, sqli, ssrf, lfi, redirect). Instantly slices URL lists into likely-vulnerable candidates.
- kxss - Finds query parameters that reflect in the response. Pipe gau/waymore into it, then hand the hits to dalfox or a manual DOM check.
- semgrep - Local SAST. Point it at reconstructed source maps or a dumped .git and hunt sinks (innerHTML, exec, pickle, yaml.load) with public rulesets.
- crlfuzz - Scans URLs for CRLF injection with encoded variants. Use on a focused URL list, not the whole program.
- ppmap - Prototype pollution scanner for URL gadgets. Pollution without a sink is weak; pair with the JS review playbook.
Workflows
- URL corpus → XSS candidates - Collect historical URLs, filter for reflected-XSS-shaped params, inject a marker, and scan with dalfox.
Related disclosures
- Stored script execution through an upload surface - Stored cross-site scripting through file upload
Questions
Is alert() enough?
For a self-XSS on your own profile, usually not. Show a session, a token in storage, or an admin-only render with a victim account you own.
Does CSP kill the finding?
Only if it actually blocks your payload. Parse the policy. Error pages and JSONP on allowed hosts are the usual way CSP fails.
This page is the public form of hunt_brief("xss") on the MCP connector. Authorized testing only.