๐ What Is This Control?
Validate all Input & Handle Exceptions is a defensive discipline with three tightly related parts: (1) validate all input at the boundary (allow-list, server-side, typed); (2) neutralise at the sink - parameterise queries and apply context-aware output encoding so data is treated as data, never code; and (3) handle exceptions safely - fail closed, return generic errors, and log detail privately. The central rule: validation reduces risk but is not a substitute for output encoding or parameterised queries - you need both.
๐ฏ What It Prevents
- SQL / NoSQL Injection: Attacker text entering the command structure
- Cross-Site Scripting (XSS): Injected markup rendered as active script
- OS Command Injection: Shell metacharacters in a spawned command
- LDAP Injection: Unescaped filter metacharacters
- XXE: XML parsers resolving external entities and DTDs
- Insecure Deserialization: Native deserializers building arbitrary objects (RCE)
- Path Traversal & Unsafe Uploads: Escaping the intended directory
- Info Disclosure / Fail-Open: Stack traces leaking internals; errors granting access
๐งญ How It Works
โ
2. Validate - allow-list, server-side, syntactic + semantic
โ
3. Neutralise at the sink - parameterise queries, encode output
โ
4. Configure parsers safely - disable XXE, avoid native deserialize
โ
5. On error: fail closed, generic message out, detail to logs
โ Without This Control
โ Applying the Control
โ Implementation Checklist
- Validate with an allow-list, server-side, syntactic + semantic, typed/schema-checked
- Canonicalise/normalise first, then validate the canonical form
- Anchor every regex and bound its length
- Parameterise SQL/NoSQL queries; allow-list identifiers you cannot bind
- Apply context-aware output encoding; use auto-escaping templates
- Sanitise rich HTML with a vetted library (e.g. DOMPurify)
- Run commands via argument arrays, no shell, validated input
- Disable DTDs and external entities on XML parsers
- Avoid native deserialization; prefer data-only formats + schema
- Confine file paths to a base dir; validate uploads by content
- Fail closed on error; return generic errors, log privately; debug off in prod
๐ Tools & Techniques
Validation & Safe Sinks:
Testing & Scanning:
How to Verify:
- Send injection probes (
' OR 1=1,<script>,; id) and confirm 400/inert output - Call the API directly (bypass the client) to test server-side validation
- Post XML with an external entity and confirm it is not resolved
- Trigger an error and confirm no stack trace reaches the client
- Confirm a security check that throws denies rather than allows
๐ Why It Matters
- SQL injection breaches: String-concatenated queries have driven some of the largest data breaches on record. The durable fix is parameterised queries, not cleverer input filtering.
- Stored and reflected XSS: User content rendered without context-aware encoding runs script in victims' browsers - stealing sessions and acting as the victim. Auto-escaping templates shut this down.
- XXE in XML processors: Parsers with external-entity resolution enabled have been used to read local files and reach internal systems (SSRF). Disabling entities and DTDs is the fix.
- Unsafe deserialization: Native, type-permissive deserializers have repeatedly led to remote code execution. Data-only formats with a strict schema remove the sink.
- Verbose errors as reconnaissance: Stack traces have handed attackers versions, paths, and schema names. Generic errors plus private logging deny that free recon.
These are documented incident classes - no fabricated CVE numbers or statistics. The same missing control sits behind all of them.
๐ Quick Tips
- DO NOT treat input validation as a substitute for encoding/parameterising
- DO NOT build SQL by concatenation or run
shell=Truewith input - DO NOT native-deserialize untrusted data or return stack traces
- DO validate with allow-lists on the server, canonicalising first
- DO parameterise queries and encode output for the exact context
- DO disable XXE and fail closed on any security check
- DO log detail privately and turn debug off in production