Input validation and injection
Every value that arrives from outside, a form field, a query string, a header, an uploaded file, a URL you fetch, is hostile until proven otherwise. Injection happens when that value is treated as code or structure instead of data.
Checklist
- Use parameterized queries, always. Never build SQL by string concatenation. Use bound parameters or an ORM that binds for you. This closes SQL injection. The same rule applies to NoSQL and to shell commands.
- Escape output by context. Rely on a templating or UI framework that escapes by default (React, for instance). Be very careful with any "render raw HTML" escape hatch. This is how cross-site scripting (XSS) gets in.
- Validate against an allowlist, not a denylist. Define what a valid value looks like and reject everything else, rather than trying to blocklist bad input.
- Guard server-side requests (SSRF). If the server fetches a user-supplied URL, validate it and block internal ranges and the cloud metadata address (169.254.169.254). Use strict host validation and pin DNS to counter rebinding.
- Never deserialize untrusted data into code. Avoid pickle, native Java or PHP deserialization, and similar on attacker-controlled bytes. They run code.
- Harden file uploads. Verify the real content (magic bytes), not just the
extension or the declared type. Enforce a hard size cap. Store files outside
the web root, under a random or id-based name, never the user's filename.
Serve them with the correct content type and
X-Content-Type-Options: nosniff. Scan for malware if you can. - Validate request bodies against a schema. Reject unknown fields rather than letting them through (see mass assignment in APIs and requests).
How to test
- Submit
' OR 1=1 --,<script>alert(1)</script>, and${7*7}into every field and confirm they are stored and shown as literal text. - Point any URL input at
http://169.254.169.254/and athttp://localhost/. - Upload an HTML file renamed to
.pngand confirm it is rejected or served inert.