TaskBuild a comment list that's XSS-safe. <form>: text input name='comment' + submit button. <ul id='comments'></ul> below. JS: on submit, prevent default, read the input value, create a <li>, set li.textContent (NOT innerHTML), append to #comments, reset the input.
XSS-safe rendering: textContent vs innerHTML, on user input
100 XP9 min
Theory
The mistake
You take a comment from a form, then render it into the DOM:
commentList.innerHTML += "<li>" + userInput + "</li>";
If userInput is <img src=x onerror="fetch('/steal?c='+document.cookie)">, the browser runs that script in YOUR origin. Now the attacker reads your users' cookies, makes requests as them, defaces your page.
The fix
const li = document.createElement("li");
li.textContent = userInput; // browser treats userInput as plain text, escapes everything
commentList.appendChild(li);textContent (and innerText) write the string as text. No HTML parsed. The literal characters <, >, & are rendered as you-typed-them, never as tag delimiters.
When you NEED HTML rendering
E.g. you want bold inside comments. Options in order of safety:
- Restricted Markdown β your server converts a small allowlist (
**bold**,*italic*,[link](url)) to safe HTML, with link URLs filtered (javascript:blocked,http(s)://relativeallowed). Then you can safely use innerHTML on the server-cleaned output. - DOMPurify β client-side library that strips dangerous tags/attrs. Useful for rich-text editors. Still: don't pass arbitrary user input to it; pass YOUR known-format markup.
- Never pass raw user input to innerHTML β even if you "trust" the user; one compromised account becomes everyone's problem.
What this looks like in a comment list
function addComment(text) {
const li = document.createElement("li");
li.textContent = text;
document.getElementById("comments").appendChild(li);
}Three lines, XSS-safe, accessible by default.
π
Sign up to start coding
Theory is open to everyone. The interactive editor, live preview, and check are unlocked with a 7-day free trial β card required, cancel anytime.
Sign up β free trial βFirst 10 lessons in each track are free. No card needed for those.