EXERCISE 3 — One HTML-encoded username reused in three contexts ================================================================ THE MISTAKE: The developer HTML-entity-encodes the username ONCE (e.g. " -> ", < -> <) and reuses that single encoded string in three different places. HTML encoding is correct for ONLY ONE of them. Contexts decode differently. PLACEMENT 1 -- HTML body: USERNAME STATUS: SAFE (correctly handled). HTML-entity encoding is exactly the right encoding for the HTML body context. < > & become inert text; no tag can be introduced. Good. PLACEMENT 2 -- URL attribute: profile STATUS: STILL VULNERABLE. HTML encoding does NOT stop a dangerous SCHEME. If the username is "javascript:alert(document.cookie)", there are no HTML-special characters to encode, so the encoded value is unchanged and the link executes JS on click. (Also, if the value isn't actually a URL, putting it in href is wrong.) CORRECT HANDLING: - Validate the SCHEME against an allowlist (http/https/mailto only); reject javascript:, data:, vbscript:. - Then URL-encode the value (encodeURIComponent for query/path parts). - Plus keep the attribute quoted and attribute-encode quotes. PLACEMENT 3 -- event-handler attribute: - If unavoidable: apply JS-STRING encoding FIRST (escape ' " \ etc., ideally \xHH hex-escaping), THEN HTML-ATTRIBUTE encoding (because it's nested: JS inside an attribute) -- two layers, in the right order. This is error-prone, which is why avoiding the inline handler is preferred. SUMMARY: context HTML-encoding enough? correct fix ------- --------------------- ----------- HTML body YES HTML-entity encode (done) href URL NO scheme allowlist + URL-encode onclick (JS-in-attr) NO avoid; else JS-encode THEN attr-encode LESSON: "I escaped it" is meaningless without "...for which context?" The SAME encoded value is safe in the body, broken in href, and broken in onclick. Encode per destination -- or let a framework's context-aware auto-escaping do it (Chapter 9).