A thread in the Ravens’ forum stores comments and shows them to everyone who opens it. The Hacker heard about XSS and added "protection": he removes the word script from any comment before showing it. The leader himself opens the thread every so often.
The same Ravens forum, but here a thread page stores comments and shows them to every visitor. The Hacker added protection that strips the word script from each comment before display. The leader button simulates him opening the thread, his browser rendering every stored comment after the filter.
Leave a stored comment so that when the leader opens the thread, his browser runs code that calls steal().
The stored comment, after the filter runs, still executes code that calls steal when shown.
Why the solution worked
This is stored XSS: your comment was saved and ran in the browser of everyone who later opened the page. The protection was a blacklist that strips one word, which is never enough: the ways to run code are endless (event attributes, javascript URLs, other tags), and banning a word is easily bypassed. The fix is to encode output on display, or sanitize with a whitelist via a mature library (such as DOMPurify) that allows only a known set of safe tags and strips every dangerous attribute or tag.
The root cause
The protection is a blacklist that strips one word, and the stored content is rendered as HTML. Blacklists always fail because the ways to run code are endless.
How the code is fixed
A blacklist chases the attacks you know of; the attacker brings the one you did not. A whitelist allows the small safe set and rejects everything else, which is why it is the right model.
Vulnerable code
function render(comment) {
// "Protection": strip the word script, then drop the rest into the page.
const cleaned = comment.replace(/script/gi, '');
return '<div class="comment">' + cleaned + '</div>';
}
Safe code
import DOMPurify from 'dompurify';
function render(comment) {
// Whitelist sanitize: only safe tags survive, every handler/script is removed.
const cleaned = DOMPurify.sanitize(comment, { ALLOWED_TAGS: ['b', 'i', 'a'], ALLOWED_ATTR: ['href'] });
return '<div class="comment">' + cleaned + '</div>';
}
Impact in the real world
Stored XSS is more dangerous than reflected because it hits everyone who opens the page with no special link; it has powered self-spreading worms on social networks and mass account theft.
How defenders detect it
Defenders sanitize content with a whitelist library on store and display, scan stored data for tags and event attributes, and apply a CSP that blocks inline script execution.