Validate & Sanitize All User Input
Never trust user-supplied data. Validate type, length, format, and range on both the client and server. Use allowlists rather than blocklists, and reject unexpected input early.
11 steps
Securing your application layer means treating every input as untrusted, every secret as precious, and every response as an opportunity to add a defensive header. These steps cover the most impactful controls you can apply directly in your codebase.
Never trust user-supplied data. Validate type, length, format, and range on both the client and server. Use allowlists rather than blocklists, and reject unexpected input early.
Store API keys, passwords, and tokens in a dedicated secrets manager (e.g., HashiCorp Vault, AWS Secrets Manager, Azure Key Vault). Never hardcode credentials or commit them to source control.
Redirect all HTTP traffic to HTTPS. Apply HSTS headers so browsers refuse plaintext connections. Enforce TLS 1.2 or higher and prefer modern cipher suites with forward secrecy.
Add Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy headers to every response. Use a library or middleware to make this automatic.
Use MFA wherever possible. Enforce role-based access control and the principle of least privilege. Verify authorization on every server-side request - never rely solely on UI-level hiding.
Regularly audit and update third-party libraries. Use automated dependency update tools (Dependabot, Renovate) and integrate SCA scanning to catch known CVEs before they reach production.
Log security-relevant events - logins, permission denials, input validation failures, and errors. Ship logs to a centralized system, ensure they are tamper-resistant, and set up alerts for anomalies.
Never expose stack traces, internal paths, or database details in user-facing error messages. Return generic messages in production and log full diagnostic details server-side only.
Guard against XSS with output encoding and a strict CSP. Prevent CSRF with SameSite cookies and anti-CSRF tokens. Use parameterized queries to block SQL injection. Restrict outbound requests to mitigate SSRF.
Allowlist extensions and verify magic bytes rather than trusting the Content-Type header. Enforce size limits, generate random server-side file names, store uploads outside the web root or in object storage, serve them with Content-Disposition: attachment, and scan them for malware before processing.
When the server fetches user-supplied URLs, resolve the host and reject private, loopback, link-local, and cloud metadata ranges after DNS resolution. Prefer an allowlist of destinations, disable redirects or re-validate each hop, and send server-side requests through an egress proxy with its own deny rules.