flawopen.com/XSS/Types of XSS
All three are the same underlying bug — unescaped untrusted content reaching the page — but they differ in where the malicious payload lives and who it reaches.
An attacker crafts a malicious URL (e.g. a search query parameter containing a script) and tricks a victim into clicking it. The server reflects that value back into the response unescaped, and it runs in the victim's browser. Requires the victim to click a specific malicious link each time.
An attacker submits malicious content (a comment, a profile field) that gets saved and later rendered to other users unescaped — every visitor who views that content is affected, with no malicious link required. The MySpace Samy worm was stored XSS, which is why it could self-propagate.
Client-side JavaScript reads an untrusted value (often from location.hash or another URL fragment) and writes it into the DOM via innerHTML or similar, entirely in the browser. The server may never see the malicious payload at all, which means server-side output encoding alone won't catch it — the fix has to be in the client-side JavaScript itself.
Reflected and stored XSS are usually fixed with server-side output encoding, since the server is the one rendering the value into HTML. DOM-based XSS requires client-side fixes — using textContent instead of innerHTML, sanitizing before any DOM write — because the server's encoding never touches this data path at all.