reminder that DOM XSS doesn't even touch the server. the payload never shows up in the response body, so half the scanners walk right past it
Don't forget about the DOM
yep. it's all client-side. some JS reads from a source and writes to a sink without sanitizing, and boom
for the newer folks — "source" is where attacker-controlled data comes in. location.hash, location.search, document.referrer, window.name, postMessage...
and the "sink" is where it lands and executes. innerHTML, document.write, eval, insertAdjacentHTML, jQuery .html()... anything that turns a string into live DOM
the classic is a site that grabs location.hash and drops it straight into innerHTML. put your payload after the # and it never even hits the server logs
that's the sneaky part. the # fragment isn't sent to the server. it's a purely browser-side party.
how do you actually hunt it though, i always feel like i'm guessing
open devtools, search the JS for the sinks. grep for innerHTML, document.write, eval. then trace BACKWARD — where does that value come from? if it traces to a source you control, you've got a candidate
set a breakpoint on the sink assignment. reload with a test string in the hash. watch it flow from source to sink untouched. if nothing HTML-encodes it on the way, it's game over