Web Security Cheat Sheet
Comprehensive defensive security reference for web developers. Covers OWASP Top 10, injection prevention, headers, authentication, and more.
1. OWASP Top 10 (2021)
| # | Vulnerability | Description | Prevention |
|---|---|---|---|
A01 | Broken Access Control | Users act outside intended permissions | Deny by default, RBAC, server-side checks |
A02 | Cryptographic Failures | Weak or missing encryption of sensitive data | TLS everywhere, strong algorithms, no hardcoded keys |
A03 | Injection | SQL, NoSQL, OS, LDAP injection via untrusted data | Parameterized queries, input validation, ORM |
A04 | Insecure Design | Missing or ineffective security controls by design | Threat modeling, secure design patterns |
A05 | Security Misconfiguration | Default configs, open cloud storage, verbose errors | Hardened defaults, automated config audits |
A06 | Vulnerable Components | Using libraries with known vulnerabilities | npm audit, Dependabot, SCA tools |
A07 | Auth & ID Failures | Broken authentication or session management | MFA, rate limiting, secure session handling |
A08 | Software & Data Integrity | Untrusted updates, CI/CD pipeline compromise | Verify signatures, SRI hashes, signed commits |
A09 | Logging & Monitoring Failures | Insufficient logging hinders breach detection | Log security events, alerting, audit trails |
A10 | SSRF | Server fetches attacker-controlled URLs | Allowlist URLs, block internal IPs, validate schemes |
2. SQL Injection Prevention
Rule #1: Never concatenate user input into SQL. Always use parameterized queries.
| Language | Parameterized Query Example |
|---|---|
Node.js | |
Python | |
Java | |
PHP | |
3. XSS Prevention
| Technique | Implementation |
|---|---|
| Output Encoding | |
| Content Security Policy | |
| DOMPurify | |
| Template Engines | React: auto-escapes by default (avoid dangerouslySetInnerHTML)Jinja2: auto-escapes by default ( {{ var }})EJS: use <%= var %> (escaped) not <%- var %> (raw) |
4. CSRF Protection
| Method | Implementation |
|---|---|
| CSRF Tokens | |
| SameSite Cookies | |
| Double-Submit Cookie | |
5. Security Headers
| Header | Recommended Value | Purpose |
|---|---|---|
Content-Security-Policy | default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; frame-ancestors 'none' | Controls resource loading, prevents XSS |
Strict-Transport-Security | max-age=63072000; includeSubDomains; preload | Forces HTTPS for 2 years |
X-Frame-Options | DENY | Prevents clickjacking |
X-Content-Type-Options | nosniff | Prevents MIME-type sniffing |
Referrer-Policy | strict-origin-when-cross-origin | Controls referrer info leaking |
Permissions-Policy | camera=(), microphone=(), geolocation=() | Disables browser APIs |
X-XSS-Protection | 0 | Disable (deprecated, CSP is better) |
Cross-Origin-Opener-Policy | same-origin | Isolates browsing context |
Cross-Origin-Resource-Policy | same-origin | Prevents cross-origin reads |
Nginx example:
add_header Content-Security-Policy "default-src 'self'; script-src 'self'" always;
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
6. Authentication Best Practices
| Topic | Implementation |
|---|---|
| Password Hashing |
Never use: MD5, SHA-1, SHA-256 alone (too fast for passwords) |
| JWT Best Practices |
|
| Session Management |
|
7. CORS Configuration
| Header | Description |
|---|---|
Access-Control-Allow-Origin | Specifies allowed origin. Use exact origin, never * with credentials. |
Access-Control-Allow-Methods | GET, POST, PUT, DELETE, OPTIONS |
Access-Control-Allow-Headers | Content-Type, Authorization |
Access-Control-Allow-Credentials | true (only with specific origin, not *) |
Access-Control-Max-Age | 86400 (cache preflight for 24 hours) |
Express CORS setup:
const cors = require('cors');
app.use(cors({
origin: ['https://myapp.com', 'https://admin.myapp.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
maxAge: 86400
}));
Common mistakes: Access-Control-Allow-Origin: * with credentials: true (rejected by browsers). Reflecting the Origin header without validation (allows any site).
8. Input Validation
| Strategy | Details |
|---|---|
| Allowlist (preferred) | Define exactly what IS allowed. Reject everything else.if (!/^[a-zA-Z0-9_-]{3,30}$/.test(username)) reject(); |
| Denylist (weak) | Block known-bad patterns. Easy to bypass with encoding tricks. Use only as defense-in-depth. |
| Type Coercion | const id = parseInt(req.params.id, 10);if (isNaN(id) || id < 1) return res.status(400); |
| Schema Validation | |
| File Uploads |
|
9. HTTPS & TLS
| Topic | Best Practice |
|---|---|
| TLS Version | Minimum TLS 1.2. Prefer TLS 1.3. Disable SSLv3, TLS 1.0, TLS 1.1. |
| Cipher Suites | Use AEAD ciphers: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256 |
| Certificates | Use Let's Encrypt (free, auto-renewable). Set up auto-renewal with certbot or ACME client. Monitor expiry. |
| HSTS Preload | 1. Add HSTS header with preload directive2. Submit to hstspreload.org3. Ensure ALL subdomains support HTTPS first |
| Redirect HTTP | |
10. Secrets Management
| Method | Implementation |
|---|---|
| Environment Variables | |
| .gitignore Rules | |
| Vault / KMS | Use HashiCorp Vault, AWS Secrets Manager, or GCP Secret Manager for production. Rotate secrets regularly. Audit access. |
| Pre-commit Hooks | Use git-secrets or trufflehog to scan for leaked secrets before commits. |
11. Rate Limiting
| Framework | Implementation |
|---|---|
Express | |
Django | |
Nginx | |
12. Common Vulnerability Patterns
| Vulnerability | Attack | Prevention |
|---|---|---|
| Directory Traversal | GET /files?name=../../etc/passwd | Resolve path, verify it starts with allowed base dir:path.resolve(base, file).startsWith(base) |
| SSRF | Server fetches http://169.254.169.254/ (cloud metadata) | Allowlist domains/IPs. Block private ranges (10.x, 172.16.x, 169.254.x). Validate URL scheme. |
| Open Redirect | /login?redirect=https://evil.com | Allowlist redirect destinations. Use relative paths only. Validate URL starts with / (not //). |
| Mass Assignment | POST { "role": "admin", "name": "Bob" } | Explicitly pick allowed fields:const { name, email } = req.body;Never pass raw body to ORM. |
| Insecure Deserialization | Tampered serialized objects execute code | Never deserialize untrusted data. Use JSON (not native serialization). Validate schema after parsing. |
| Clickjacking | Transparent iframe overlay tricks clicks | X-Frame-Options: DENY and CSP frame-ancestors 'none' |
Quick Security Checklist
Before Deploy
- Run
npm audit/pip audit - Scan with SAST tool (Semgrep, SonarQube)
- Check for hardcoded secrets
- Verify all security headers set
- Test auth flows and permissions
Ongoing
- Monitor dependency vulnerabilities
- Review access logs for anomalies
- Rotate secrets and API keys
- Keep frameworks and OS updated
- Run periodic penetration tests
Incident Response
- Have a documented response plan
- Rotate all compromised credentials
- Preserve logs for forensics
- Notify affected users promptly
- Conduct post-mortem review