EXERCISE 2 — Why input validation can't be the primary XSS defence =================================================================== WHY VALIDATION CAN'T BE PRIMARY (free-text fields legitimately contain HTML-special characters): Field 1 -- a NAME. Legitimate value: O'Brien, "Bob" , AT&T, Müller-Lévy. Names genuinely contain ' " < > &. If you reject those characters you break real users' names. So you must ACCEPT them -- and then neutralise them at output (encode), not reject them at input. Field 2 -- a COMMENT / MESSAGE / BUG REPORT. Legitimate value: "use a < b to compare" or "the form posts to " or pasted code: if (a < b && c > d) { ... }. Free text routinely includes < > & " '. Rejecting them mangles ordinary content (math, code, quotes). Must accept; must encode on output. Field 3 -- a SEARCH QUERY. Legitimate value: users search for "
", "a && b", "price > 100". You can't forbid these characters or the search feature is crippled. The echoed query (reflected context) must be ENCODED on output instead. In all three, the dangerous characters are ALSO valid content, so there's no input filter that removes the threat without removing legitimate data. The only reliable fix is at OUTPUT (encode/sanitize), which makes the data safe regardless of what was entered. Hence validation is secondary (defence-in-depth), not the XSS defence. TWO FIELDS WHERE ALLOWLIST VALIDATION GENUINELY HELPS: Field A -- a DATE (or UUID, or integer, or enum/select value). These have a STRICT, NARROW FORMAT. A date must match YYYY-MM-DD; a UUID matches a fixed pattern; a quantity is digits; a status is one of a fixed set. You can ALLOWLIST-VALIDATE: reject anything that doesn't match the exact format. A payload like simply isn't a valid date, so it's rejected outright -- input validation legitimately blocks it. Field B -- an EMAIL ADDRESS / a numeric amount / a country code. Constrained formats again: validate against the expected shape and reject off-format input.