skills/dom-xss/SKILL.md
Use when XSS depends on browser-side sources and sinks such as URL/query/hash, router state, local/session storage, cookies, postMessage, DOM parsing, framework render paths, or client-side sanitizer behavior.
npx skillsauth add ghostonbutterbread/bug-bounty-harness dom-xssInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this lane when the server response alone is not the whole story. DOM XSS requires browser-side source-to-sink reasoning and execution proof.
xsslive-testing-policywaf-live-policy for browser/raw-client, sanitizer, and parser differenceschromium-test when local browser verification is possibleskills/xss/references/payload-selection.mdLook for attacker-controlled sources:
location, location.href, location.search, location.hashdocument.URL, document.referrerlocalStorage, sessionStoragepostMessage event dataBroadcastChannel, MessageChannelHigh-signal sinks:
innerHTML, outerHTMLinsertAdjacentHTMLdocument.write, document.writelneval, Function, string timerssetAttribute on URL/event-sensitive attributessrcdocFramework-specific review:
dangerouslySetInnerHTML, raw markdown/HTML renderers, unsafe URL
props, hydration mismatch pathsv-html, dynamic template compilation, custom components forwarding raw
HTML[innerHTML], bypassSecurityTrustHtml,
bypassSecurityTrustUrl, bypassSecurityTrustScriptLikely or Potential.For /hybrid, /deep-hunt, URL-batch, or route-cluster handoffs, do not stop
at "marker reflected" or "framework detected." Produce a compact source-to-sink
map:
postMessage,
bootstrap data, API response, and framework state candidatesattempts.jsonl row per deliberate source/sink probe
with payload family, transformation result, browser result, and stop reasonIf the route is browser-only due to challenge or client rendering, raw HTTP is not sufficient evidence to close the DOM lane.
DOM payloads often succeed because two components disagree:
location.toString().value decodes before innerHTMLFor hard labs and real apps, mutation is normal. Try fragments, duplicate params, encoded delimiters, parser recovery, alternate source locations, storage writes, message bodies, route state, and browser-only behavior when they are scoped and rate-limited.
Prefer:
chromium-test launcherRecord if browser verification is blocked by missing Chromium, missing Playwright, CAPTCHA, challenge, rate pressure, or scope.
For postMessage:
Include:
testing
Systematic live request mutation: flip booleans, field ops, headers, content-type, parser differentials, replay vs intercept, null/empty testing. Inherits live-testing-policy scope/rate/ownership rules.
development
Test password reset, forgot-password, reset-token, email reset, and account recovery flows for account takeover risks.
tools
Targeted param/field discovery using tech stack clues, naming conventions, and controlled-rate ffuf — then feeds findings into request-exploration for mutation. Not brute-force; informed and scoped.
testing
Ghost-only workflow for creating approved bug bounty test accounts and saving credential references.