Web Security Hardening
Security audit checklist for web applications. Run through each item when reviewing or building web apps.
Audit Workflow
- Identify the framework (Node.js/Express, Python/Django/Flask, etc.)
- Review each checklist item below
- For implementation details, see framework-specific references:
- Node.js/Express: See references/nodejs.md
- Python/Django/Flask: See references/python.md
- For production deployments, see references/production-gcp.md for extended checklist covering:
- GCP infrastructure (IAM, networking, secrets)
- CI/CD pipeline security
- Monitoring & incident response
- Report findings with severity and remediation steps
Security Checklist
1. Rate Limiting
Risk: DoS attacks, brute force attempts, API abuse
Check for:
- Per-endpoint rate limits (stricter on auth endpoints)
- Rate limit headers in responses (
X-RateLimit-*)
- Appropriate limits for different user tiers
2. Security & Authorization Headers
Risk: XSS, clickjacking, MIME sniffing, info leakage
Required headers:
Strict-Transport-Security (HSTS)
X-Content-Type-Options: nosniff
X-Frame-Options: DENY or SAMEORIGIN
Content-Security-Policy
Authorization header validation on protected routes
3. IP Block List (Public APIs)
Risk: Abuse from known bad actors, bot traffic
Check for:
- IP-based blocking mechanism
- Integration with threat intelligence feeds (optional)
- Logging of blocked requests
4. CORS Configuration
Risk: Unauthorized cross-origin requests, data theft
Check for:
- Explicit origin whitelist (not
* in production)
- Appropriate methods and headers allowed
- Credentials handling if needed
5. Security Middleware
Risk: Common web vulnerabilities
Check for framework-appropriate middleware:
- Node.js:
helmet
- Python:
django-secure, flask-talisman
- Sets multiple security headers automatically
6. Input Validation
Risk: Injection attacks, data corruption, XSS
Check for:
- Frontend validation (UX, not security)
- Backend validation (required for security)
- Schema validation libraries (Zod, Joi, Pydantic, etc.)
- Sanitization of user input before storage/display
7. File Upload Limits
Risk: Storage exhaustion, malicious file uploads
Check for:
- Max file size limits
- Allowed file type restrictions (MIME + extension)
- File content validation (magic bytes)
- Secure storage location (outside webroot)
8. ORM for Database Access
Risk: SQL injection
Check for:
- Parameterized queries (never string concatenation)
- ORM usage (Prisma, Sequelize, SQLAlchemy, Django ORM)
- If raw SQL needed: prepared statements only
9. Password Hashing
Risk: Credential theft, rainbow table attacks
Check for:
- Strong algorithm: bcrypt, Argon2, or scrypt
- Appropriate cost factor (bcrypt rounds ≥10)
- No MD5, SHA1, or plain SHA256 for passwords
- No plaintext password storage or logging
Gotchas
- CORS
credentials: true + origin: '*' fails silently in browsers — must specify explicit origin when using credentials
helmet() defaults changed between v4 and v5 — CSP is no longer set by default in v5, must configure explicitly
- CSP
unsafe-inline negates most XSS protection — if you need inline scripts, use nonces or hashes instead
express.json() without limit accepts arbitrarily large payloads — always set limit: '1mb' or similar
httpOnly cookies prevent XSS token theft but NOT CSRF — still need CSRF tokens or SameSite=Strict
- Rate limiting per IP fails behind reverse proxies — must set
trust proxy and use X-Forwarded-For
bcrypt silently truncates passwords at 72 bytes — use Argon2 for long passphrases or pre-hash with SHA-256
// WRONG: credentials with wildcard origin (silently fails)
app.use(cors({ origin: '*', credentials: true }));
// RIGHT: explicit origin
app.use(cors({ origin: 'https://app.example.com', credentials: true }));
// WRONG: helmet v5 without CSP (no longer set by default)
app.use(helmet());
// RIGHT: explicit CSP
app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"] } } }));
Audit Report Format
## Security Audit: [App Name]
### Summary
- **Items Passing**: X/9
- **Critical Issues**: X
- **Recommendations**: X
### Findings
#### [Item Name] - [PASS/FAIL/PARTIAL]
**Severity**: Critical/High/Medium/Low
**Finding**: [Description]
**Location**: [File/endpoint]
**Remediation**: [Steps to fix]
1---2name: web-security-hardening3description: Security audit checklist for web applications. Use when reviewing, auditing, or hardening a web app's security posture. Covers rate limiting, auth headers, IP blocking, CORS, security middleware, input validation, file upload limits, ORM usage, and password hashing. Triggers on requests like "review security", "harden this app", "security audit", "check for vulnerabilities", or when building/reviewing API endpoints.4---56# Web Security Hardening78Security audit checklist for web applications. Run through each item when reviewing or building web apps.910## Audit Workflow11121. Identify the framework (Node.js/Express, Python/Django/Flask, etc.)132. Review each checklist item below143. For implementation details, see framework-specific references:15 - **Node.js/Express**: See [references/nodejs.md](references/nodejs.md)16 - **Python/Django/Flask**: See [references/python.md](references/python.md)174. For production deployments, see [references/production-gcp.md](references/production-gcp.md) for extended checklist covering:18 - GCP infrastructure (IAM, networking, secrets)19 - CI/CD pipeline security20 - Monitoring & incident response215. Report findings with severity and remediation steps2223## Security Checklist2425### 1. Rate Limiting26**Risk**: DoS attacks, brute force attempts, API abuse2728Check for:29- Per-endpoint rate limits (stricter on auth endpoints)30- Rate limit headers in responses (`X-RateLimit-*`)31- Appropriate limits for different user tiers3233### 2. Security & Authorization Headers34**Risk**: XSS, clickjacking, MIME sniffing, info leakage3536Required headers:37- `Strict-Transport-Security` (HSTS)38- `X-Content-Type-Options: nosniff`39- `X-Frame-Options: DENY` or `SAMEORIGIN`40- `Content-Security-Policy`41- `Authorization` header validation on protected routes4243### 3. IP Block List (Public APIs)44**Risk**: Abuse from known bad actors, bot traffic4546Check for:47- IP-based blocking mechanism48- Integration with threat intelligence feeds (optional)49- Logging of blocked requests5051### 4. CORS Configuration52**Risk**: Unauthorized cross-origin requests, data theft5354Check for:55- Explicit origin whitelist (not `*` in production)56- Appropriate methods and headers allowed57- Credentials handling if needed5859### 5. Security Middleware60**Risk**: Common web vulnerabilities6162Check for framework-appropriate middleware:63- Node.js: `helmet`64- Python: `django-secure`, `flask-talisman`65- Sets multiple security headers automatically6667### 6. Input Validation68**Risk**: Injection attacks, data corruption, XSS6970Check for:71- Frontend validation (UX, not security)72- Backend validation (required for security)73- Schema validation libraries (Zod, Joi, Pydantic, etc.)74- Sanitization of user input before storage/display7576### 7. File Upload Limits77**Risk**: Storage exhaustion, malicious file uploads7879Check for:80- Max file size limits81- Allowed file type restrictions (MIME + extension)82- File content validation (magic bytes)83- Secure storage location (outside webroot)8485### 8. ORM for Database Access86**Risk**: SQL injection8788Check for:89- Parameterized queries (never string concatenation)90- ORM usage (Prisma, Sequelize, SQLAlchemy, Django ORM)91- If raw SQL needed: prepared statements only9293### 9. Password Hashing94**Risk**: Credential theft, rainbow table attacks9596Check for:97- Strong algorithm: bcrypt, Argon2, or scrypt98- Appropriate cost factor (bcrypt rounds ≥10)99- No MD5, SHA1, or plain SHA256 for passwords100- No plaintext password storage or logging101102## Gotchas103104- CORS `credentials: true` + `origin: '*'` fails silently in browsers — must specify explicit origin when using credentials105- `helmet()` defaults changed between v4 and v5 — CSP is no longer set by default in v5, must configure explicitly106- CSP `unsafe-inline` negates most XSS protection — if you need inline scripts, use nonces or hashes instead107- `express.json()` without `limit` accepts arbitrarily large payloads — always set `limit: '1mb'` or similar108- `httpOnly` cookies prevent XSS token theft but NOT CSRF — still need CSRF tokens or SameSite=Strict109- Rate limiting per IP fails behind reverse proxies — must set `trust proxy` and use `X-Forwarded-For`110- `bcrypt` silently truncates passwords at 72 bytes — use Argon2 for long passphrases or pre-hash with SHA-256111112```javascript113// WRONG: credentials with wildcard origin (silently fails)114app.use(cors({ origin: '*', credentials: true }));115// RIGHT: explicit origin116app.use(cors({ origin: 'https://app.example.com', credentials: true }));117118// WRONG: helmet v5 without CSP (no longer set by default)119app.use(helmet());120// RIGHT: explicit CSP121app.use(helmet({ contentSecurityPolicy: { directives: { defaultSrc: ["'self'"] } } }));122```123124## Audit Report Format125126```markdown127## Security Audit: [App Name]128129### Summary130- **Items Passing**: X/9131- **Critical Issues**: X132- **Recommendations**: X133134### Findings135136#### [Item Name] - [PASS/FAIL/PARTIAL]137**Severity**: Critical/High/Medium/Low138**Finding**: [Description]139**Location**: [File/endpoint]140**Remediation**: [Steps to fix]141```