EXERCISE 1 — Why input validation helps but can't replace parameterization =========================================================================== WHY VALIDATION HELPS: - Allowlist validation rejects input that doesn't match its EXPECTED SHAPE before it ever reaches a query. For strict-format fields this removes the ability to carry a payload at all, shrinking the attack surface and catching obvious junk early. It's good practice and a useful layer. WHY IT CANNOT REPLACE PARAMETERIZED QUERIES: - Many legitimate fields MUST accept the same characters payloads use, so you can't reject them without breaking the feature. - Blocklisting "bad characters" is endlessly bypassable (encodings, numeric context with no quotes, comment variants) — the same losing game as XSS filters. - It operates at the wrong layer/time and is blind to SECOND-ORDER injection. - So validation reduces likelihood; only parameterization removes the bug. A FIELD WHERE ALLOWLIST VALIDATION GENUINELY BLOCKS INJECTION: - A numeric ID (or UUID, enum, date). If you require id to be a positive INTEGER and reject anything else: if (!Number.isInteger(id) || id < 1) return badRequest(); then a payload like 5 OR 1=1 or '; DROP TABLE fails validation outright — it isn't an integer. There's no valid integer that contains SQL syntax, so for this strict format, validation alone blocks the injection. (Other examples: a status that must be one of {open,closed,pending}; a country code matching ^[A-Z]{2}$.) A FIELD WHERE IT CAN'T (without breaking the feature): - Free-text fields: a person's NAME, a COMMENT, a SEARCH query. These legitimately contain ' " ; -- < > and arbitrary text: * O'Brien, D'Angelo (apostrophes in real names), * "use a < b; see note -- updated" (a comment with SQL-looking chars), * search for "O'Reilly" or "1=1". You cannot reject quotes/semicolons/dashes here without rejecting valid user data and breaking the field's purpose. So the payload characters pass validation legitimately, and the ONLY safe handling is to parameterize the query that uses them. WHY SECOND-ORDER SQLi DEFEATS INPUT VALIDATION ENTIRELY: - Second-order (Chapter 6): a value is STORED in request 1 (often looking harmless and passing any validation — e.g. username admin'-- is a "valid" string), then TRIGGERS in request 2 when a DIFFERENT code path reads it from the database and concatenates it into a new query. - Input validation only inspects data AS IT ENTERS. But the dangerous query in request 2 operates on data that is NO LONGER "user input" — it's a row from your OWN database, which code tends to trust and not re-validate. The front-door check is irrelevant to the query that actually breaks. - You also can't reject admin'-- at input without rejecting legitimate names containing apostrophes. So validation is structurally unable to stop second-order injection; it must be parameterized at the query that re-uses the stored value. CONCLUSION: Use allowlist validation for data quality and to harden strict-format fields, but ALWAYS parameterize every query — validation can't cover free-text fields or second-order paths, and is not the SQLi fix.