Technology & EngineeringVibe Coding Security385 lines
Production Hardening Checklist
Quick Summary24 lines
AI gets your application running. This checklist gets it running safely. Every item here has been found missing in production AI-generated codebases. Work through each section before launch — every unchecked item is an open vulnerability. ## Key Points - [ ] All HTTP traffic redirects to HTTPS (301) - [ ] TLS 1.2+ only (no TLS 1.0/1.1) - [ ] Strong cipher suites configured - [ ] Certificate auto-renewal (Let's Encrypt / ACM) - [ ] SSL Labs test: A+ rating (`ssllabs.com/ssltest/`) - [ ] HSTS header present on all HTTPS responses - [ ] `includeSubDomains` enabled - [ ] Submitted to HSTS preload list (hstspreload.org) - [ ] CSP header configured - [ ] No `unsafe-inline` for scripts (use nonces if needed) - [ ] No `unsafe-eval` - [ ] `frame-ancestors 'none'` (prevents clickjacking) ## Quick Example ``` Strict-Transport-Security: max-age=31536000; includeSubDomains; preload ```
skilldb get vibe-coding-security-skills/production-hardening-checklistFull skill: 385 linesPaste into your CLAUDE.md or agent config
Production Hardening Checklist
AI gets your application running. This checklist gets it running safely. Every item here has been found missing in production AI-generated codebases. Work through each section before launch — every unchecked item is an open vulnerability.
TLS / HTTPS
# Nginx — force HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Modern TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# Session settings
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
}
Checklist:
- All HTTP traffic redirects to HTTPS (301)
- TLS 1.2+ only (no TLS 1.0/1.1)
- Strong cipher suites configured
- Certificate auto-renewal (Let's Encrypt / ACM)
- SSL Labs test: A+ rating (
ssllabs.com/ssltest/)
HSTS (HTTP Strict Transport Security)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
// Express with helmet
app.use(helmet.hsts({
maxAge: 31536000, // 1 year
includeSubDomains: true,
preload: true,
}));
- HSTS header present on all HTTPS responses
-
includeSubDomainsenabled - Submitted to HSTS preload list (hstspreload.org)
Content Security Policy (CSP)
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"], // No 'unsafe-inline' or 'unsafe-eval'
styleSrc: ["'self'", "'unsafe-inline'"], // Inline styles needed for some frameworks
imgSrc: ["'self'", "data:", "https://cdn.example.com"],
connectSrc: ["'self'", "https://api.example.com"],
fontSrc: ["'self'", "https://fonts.gstatic.com"],
objectSrc: ["'none'"],
mediaSrc: ["'self'"],
frameSrc: ["'none'"],
baseUri: ["'self'"],
formAction: ["'self'"],
frameAncestors: ["'none'"],
upgradeInsecureRequests: [],
},
}));
- CSP header configured
- No
unsafe-inlinefor scripts (use nonces if needed) - No
unsafe-eval -
frame-ancestors 'none'(prevents clickjacking) - Report-URI configured for monitoring violations
Security Headers
import helmet from 'helmet';
app.use(helmet());
// Additional headers
app.use((req, res, next) => {
// Prevent MIME sniffing
res.setHeader('X-Content-Type-Options', 'nosniff');
// Prevent clickjacking
res.setHeader('X-Frame-Options', 'DENY');
// XSS protection (legacy browsers)
res.setHeader('X-XSS-Protection', '0'); // Disabled — CSP is the modern approach
// Referrer policy
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
// Permissions policy — disable unnecessary browser features
res.setHeader('Permissions-Policy',
'camera=(), microphone=(), geolocation=(), payment=(self)');
// Cross-origin policies
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
res.setHeader('Cross-Origin-Resource-Policy', 'same-origin');
next();
});
// Remove identifying headers
app.disable('x-powered-by');
Checklist:
- X-Content-Type-Options: nosniff
- X-Frame-Options: DENY
- Referrer-Policy set
- Permissions-Policy configured
- Server header removed
- X-Powered-By removed
Cookie Flags
// Every cookie must have these flags
res.cookie('session', token, {
httpOnly: true, // Not accessible via JavaScript
secure: true, // HTTPS only
sameSite: 'lax', // CSRF protection ('strict' for sensitive actions)
maxAge: 86400000, // 24 hours — not indefinite
path: '/',
domain: undefined, // Current domain only — no subdomain sharing unless needed
});
// Use __Host- prefix for maximum security
res.cookie('__Host-session', token, {
httpOnly: true,
secure: true, // Required by __Host- prefix
sameSite: 'lax',
path: '/', // Required by __Host- prefix
// domain is intentionally omitted — required by __Host- prefix
});
- httpOnly on all auth cookies
- secure flag on all cookies
- sameSite set (lax or strict)
- Reasonable maxAge (not indefinite)
- __Host- prefix where possible
DNS Configuration
# CAA record — only allow specific CAs to issue certificates
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issuewild ";" # No wildcard certs
# DMARC — prevent email spoofing
_dmarc.example.com. IN TXT "v=DMARC1; p=reject; ruf=mailto:dmarc@example.com"
# SPF — specify allowed email senders
example.com. IN TXT "v=spf1 include:_spf.google.com -all"
# DKIM — email signing (configured via your email provider)
- CAA records restrict certificate issuance
- DMARC policy set to reject
- SPF record configured
- DKIM configured
- DNSSEC enabled (if registrar supports)
DDoS Protection
Cloudflare
# Page rules for API protection
api.example.com/*
- Security Level: I'm Under Attack (during incidents)
- Rate Limiting: 100 requests per minute per IP
- Browser Integrity Check: On
# WAF rules
- Block known bot user agents
- Challenge suspicious IPs
- Block requests from TOR exit nodes (if appropriate)
AWS Shield + WAF
{
"Name": "RateLimitRule",
"Priority": 1,
"Statement": {
"RateBasedStatement": {
"Limit": 2000,
"AggregateKeyType": "IP"
}
},
"Action": { "Block": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "RateLimitRule"
}
}
- DDoS protection enabled (Cloudflare, AWS Shield, Cloud Armor)
- Rate limiting on all endpoints
- Stricter rate limiting on auth endpoints
- Geographic restrictions if applicable
- Bot detection enabled
WAF Rules
# AWS WAF managed rule groups
- AWSManagedRulesCommonRuleSet # OWASP Top 10
- AWSManagedRulesSQLiRuleSet # SQL injection
- AWSManagedRulesKnownBadInputsRuleSet # Log4j, etc.
- AWSManagedRulesBotControlRuleSet # Bot management
# Custom rules
- Block requests with bodies > 10MB
- Block requests with more than 50 query parameters
- Block requests with SQL keywords in parameters
- Rate limit by IP: 100 requests per 5 minutes
Backup Verification
#!/bin/bash
# backup-verify.sh — run weekly
# 1. Create backup
pg_dump -h $DB_HOST -U $DB_USER $DB_NAME | gzip > /tmp/backup-test.sql.gz
# 2. Restore to test database
createdb backup_test
gunzip -c /tmp/backup-test.sql.gz | psql backup_test
# 3. Verify data integrity
EXPECTED_USERS=$(psql $DB_NAME -t -c "SELECT count(*) FROM users")
RESTORED_USERS=$(psql backup_test -t -c "SELECT count(*) FROM users")
if [ "$EXPECTED_USERS" != "$RESTORED_USERS" ]; then
echo "BACKUP VERIFICATION FAILED: user count mismatch"
# Alert team
exit 1
fi
# 4. Cleanup
dropdb backup_test
rm /tmp/backup-test.sql.gz
echo "Backup verification passed"
- Automated daily backups
- Backups are encrypted at rest
- Backup restore tested monthly
- Backups stored in different region/provider
- Backup retention policy defined (e.g., 30 days)
- Point-in-time recovery enabled (RDS/Cloud SQL)
Incident Response Plan
## Incident Runbook
### Severity Levels
- P1 (Critical): Data breach, system compromise, service down
- P2 (High): Vulnerability actively exploited, partial outage
- P3 (Medium): Vulnerability discovered, no exploitation
- P4 (Low): Security improvement needed
### P1 Response (within 15 minutes)
1. Acknowledge in #incidents channel
2. Assemble response team
3. Contain the incident (revoke compromised credentials, block attack source)
4. Preserve evidence (logs, snapshots)
5. Assess impact (what data was accessed?)
6. Notify affected users (within 72 hours per GDPR)
7. Post-mortem within 48 hours
### Key Contacts
- On-call engineer: PagerDuty rotation
- Security lead: [contact]
- Legal/compliance: [contact]
- PR/communications: [contact]
### Emergency Actions
- Revoke all API keys: `./scripts/revoke-all-keys.sh`
- Enable maintenance mode: `./scripts/maintenance-on.sh`
- Block IP range: Cloudflare dashboard or `./scripts/block-ip.sh`
- Force logout all sessions: `redis-cli FLUSHDB` (session store)
- Incident response plan documented
- On-call rotation established
- Runbooks for common scenarios
- Communication templates ready
- Legal/compliance contacts identified
- Post-mortem process defined
Monitoring Setup
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Detailed health check (internal only)
app.get('/health/detailed', requireInternalNetwork, async (req, res) => {
const checks = {
database: await checkDatabase(),
redis: await checkRedis(),
storage: await checkStorage(),
memory: process.memoryUsage(),
uptime: process.uptime(),
};
const healthy = Object.values(checks).every(c => c.status !== 'error');
res.status(healthy ? 200 : 503).json(checks);
});
- Uptime monitoring (external: Pingdom, UptimeRobot)
- Application performance monitoring (Datadog, New Relic)
- Error tracking (Sentry)
- Log aggregation (CloudWatch, Datadog, ELK)
- Security event alerting
- SSL certificate expiry monitoring
- Disk space and resource alerts
- Database connection pool monitoring
The Full Pre-Launch Checklist
| Category | Item | Status |
|---|---|---|
| TLS | HTTPS enforced, TLS 1.2+ | [ ] |
| Headers | HSTS, CSP, X-Content-Type-Options | [ ] |
| Cookies | httpOnly, secure, sameSite | [ ] |
| Auth | Rate limiting on login, MFA available | [ ] |
| API | Rate limiting, input validation | [ ] |
| Database | Parameterized queries, encrypted connections | [ ] |
| Secrets | No hardcoded credentials, rotation schedule | [ ] |
| Dependencies | Audited, pinned, monitored | [ ] |
| Containers | Non-root, scanned, minimal base | [ ] |
| DNS | CAA, DMARC, SPF configured | [ ] |
| DDoS | Protection enabled, WAF rules active | [ ] |
| Backups | Automated, encrypted, tested | [ ] |
| Monitoring | Uptime, errors, security events | [ ] |
| Incident | Response plan documented, contacts ready | [ ] |
| Logging | Structured, no PII, centralized | [ ] |
| Error handling | Generic responses, no stack traces | [ ] |
No application is ready for production until every item on this list is addressed. AI will generate zero of these by default. This is the gap between "it works" and "it's safe to deploy."
Install this skill directly: skilldb add vibe-coding-security-skills
Related Skills
AI-Specific Vulnerabilities
Vibe Coding Security•378L
Authentication and Authorization Patterns
Vibe Coding Security•369L
Container and Deployment Security
Vibe Coding Security•420L
Credential Management
Vibe Coding Security•391L
Database Security Hardening
Vibe Coding Security•323L
Dependency Supply Chain Security
Vibe Coding Security•362L