Security isn't a feature you add at the end — it's a discipline you build throughout development. This checklist covers every layer of a modern web application, organized so you can work through it systematically before shipping.
How to use this checklist: work through each section during development and before every major release. Items marked ⚠️ are critical — skip them only with documented justification.
1. Authentication
- ⚠️ Passwords hashed with bcrypt (cost ≥ 12) or Argon2id — never MD5, SHA-1, or plain SHA-256
- ⚠️ No plain-text passwords stored anywhere (logs, DB, emails)
- ⚠️ Rate limiting on login endpoint (max 5 attempts per 15 min per IP)
- Account lockout after repeated failures with notification to user
- ⚠️ Multi-factor authentication available for sensitive accounts
- "Forgot password" tokens are single-use, expire in ≤ 1 hour, hashed in DB
- Username enumeration prevented (same response for invalid user vs wrong password)
- Session invalidated on logout (server-side invalidation, not just deleting cookie)
- Concurrent session limits enforced if required
2. Authorization
- ⚠️ Every API endpoint explicitly checks authorization — no implicit trust
- ⚠️ Resource-level access control: user can only access their own data
- ⚠️ Admin functions require admin role check on the server (not just hidden in UI)
- Principle of least privilege: services and users have minimum required permissions
- JWT tokens validated on every request (signature + expiry + claims)
- Sensitive operations (delete, transfer, admin actions) require re-authentication
3. Input Validation & Output Encoding
- ⚠️ All user input validated on the server side (client-side validation is UX only)
- ⚠️ Parameterized queries used for all database operations — no string concatenation
- ⚠️ HTML output escaped before rendering user-controlled data
- File uploads: validate type (not just extension), size limit, scan for malware
- File uploads stored outside webroot or in cloud storage, not served directly
- Redirects validate the destination URL against an allowlist
- JSON input parsed with a size limit
4. Secrets & Configuration
- ⚠️ No secrets in source code or git history
- ⚠️ All secrets in environment variables or a secrets manager (Vault, AWS Secrets Manager)
- .env files in .gitignore; .env.example committed instead
- ⚠️ Production and development secrets are different values
- API keys have minimal permissions (not root/admin keys)
- Secrets rotated regularly and after team member offboarding
git logchecked for accidental secret commits before first push
5. HTTPS & Transport Security
- ⚠️ HTTPS enforced everywhere — HTTP redirects to HTTPS (301)
- ⚠️ Valid certificate from trusted CA, not self-signed in production
- TLS 1.2 minimum; TLS 1.3 preferred
- HSTS header set with at least 1-year max-age
- Cookies set with Secure, HttpOnly, SameSite attributes
- Mixed content warnings resolved (no HTTP resources on HTTPS page)
6. HTTP Security Headers
# Minimum security headers
Content-Security-Policy: default-src 'self'
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()- CSP defined and tested (no
unsafe-inlinefor scripts without nonce) - Server version information hidden (
server_tokens offin Nginx) - Error pages don't expose stack traces or framework information
7. Dependencies
- ⚠️
npm audit/pip-auditrun — no known high/critical vulnerabilities - Dependencies locked (
package-lock.json,requirements.txtwith pinned versions) - Automated dependency scanning in CI (Dependabot, Snyk, or similar)
- Third-party scripts loaded from known CDNs with Subresource Integrity (SRI) hashes
- No abandoned or unmaintained packages for security-critical functions
8. Session Management
- Session tokens are cryptographically random and ≥ 128 bits
- Session ID rotated on privilege escalation (login, role change)
- Session timeout after inactivity (configurable, default ≤ 30 min for sensitive apps)
- "Remember me" uses a separate long-lived token, not extending the session
- CSRF protection on all state-changing requests (SameSite cookie or CSRF token)
9. Logging & Monitoring
- Authentication events logged (success, failure, lockout)
- ⚠️ Logs don't contain sensitive data (passwords, tokens, PII)
- Authorization failures logged (403 responses)
- Alerts configured for anomalies (high error rate, unusual traffic)
- Log aggregation and retention policy defined
- Uptime monitoring with alerting
10. Infrastructure
- ⚠️ Firewall rules: only required ports open (typically 80, 443, and SSH from specific IPs)
- SSH: key-only authentication, root login disabled
- Automatic security updates enabled for OS
- Database not publicly accessible (VPC/private network only)
- Backups automated, tested, and stored separately
- Principle of least privilege for cloud IAM roles
11. Before Each Release
git logreviewed for any debug code, test credentials, TODO security notes- New endpoints have authorization checks
- Any new third-party integrations reviewed for data exposure
- Sensitive changes reviewed by a second engineer