diff --git a/docs/plans/QUICK_WINS_IMPLEMENTATION.md b/docs/plans/QUICK_WINS_IMPLEMENTATION.md new file mode 100644 index 00000000..4554f69c --- /dev/null +++ b/docs/plans/QUICK_WINS_IMPLEMENTATION.md @@ -0,0 +1,427 @@ +# Security Quick Wins Implementation Guide +**Get 80% of security value with 20% of effort** + +**Status:** Ready to Deploy +**Time to Implement:** 1-2 hours +**Value:** HIGH - Immediate protection against common attacks + +--- + +## What You're Getting + +✅ **Security Headers** - Prevents XSS, clickjacking, MIME sniffing +✅ **Input Validation** - Sanitizes HTML, enforces length limits +✅ **Rate Limiting** - Prevents brute force, DoS, spam +✅ **CSRF Protection** - Prevents cross-site request forgery +✅ **Security Logging** - Audit trail for all security events +✅ **Response Sanitization** - Hides stack traces and sensitive data + +**What This Protects Against:** +- Cross-Site Scripting (XSS) attacks +- Cross-Site Request Forgery (CSRF) +- Clickjacking +- MIME type confusion attacks +- Brute force authentication +- Form spam +- DoS attacks +- Information disclosure + +--- + +## Prerequisites + +### 1. Install Dependencies +```bash +cd /home/theflow/projects/tractatus + +# Install required npm packages +npm install express-rate-limit validator csurf cookie-parser +``` + +### 2. Create Log Directory +```bash +# Create security log directory +sudo mkdir -p /var/log/tractatus +sudo chown -R $USER:$USER /var/log/tractatus +sudo chmod 750 /var/log/tractatus +``` + +--- + +## Step 1: Update src/server.js + +Add the following to your `src/server.js` file. **Insert in the order shown:** + +```javascript +const express = require('express'); +const cookieParser = require('cookie-parser'); +const csrf = require('csurf'); + +// Import security middleware +const { securityHeadersMiddleware } = require('./middleware/security-headers.middleware'); +const { publicRateLimiter } = require('./middleware/rate-limit.middleware'); +const { sanitizeErrorResponse, sanitizeResponseData } = require('./middleware/response-sanitization.middleware'); + +const app = express(); + +// ============================================================ +// SECURITY MIDDLEWARE (Apply BEFORE routes) +// ============================================================ + +// 1. Security Headers (HIGH VALUE - 5 minutes to add) +app.use(securityHeadersMiddleware); + +// 2. Cookie Parser (required for CSRF) +app.use(cookieParser()); + +// 3. Body Parsers +app.use(express.json({ limit: '1mb' })); // Payload size limit +app.use(express.urlencoded({ extended: true, limit: '1mb' })); + +// 4. Response Data Sanitization +app.use(sanitizeResponseData); + +// 5. Public Rate Limiting (100 req/15min per IP) +app.use(publicRateLimiter); + +// 6. CSRF Protection (POST/PUT/DELETE/PATCH only) +const csrfProtection = csrf({ cookie: true }); +app.use((req, res, next) => { + if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(req.method)) { + return csrfProtection(req, res, next); + } + next(); +}); + +// ============================================================ +// YOUR EXISTING ROUTES +// ============================================================ + +// CSRF token endpoint (for forms) +app.get('/api/csrf-token', (req, res) => { + res.json({ csrfToken: req.csrfToken() }); +}); + +// ... your existing routes here ... + +// ============================================================ +// ERROR HANDLING (Apply AFTER routes) +// ============================================================ + +// CSRF Error Handler +app.use((err, req, res, next) => { + if (err.code === 'EBADCSRFTOKEN') { + return res.status(403).json({ + error: 'Invalid CSRF token', + message: 'Request blocked for security reasons' + }); + } + next(err); +}); + +// General Error Handler (hides stack traces in production) +app.use(sanitizeErrorResponse); + +// Start server +const PORT = process.env.PORT || 9000; +app.listen(PORT, () => { + console.log(`Server running on port ${PORT}`); + console.log('✅ Security middleware active'); +}); +``` + +--- + +## Step 2: Add Form-Specific Rate Limiting + +For form submission endpoints (contact, cases, media inquiries), add stricter rate limiting: + +```javascript +const { formRateLimiter } = require('./middleware/rate-limit.middleware'); +const { createInputValidationMiddleware } = require('./middleware/input-validation.middleware'); + +// Example: Case submission endpoint +app.post('/api/cases/submit', + formRateLimiter, // 5 submissions/min + createInputValidationMiddleware({ + title: { type: 'text', required: true, maxLength: 200 }, + description: { type: 'text', required: true, maxLength: 5000 }, + contact_email: { type: 'email', required: true }, + contact_name: { type: 'text', required: true, maxLength: 100 } + }), + casesController.submitCase +); + +// Example: Contact form +app.post('/api/contact', + formRateLimiter, + createInputValidationMiddleware({ + name: { type: 'text', required: true, maxLength: 100 }, + email: { type: 'email', required: true }, + message: { type: 'text', required: true, maxLength: 5000 } + }), + contactController.submitContact +); +``` + +--- + +## Step 3: Update Client-Side Forms for CSRF + +Add CSRF token to all forms that POST/PUT/DELETE: + +```javascript +// Fetch CSRF token before form submission +async function submitForm(formData) { + try { + // Get CSRF token + const tokenResponse = await fetch('/api/csrf-token'); + const { csrfToken } = await tokenResponse.json(); + + // Add CSRF token to form data + formData.append('_csrf', csrfToken); + + // Submit form + const response = await fetch('/api/cases/submit', { + method: 'POST', + body: formData + }); + + if (!response.ok) { + throw new Error('Submission failed'); + } + + return await response.json(); + } catch (error) { + console.error('Form submission error:', error); + throw error; + } +} +``` + +**For JSON submissions:** +```javascript +async function submitJSON(data) { + // Get CSRF token + const tokenResponse = await fetch('/api/csrf-token'); + const { csrfToken } = await tokenResponse.json(); + + // Submit with CSRF token + const response = await fetch('/api/cases/submit', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'CSRF-Token': csrfToken // Can also use header instead of body + }, + body: JSON.stringify({ + ...data, + _csrf: csrfToken // Or include in body + }) + }); + + return response.json(); +} +``` + +--- + +## Step 4: Test the Security Measures + +### Test Security Headers +```bash +# Check headers are present +curl -I http://localhost:9000 + +# Expected headers: +# Content-Security-Policy: ... +# X-Content-Type-Options: nosniff +# X-Frame-Options: DENY +# X-XSS-Protection: 1; mode=block +# Referrer-Policy: strict-origin-when-cross-origin +# Permissions-Policy: geolocation=(), ... +``` + +### Test Rate Limiting +```bash +# Exceed public limit (should get 429 after 100 requests) +for i in {1..110}; do + curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9000 +done + +# Expected: First 100 return 200, remaining return 429 +``` + +### Test Input Validation +```bash +# Test XSS payload (should be sanitized) +curl -X POST http://localhost:9000/api/contact \ + -H "Content-Type: application/json" \ + -d '{"name":"","email":"test@example.com","message":"test"}' + +# Expected: Name sanitized to empty or plain text +``` + +### Test CSRF Protection +```bash +# Request without CSRF token (should be rejected) +curl -X POST http://localhost:9000/api/contact \ + -H "Content-Type: application/json" \ + -d '{"name":"Test","email":"test@example.com","message":"test"}' + +# Expected: 403 Forbidden with "Invalid CSRF token" +``` + +### Check Security Logs +```bash +# View security events +tail -f /var/log/tractatus/security-audit.log + +# Should see JSON entries for: +# - rate_limit_exceeded +# - input_sanitized +# - input_validation_failure +``` + +--- + +## Step 5: Deploy to Production + +### 1. Commit Changes +```bash +git add src/middleware/ src/utils/security-logger.js src/server.js +git commit -m "security: implement quick wins (headers, rate limiting, CSRF, input validation)" +``` + +### 2. Deploy to Production +```bash +# Your deployment script +./scripts/deploy-full-project-SAFE.sh + +# Or manual deployment +rsync -avz --chmod=D755,F644 -e "ssh -i ~/.ssh/tractatus_deploy" \ + src/middleware/ src/utils/security-logger.js \ + ubuntu@vps-93a693da.vps.ovh.net:/var/www/tractatus/src/ + +# Restart production server +ssh -i ~/.ssh/tractatus_deploy ubuntu@vps-93a693da.vps.ovh.net \ + "sudo systemctl restart tractatus" +``` + +### 3. Verify Production +```bash +# Check headers on production +curl -I https://agenticgovernance.digital + +# Test rate limiting +for i in {1..110}; do + curl -s -o /dev/null -w "%{http_code}\n" https://agenticgovernance.digital +done + +# Check SecurityHeaders.com grade +# Visit: https://securityheaders.com/?q=https://agenticgovernance.digital +# Expected: Grade A or A+ +``` + +### 4. Monitor for Issues +```bash +# Watch production logs +ssh -i ~/.ssh/tractatus_deploy ubuntu@vps-93a693da.vps.ovh.net \ + "tail -f /var/www/tractatus/logs/combined.log" + +# Watch security logs +ssh -i ~/.ssh/tractatus_deploy ubuntu@vps-93a693da.vps.ovh.net \ + "tail -f /var/log/tractatus/security-audit.log" +``` + +--- + +## What's Next? (Phase 1-6) + +These quick wins give you immediate protection. When ready for comprehensive security: + +1. **Phase 1** - Install ClamAV, YARA, fail2ban, Redis +2. **Phase 2** - File upload malware scanning, email security +3. **Phase 3** - Enhanced input validation (NoSQL injection, XSS detection) +4. **Phase 4** - JWT authentication, Redis rate limiting, IP blocking +5. **Phase 5** - Security dashboard, ProtonMail alerts, Signal notifications +6. **Phase 6** - Penetration testing, team training, external audit + +See `docs/plans/security-implementation-roadmap.md` for full details. + +--- + +## Troubleshooting + +### "Cannot find module 'express-rate-limit'" +```bash +npm install express-rate-limit validator csurf cookie-parser +``` + +### "Permission denied: /var/log/tractatus/" +```bash +sudo mkdir -p /var/log/tractatus +sudo chown -R $USER:$USER /var/log/tractatus +sudo chmod 750 /var/log/tractatus +``` + +### CSRF token errors on GET requests +CSRF protection is only applied to POST/PUT/DELETE/PATCH. GET requests should not be affected. + +### Rate limit too restrictive +Adjust limits in `src/middleware/rate-limit.middleware.js`: +```javascript +const publicRateLimiter = createRateLimiter({ + windowMs: 15 * 60 * 1000, + max: 200, // Increase from 100 to 200 + tier: 'public' +}); +``` + +### Security headers causing issues +Temporarily disable specific headers in `src/middleware/security-headers.middleware.js` while debugging. + +--- + +## Performance Impact + +Expected performance impact: **<10ms per request** + +- Security headers: <1ms (set headers only) +- Input validation: 2-5ms (depends on input size) +- Rate limiting: 1-2ms (in-memory lookup) +- CSRF validation: 1-2ms (token comparison) +- Response sanitization: 1-2ms (field removal) + +**Total:** ~5-10ms additional latency per request (negligible for most applications) + +--- + +## Success Criteria + +✅ Security headers present on all responses +✅ SecurityHeaders.com grade A or A+ +✅ Rate limiting preventing abuse (429 errors after limits) +✅ CSRF tokens required for POST/PUT/DELETE +✅ Input sanitization removing HTML tags +✅ Security events logged to `/var/log/tractatus/security-audit.log` +✅ Error responses sanitized (no stack traces in production) +✅ Zero false positives with legitimate traffic + +--- + +## Support + +**Questions?** Check: +- `docs/plans/security-implementation-roadmap.md` - Full implementation plan +- `docs/plans/security-implementation-tracker.md` - Phase tracking +- `.claude/instruction-history.json` - inst_041 through inst_046 + +**Issues?** Create incident report in `docs/security/incidents/` + +**Ready for More?** Proceed to Phase 1 in the tracker! + +--- + +**Last Updated:** 2025-10-14 +**Version:** 1.0 (Quick Wins) +**Next:** Full Phase 1-6 implementation diff --git a/docs/plans/security-implementation-tracker.md b/docs/plans/security-implementation-tracker.md new file mode 100644 index 00000000..cbf99fdf --- /dev/null +++ b/docs/plans/security-implementation-tracker.md @@ -0,0 +1,1020 @@ +# Security Implementation Tracker +**Tractatus 6-Phase Security Framework** + +**Project Start:** 2025-10-14 +**Target Completion:** TBD +**Current Phase:** Phase 0 (Quick Wins) +**Overall Status:** 🟡 In Progress + +--- + +## Quick Reference + +| Phase | Status | Progress | Start Date | Completion Date | Effort (hours) | +|-------|--------|----------|------------|-----------------|----------------| +| **Phase 0: Quick Wins** | 🟡 In Progress | 0% | 2025-10-14 | - | 0 / 5 | +| **Phase 1: Foundation** | ⚪ Not Started | 0% | - | - | 0 / 25 | +| **Phase 2: File & Email** | ⚪ Not Started | 0% | - | - | 0 / 45 | +| **Phase 3: App Security** | ⚪ Not Started | 0% | - | - | 0 / 35 | +| **Phase 4: API Protection** | ⚪ Not Started | 0% | - | - | 0 / 35 | +| **Phase 5: Monitoring** | ⚪ Not Started | 0% | - | - | 0 / 45 | +| **Phase 6: Integration** | ⚪ Not Started | 0% | - | - | 0 / 30 | +| **TOTAL** | - | 0% | - | - | 0 / 220 | + +**Legend:** 🟢 Complete | 🟡 In Progress | 🔴 Blocked | ⚪ Not Started + +--- + +## Phase 0: Quick Wins (80/20 Approach) + +**Goal:** Implement high-value, low-effort security measures immediately +**Duration:** 1 day +**Effort:** 5 hours +**Status:** 🟡 In Progress + +### Quick Win Tasks + +#### QW-1: Security Headers Middleware ✅ HIGH VALUE, LOW EFFORT +- [ ] Create `src/middleware/security-headers.middleware.js` +- [ ] Implement CSP, HSTS, X-Frame-Options, X-Content-Type-Options +- [ ] Apply globally to all routes in `src/server.js` +- [ ] Test headers with `curl -I localhost:9000` +- [ ] Verify on SecurityHeaders.com +- **Effort:** 30 minutes +- **Value:** Prevents XSS, clickjacking, MIME sniffing attacks + +#### QW-2: Basic Input Validation ✅ HIGH VALUE, MEDIUM EFFORT +- [ ] Install dependencies: `npm install validator dompurify jsdom` +- [ ] Create `src/middleware/input-validation.middleware.js` (basic version) +- [ ] Implement HTML sanitization and length limits +- [ ] Apply to critical endpoints (cases, media, contact) +- [ ] Test with XSS payloads +- **Effort:** 1 hour +- **Value:** Prevents XSS and injection attacks on forms + +#### QW-3: Rate Limiting (In-Memory) ✅ HIGH VALUE, LOW EFFORT +- [ ] Install: `npm install express-rate-limit` +- [ ] Create `src/middleware/rate-limit.middleware.js` (basic version) +- [ ] Apply to public endpoints (100 req/15min) +- [ ] Apply to form endpoints (5 req/min) +- [ ] Test by exceeding limits +- **Effort:** 30 minutes +- **Value:** Prevents brute force, DoS, spam + +#### QW-4: File Upload Size Limits ✅ MEDIUM VALUE, LOW EFFORT +- [ ] Configure multer file size limits in existing upload routes +- [ ] Set 10MB for documents, 50MB for media +- [ ] Add basic MIME type validation +- [ ] Test with oversized files +- **Effort:** 20 minutes +- **Value:** Prevents resource exhaustion + +#### QW-5: CSRF Protection ✅ HIGH VALUE, LOW EFFORT +- [ ] Install: `npm install csurf cookie-parser` +- [ ] Configure CSRF middleware in `src/server.js` +- [ ] Add CSRF token endpoint `/api/csrf-token` +- [ ] Update client-side forms to include CSRF token +- [ ] Test CSRF rejection +- **Effort:** 45 minutes +- **Value:** Prevents cross-site request forgery + +#### QW-6: Basic Security Logging ✅ MEDIUM VALUE, LOW EFFORT +- [ ] Create `/var/log/tractatus/security-audit.log` +- [ ] Create `src/utils/security-logger.js` (simple version) +- [ ] Log failed auth attempts, rate limits, validation failures +- [ ] Test logging with security events +- **Effort:** 30 minutes +- **Value:** Audit trail for security events + +#### QW-7: Response Sanitization ✅ MEDIUM VALUE, LOW EFFORT +- [ ] Create `src/middleware/response-sanitization.middleware.js` +- [ ] Hide stack traces in production +- [ ] Remove sensitive fields from responses +- [ ] Apply error handler globally +- [ ] Test with forced errors +- **Effort:** 30 minutes +- **Value:** Prevents information disclosure + +#### QW-8: Deploy to Production ✅ CRITICAL +- [ ] Commit all changes +- [ ] Deploy security middleware to production +- [ ] Verify headers on production +- [ ] Monitor for false positives +- [ ] Create rollback plan +- **Effort:** 30 minutes +- **Value:** Security improvements live + +### Quick Wins Completion Criteria +- [ ] All 8 quick win tasks completed +- [ ] Security headers active on production +- [ ] Basic input validation working +- [ ] Rate limiting preventing abuse +- [ ] CSRF protection enabled +- [ ] Security logging operational +- [ ] Zero critical issues from quick wins +- [ ] Performance impact <10ms per request + +**Progress:** 0 / 8 tasks complete (0%) + +--- + +## Phase 1: Foundation & Sovereign Tools + +**Goal:** Install and configure all security infrastructure +**Duration:** 1-2 weeks +**Effort:** 25 hours +**Status:** ⚪ Not Started +**Dependencies:** Phase 0 complete + +### Infrastructure Installation + +#### P1-1: ClamAV Antivirus Setup +- [ ] Install ClamAV and daemon: `apt install clamav clamav-daemon` +- [ ] Configure `/etc/clamav/clamd.conf` (max file sizes) +- [ ] Configure `/etc/clamav/freshclam.conf` (daily updates) +- [ ] Update virus definitions: `freshclam` +- [ ] Enable and start services +- [ ] Test with EICAR file +- **Effort:** 2 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P1-2: YARA Pattern Matching +- [ ] Install YARA: `apt install yara` +- [ ] Create `/etc/yara/rules/` directory +- [ ] Create base rule set (suspicious executables, scripts, macros) +- [ ] Test rules on sample files +- [ ] Document rule update process +- **Effort:** 1.5 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P1-3: fail2ban Installation +- [ ] Install fail2ban: `apt install fail2ban` +- [ ] Copy jail.conf to jail.local +- [ ] Basic configuration (will integrate in Phase 5) +- [ ] Enable and start service +- [ ] Verify status +- **Effort:** 1 hour +- **Blockers:** None +- **Priority:** MEDIUM + +#### P1-4: Redis for Rate Limiting +- [ ] Install Redis: `apt install redis-server` +- [ ] Configure `/etc/redis/redis.conf` (bind localhost, password) +- [ ] Set maxmemory 256mb +- [ ] Enable and start service +- [ ] Test connection with redis-cli +- **Effort:** 1 hour +- **Blockers:** None +- **Priority:** MEDIUM (can use in-memory initially) + +#### P1-5: Email Stack Installation +- [ ] Install postfix: `apt install postfix` +- [ ] Install SpamAssassin: `apt install spamassassin` +- [ ] Install amavisd-new: `apt install amavisd-new` +- [ ] Install OpenDKIM: `apt install opendkim` +- [ ] Basic configuration (detailed in Phase 2) +- [ ] Verify services running +- **Effort:** 3 hours +- **Blockers:** None +- **Priority:** LOW (can defer if no email submissions yet) + +### Logging Infrastructure + +#### P1-6: Log Directory Setup +- [ ] Create `/var/log/tractatus/` with correct permissions +- [ ] Create `/var/quarantine/tractatus/` for suspicious files +- [ ] Create `/var/quarantine/email/` for suspicious emails +- [ ] Configure log rotation in `/etc/logrotate.d/tractatus` +- [ ] Test log rotation +- **Effort:** 30 minutes +- **Blockers:** None +- **Priority:** HIGH + +### Communication Setup + +#### P1-7: ProtonMail Configuration +- [ ] Create ProtonMail Business accounts +- [ ] Configure `security@tractatus.digital` +- [ ] Configure `admin@tractatus.digital` +- [ ] Set up custom domain integration +- [ ] Test email delivery to all team members +- [ ] Document credentials securely +- **Effort:** 2 hours +- **Blockers:** None +- **Priority:** MEDIUM + +#### P1-8: Signal Setup +- [ ] Create "Tractatus Security Team" Signal group +- [ ] Add all team members with verified numbers +- [ ] Document escalation protocol (4 levels) +- [ ] Test notification chain with dummy alert +- [ ] Save group ID for automation +- **Effort:** 1 hour +- **Blockers:** Team member availability +- **Priority:** MEDIUM + +### Documentation + +#### P1-9: Security Documentation Structure +- [ ] Create `docs/security/` directory structure +- [ ] Create `SECURITY_POLICY.md` (template) +- [ ] Create `INCIDENT_RESPONSE.md` (template) +- [ ] Create `ALERT_THRESHOLDS.md` +- [ ] Create `TOOL_INVENTORY.md` +- [ ] Document all installed tools and versions +- **Effort:** 2 hours +- **Blockers:** None +- **Priority:** MEDIUM + +### Phase 1 Completion Criteria +- [ ] All sovereign tools installed and operational +- [ ] ClamAV scanning functional (tested with EICAR) +- [ ] YARA rules loading without errors +- [ ] fail2ban service running +- [ ] Redis operational (or documented as deferred) +- [ ] Email stack installed (or documented as deferred) +- [ ] Log directories created with correct permissions +- [ ] ProtonMail accounts configured +- [ ] Signal group created with all team members +- [ ] Security documentation structure in place +- [ ] Tool inventory documented + +**Progress:** 0 / 9 tasks complete (0%) + +--- + +## Phase 2: File & Email Security + +**Goal:** Implement file upload validation and email security pipeline +**Duration:** 2-3 weeks +**Effort:** 45 hours +**Status:** ⚪ Not Started +**Dependencies:** Phase 1 complete + +### File Upload Validation (inst_041) + +#### P2-1: Enhanced Security Logger +- [ ] Upgrade `src/utils/security-logger.js` with full JSON logging +- [ ] Add severity levels +- [ ] Add event type taxonomy +- [ ] Test logging to `/var/log/tractatus/security-audit.log` +- [ ] Verify log format with JSON parser +- **Effort:** 1 hour +- **Blockers:** Phase 1 logging setup +- **Priority:** HIGH + +#### P2-2: File Security Middleware +- [ ] Create `src/middleware/file-security.middleware.js` +- [ ] Implement file(1) type validation +- [ ] Integrate ClamAV scanning (clamdscan) +- [ ] Integrate YARA pattern matching +- [ ] Implement quarantine system +- [ ] Add comprehensive logging +- [ ] Create size limit enforcement +- **Effort:** 6 hours +- **Blockers:** Phase 1 ClamAV/YARA installed +- **Priority:** HIGH + +#### P2-3: File Upload Route Integration +- [ ] Apply file security to `/api/cases/submit` +- [ ] Apply to `/api/media/upload` +- [ ] Apply to any other upload endpoints +- [ ] Update multer configuration +- [ ] Test with clean files +- [ ] Test with malware samples (EICAR) +- **Effort:** 2 hours +- **Blockers:** P2-2 complete +- **Priority:** HIGH + +#### P2-4: Quarantine Management +- [ ] Create quarantine review script +- [ ] Add manual release procedure +- [ ] Add permanent delete procedure +- [ ] Document quarantine workflow +- [ ] Test quarantine/release/delete +- **Effort:** 2 hours +- **Blockers:** P2-2 complete +- **Priority:** MEDIUM + +### Email Security (inst_042) + +#### P2-5: Postfix Configuration +- [ ] Configure `/etc/postfix/main.cf` +- [ ] Set up virtual domains +- [ ] Configure relay restrictions +- [ ] Enable TLS +- [ ] Test mail delivery +- **Effort:** 3 hours +- **Blockers:** Phase 1 email stack installed +- **Priority:** MEDIUM (if email submissions active) + +#### P2-6: SpamAssassin Configuration +- [ ] Configure `/etc/spamassassin/local.cf` +- [ ] Set required score: 5.0 +- [ ] Add custom rules for governance domain +- [ ] Enable auto-learn +- [ ] Test spam filtering +- **Effort:** 2 hours +- **Blockers:** P2-5 complete +- **Priority:** MEDIUM + +#### P2-7: amavisd-new Integration +- [ ] Configure `/etc/amavis/conf.d/` +- [ ] Integrate ClamAV backend +- [ ] Set virus scanning policies +- [ ] Configure quarantine actions +- [ ] Test virus detection in email +- **Effort:** 3 hours +- **Blockers:** P2-5, P2-6 complete +- **Priority:** MEDIUM + +#### P2-8: DKIM/SPF/DMARC Setup +- [ ] Generate DKIM keys +- [ ] Add DNS TXT records (DKIM, SPF, DMARC) +- [ ] Configure OpenDKIM +- [ ] Test email authentication +- [ ] Verify with mail-tester.com +- **Effort:** 4 hours +- **Blockers:** P2-5 complete +- **Priority:** MEDIUM + +#### P2-9: Email Attachment Validation +- [ ] Configure allowed attachment types +- [ ] Block executables, scripts, archives +- [ ] Implement attachment scanning +- [ ] Set up email quarantine +- [ ] Test with various attachment types +- **Effort:** 2 hours +- **Blockers:** P2-7 complete +- **Priority:** MEDIUM + +### Testing & Documentation + +#### P2-10: File Security Testing +- [ ] Test with clean PDF, DOC, images +- [ ] Test with EICAR malware +- [ ] Test with MIME type mismatch +- [ ] Test with oversized files +- [ ] Test with ZIP bombs +- [ ] Document test results +- **Effort:** 2 hours +- **Blockers:** P2-3 complete +- **Priority:** HIGH + +#### P2-11: Email Security Testing +- [ ] Send clean email with attachment +- [ ] Send spam-like email +- [ ] Send email with malware attachment +- [ ] Test DKIM/SPF/DMARC validation +- [ ] Verify quarantine functionality +- [ ] Document test results +- **Effort:** 2 hours +- **Blockers:** P2-9 complete +- **Priority:** MEDIUM + +### Phase 2 Completion Criteria +- [ ] File upload validation operational on all endpoints +- [ ] ClamAV detecting malware (100% EICAR detection) +- [ ] YARA detecting suspicious patterns +- [ ] File quarantine system working +- [ ] Clean files passing validation +- [ ] Email stack configured (if applicable) +- [ ] Spam filtering operational +- [ ] Email virus scanning functional +- [ ] DKIM/SPF/DMARC passing +- [ ] Email quarantine working +- [ ] Zero false positives with legitimate files +- [ ] All tests documented + +**Progress:** 0 / 11 tasks complete (0%) + +--- + +## Phase 3: Application Security + +**Goal:** Input validation, HTTP headers, CSRF protection, CSP reporting +**Duration:** 1-2 weeks +**Effort:** 35 hours +**Status:** ⚪ Not Started +**Dependencies:** Phase 0 (quick wins provide foundation) + +### Enhanced Input Validation + +#### P3-1: Full Input Validation Middleware +- [ ] Enhance existing input validation from Phase 0 +- [ ] Add data type validation (email, URL, phone, numeric) +- [ ] Add NoSQL injection detection +- [ ] Add XSS pattern detection +- [ ] Implement validation schemas per endpoint +- [ ] Test with injection payloads +- **Effort:** 4 hours +- **Blockers:** Phase 0 basic validation in place +- **Priority:** HIGH + +#### P3-2: Apply Validation to All Endpoints +- [ ] `/api/cases/submit` validation schema +- [ ] `/api/media/inquiry` validation schema +- [ ] `/api/contact` validation schema +- [ ] Any other form endpoints +- [ ] Test each endpoint with valid/invalid data +- **Effort:** 3 hours +- **Blockers:** P3-1 complete +- **Priority:** HIGH + +### Enhanced Security Headers + +#### P3-3: Upgrade Security Headers +- [ ] Enhance existing headers from Phase 0 +- [ ] Add Permissions-Policy +- [ ] Fine-tune CSP directives +- [ ] Add CSP report-uri +- [ ] Test on SecurityHeaders.com (target: A+) +- **Effort:** 2 hours +- **Blockers:** Phase 0 basic headers in place +- **Priority:** MEDIUM + +#### P3-4: CSP Violation Reporting Endpoint +- [ ] Create `/api/csp-violations` endpoint +- [ ] Parse CSP reports +- [ ] Log to security audit trail +- [ ] Test with intentional CSP violation +- [ ] Monitor for patterns +- **Effort:** 2 hours +- **Blockers:** P3-3 complete +- **Priority:** MEDIUM + +### CSRF Protection + +#### P3-5: CSRF Token Management +- [ ] Enhance CSRF from Phase 0 if needed +- [ ] Ensure all POST/PUT/DELETE protected +- [ ] Test token rotation per session +- [ ] Test CSRF rejection +- [ ] Document client-side integration +- **Effort:** 1 hour +- **Blockers:** Phase 0 CSRF in place +- **Priority:** HIGH + +### Testing & Documentation + +#### P3-6: Input Validation Testing +- [ ] Test XSS payloads (script tags, event handlers) +- [ ] Test NoSQL injection (`$ne`, `$gt`, etc.) +- [ ] Test SQL injection patterns +- [ ] Test length limit enforcement +- [ ] Test data type validation +- [ ] Document all test cases +- **Effort:** 3 hours +- **Blockers:** P3-2 complete +- **Priority:** HIGH + +#### P3-7: Security Headers Testing +- [ ] Verify all headers present +- [ ] Test CSP blocking inline scripts +- [ ] Test X-Frame-Options blocking iframes +- [ ] Test HSTS enforcement +- [ ] Run SecurityHeaders.com scan +- [ ] Document header configuration +- **Effort:** 2 hours +- **Blockers:** P3-3 complete +- **Priority:** MEDIUM + +### Phase 3 Completion Criteria +- [ ] Input validation on all form endpoints +- [ ] HTML sanitization removing XSS patterns +- [ ] NoSQL injection detection functional +- [ ] Security headers returning A or A+ grade +- [ ] CSP violation reporting operational +- [ ] CSRF protection on all state-changing operations +- [ ] Zero false positives with legitimate input +- [ ] All tests passing +- [ ] Documentation complete + +**Progress:** 0 / 7 tasks complete (0%) + +--- + +## Phase 4: API Protection + +**Goal:** Rate limiting, JWT authentication, IP blocking, request validation +**Duration:** 1-2 weeks +**Effort:** 35 hours +**Status:** ⚪ Not Started +**Dependencies:** Phase 1 (Redis), Phase 0 (basic rate limiting) + +### JWT Authentication System + +#### P4-1: JWT Middleware Implementation +- [ ] Create `src/middleware/auth.middleware.js` +- [ ] Implement access token generation (15min expiry) +- [ ] Implement refresh token generation (7day expiry) +- [ ] Implement token verification +- [ ] Add role-based authorization +- [ ] Test token lifecycle +- **Effort:** 4 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P4-2: Authentication Routes +- [ ] Create `/api/auth/login` endpoint +- [ ] Create `/api/auth/refresh` endpoint +- [ ] Create `/api/auth/logout` endpoint +- [ ] Hash passwords with bcrypt +- [ ] Test authentication flow +- **Effort:** 3 hours +- **Blockers:** P4-1 complete +- **Priority:** HIGH + +#### P4-3: Apply Authentication to Routes +- [ ] Protect `/api/cases/*` (authenticated) +- [ ] Protect `/api/media/*` (authenticated) +- [ ] Protect `/api/admin/*` (admin role) +- [ ] Protect `/api/governance/*` (admin role) +- [ ] Test unauthorized access rejection +- **Effort:** 2 hours +- **Blockers:** P4-2 complete +- **Priority:** HIGH + +### Enhanced Rate Limiting + +#### P4-4: Redis-Based Rate Limiting +- [ ] Upgrade rate limiting from Phase 0 to use Redis +- [ ] Create `src/middleware/rate-limit.middleware.js` (full version) +- [ ] Implement public tier (100 req/15min) +- [ ] Implement authenticated tier (1000 req/15min) +- [ ] Implement admin tier (50 req/15min) +- [ ] Test each tier +- **Effort:** 3 hours +- **Blockers:** Phase 1 Redis installed +- **Priority:** HIGH + +#### P4-5: IP Blocking System +- [ ] Implement violation tracking in Redis +- [ ] Add automatic blocking (10 violations = 24hr block) +- [ ] Create IP whitelist mechanism +- [ ] Test blocking and expiry +- [ ] Document manual unblock procedure +- **Effort:** 3 hours +- **Blockers:** P4-4 complete +- **Priority:** MEDIUM + +### API Request Validation + +#### P4-6: API Validation Middleware +- [ ] Create `src/middleware/api-validation.middleware.js` +- [ ] Implement content-type validation +- [ ] Implement payload size validation (1MB max) +- [ ] Implement unexpected field rejection +- [ ] Test with malformed requests +- **Effort:** 2 hours +- **Blockers:** None +- **Priority:** MEDIUM + +### Response Sanitization + +#### P4-7: Enhanced Response Sanitization +- [ ] Upgrade from Phase 0 quick win +- [ ] Hide stack traces in production +- [ ] Remove internal paths from errors +- [ ] Sanitize database errors +- [ ] Test with forced errors +- **Effort:** 2 hours +- **Blockers:** Phase 0 basic sanitization +- **Priority:** MEDIUM + +### Testing & Documentation + +#### P4-8: Authentication Testing +- [ ] Test login with valid credentials +- [ ] Test login with invalid credentials +- [ ] Test token expiry (15min access) +- [ ] Test refresh token flow +- [ ] Test role-based authorization +- [ ] Document JWT configuration +- **Effort:** 2 hours +- **Blockers:** P4-3 complete +- **Priority:** HIGH + +#### P4-9: Rate Limiting Testing +- [ ] Exceed public limit (test 101 requests) +- [ ] Exceed authenticated limit (test 1001 requests) +- [ ] Trigger IP block (10 violations) +- [ ] Verify Redis storing data +- [ ] Test distributed rate limiting +- [ ] Document rate limit configuration +- **Effort:** 2 hours +- **Blockers:** P4-5 complete +- **Priority:** HIGH + +### Phase 4 Completion Criteria +- [ ] JWT authentication operational +- [ ] Access tokens expiring after 15 minutes +- [ ] Refresh tokens working (7 days) +- [ ] Role-based authorization enforced +- [ ] Redis-based rate limiting active +- [ ] IP blocking functional (10 violations = block) +- [ ] Content-type validation enforced +- [ ] Payload size limits working +- [ ] Response sanitization hiding sensitive data +- [ ] All tests passing +- [ ] Documentation complete + +**Progress:** 0 / 9 tasks complete (0%) + +--- + +## Phase 5: Security Monitoring & Alerting + +**Goal:** Dashboard, fail2ban, alerts, weekly reports +**Duration:** 2-3 weeks +**Effort:** 45 hours +**Status:** ⚪ Not Started +**Dependencies:** Phases 1-4 complete + +### Security Monitoring Dashboard + +#### P5-1: Dashboard Frontend +- [ ] Create `public/admin/security-monitoring.html` +- [ ] Build metrics grid (8 key metrics) +- [ ] Build recent events table +- [ ] Build top violating IPs display +- [ ] Add time range selector +- [ ] Style with Tailwind +- **Effort:** 6 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P5-2: Dashboard Backend API +- [ ] Create `src/controllers/security-monitoring.controller.js` +- [ ] Implement log parsing function +- [ ] Implement metrics calculation +- [ ] Create `/api/security-monitoring/metrics` endpoint +- [ ] Create `/api/security-monitoring/events` endpoint +- [ ] Test with sample log data +- **Effort:** 4 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P5-3: Dashboard Client-Side Logic +- [ ] Create `public/js/admin/security-monitoring.js` +- [ ] Fetch and display metrics +- [ ] Fetch and render events table +- [ ] Implement auto-refresh (every 30s) +- [ ] Add loading states +- [ ] Test dashboard interaction +- **Effort:** 3 hours +- **Blockers:** P5-1, P5-2 complete +- **Priority:** HIGH + +### fail2ban Integration + +#### P5-4: fail2ban Filter Configuration +- [ ] Create `/etc/fail2ban/filter.d/tractatus.conf` +- [ ] Add patterns for rate limit violations +- [ ] Add patterns for authentication failures +- [ ] Add patterns for injection attempts +- [ ] Test filter with fail2ban-regex +- **Effort:** 2 hours +- **Blockers:** Phase 1 fail2ban installed +- **Priority:** MEDIUM + +#### P5-5: fail2ban Jail Configuration +- [ ] Configure jail in `/etc/fail2ban/jail.local` +- [ ] Set maxretry: 10, findtime: 3600, bantime: 86400 +- [ ] Enable tractatus jail +- [ ] Restart fail2ban +- [ ] Test banning with violations +- **Effort:** 1 hour +- **Blockers:** P5-4 complete +- **Priority:** MEDIUM + +### Alert System + +#### P5-6: ProtonMail Alert Integration +- [ ] Install ProtonMail Bridge on server +- [ ] Create `src/utils/email-alerts.js` +- [ ] Configure nodemailer with ProtonMail Bridge +- [ ] Create email alert templates +- [ ] Test email sending +- **Effort:** 3 hours +- **Blockers:** Phase 1 ProtonMail accounts +- **Priority:** MEDIUM + +#### P5-7: Signal Notification Integration +- [ ] Install signal-cli on server +- [ ] Register Signal number +- [ ] Create `src/utils/signal-alerts.js` +- [ ] Implement text notification function +- [ ] Test Signal sending to group +- **Effort:** 2 hours +- **Blockers:** Phase 1 Signal group created +- **Priority:** MEDIUM + +#### P5-8: Alert Monitoring Service +- [ ] Create `src/services/alert-monitor.service.js` +- [ ] Implement threshold checking (10 violations, 100 global) +- [ ] Integrate email alerts +- [ ] Integrate Signal notifications +- [ ] Start monitoring on server startup +- [ ] Test alert triggers +- **Effort:** 4 hours +- **Blockers:** P5-6, P5-7 complete +- **Priority:** HIGH + +### Weekly Security Reports + +#### P5-9: Report Generator Script +- [ ] Create `scripts/generate-security-report.js` +- [ ] Implement metrics aggregation (7 days) +- [ ] Implement trend analysis (week-over-week) +- [ ] Identify attack patterns +- [ ] Generate recommendations +- [ ] Email report to security team +- **Effort:** 4 hours +- **Blockers:** P5-6 complete +- **Priority:** MEDIUM + +#### P5-10: Schedule Weekly Reports +- [ ] Add cron job for Monday 9am reports +- [ ] Test manual report generation +- [ ] Verify email delivery +- [ ] Create report archive directory +- [ ] Document report format +- **Effort:** 1 hour +- **Blockers:** P5-9 complete +- **Priority:** MEDIUM + +### Testing & Documentation + +#### P5-11: Dashboard Testing +- [ ] Verify metrics calculating correctly +- [ ] Test with various time ranges +- [ ] Test event table pagination +- [ ] Test auto-refresh +- [ ] Load test dashboard (1000+ events) +- [ ] Document dashboard usage +- **Effort:** 2 hours +- **Blockers:** P5-3 complete +- **Priority:** HIGH + +#### P5-12: Alert Testing +- [ ] Trigger single IP alert (10 violations) +- [ ] Trigger global alert (100 violations) +- [ ] Trigger malware alert +- [ ] Verify email delivery +- [ ] Verify Signal notification +- [ ] Test alert escalation +- **Effort:** 2 hours +- **Blockers:** P5-8 complete +- **Priority:** HIGH + +### Phase 5 Completion Criteria +- [ ] Security dashboard accessible and functional +- [ ] Metrics displaying correctly +- [ ] Recent events table showing log data +- [ ] fail2ban banning IPs automatically +- [ ] ProtonMail alerts sending successfully +- [ ] Signal notifications delivering +- [ ] Alert thresholds triggering correctly +- [ ] Weekly reports generating and emailing +- [ ] No false positive alerts +- [ ] All tests passing +- [ ] Documentation complete + +**Progress:** 0 / 12 tasks complete (0%) + +--- + +## Phase 6: Integration & Hardening + +**Goal:** Testing, penetration testing, documentation, training +**Duration:** 1-2 weeks +**Effort:** 30 hours +**Status:** ⚪ Not Started +**Dependencies:** Phases 1-5 complete + +### Integration Testing + +#### P6-1: End-to-End Security Tests +- [ ] Create `tests/integration/security-integration.test.js` +- [ ] Test file upload → malware → quarantine → alert flow +- [ ] Test XSS attempt → sanitization → rate limit → block flow +- [ ] Test auth failure → logging → alert flow +- [ ] Test coordinated attack → multiple layers → escalation +- [ ] All integration tests passing +- **Effort:** 6 hours +- **Blockers:** All previous phases complete +- **Priority:** HIGH + +#### P6-2: Performance Testing +- [ ] Measure baseline response times (without security) +- [ ] Measure with all security middleware (<50ms impact) +- [ ] Load test rate limiting +- [ ] Stress test file validation +- [ ] Profile Redis performance +- [ ] Optimize bottlenecks +- **Effort:** 4 hours +- **Blockers:** P6-1 complete +- **Priority:** MEDIUM + +### Penetration Testing + +#### P6-3: Automated Security Scanning +- [ ] Run OWASP ZAP scan +- [ ] Run Nikto web scanner +- [ ] Run testssl.sh for TLS +- [ ] Run nmap port scan +- [ ] Document findings +- [ ] Fix critical vulnerabilities +- **Effort:** 3 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P6-4: Manual Penetration Testing +- [ ] SQL/NoSQL injection attempts +- [ ] XSS payload testing +- [ ] CSRF bypass attempts +- [ ] Authentication bypass attempts +- [ ] Authorization escalation tests +- [ ] File upload exploits +- [ ] Document all findings +- [ ] Fix all issues found +- **Effort:** 6 hours +- **Blockers:** P6-3 complete +- **Priority:** HIGH + +### Documentation + +#### P6-5: Complete Security Documentation +- [ ] Finalize `SECURITY_POLICY.md` +- [ ] Complete `INCIDENT_RESPONSE.md` +- [ ] Document `ALERT_THRESHOLDS.md` +- [ ] Update `TOOL_INVENTORY.md` +- [ ] Create `SECURITY_TESTING.md` +- [ ] Review all documentation for accuracy +- **Effort:** 4 hours +- **Blockers:** None +- **Priority:** HIGH + +#### P6-6: Operational Runbooks +- [ ] Create daily operations checklist +- [ ] Create weekly operations checklist +- [ ] Create monthly operations checklist +- [ ] Create troubleshooting guide +- [ ] Create disaster recovery procedures +- [ ] Test all procedures +- **Effort:** 3 hours +- **Blockers:** P6-5 complete +- **Priority:** MEDIUM + +### Team Training + +#### P6-7: Security Training Sessions +- [ ] Schedule training sessions (7 hours per member) +- [ ] Module 1: Security Framework Overview (1 hour) +- [ ] Module 2: Incident Response Training (2 hours) +- [ ] Module 3: Tool-Specific Training (3 hours) +- [ ] Module 4: Security Monitoring (1 hour) +- [ ] All team members trained +- **Effort:** 2 hours prep + training time +- **Blockers:** P6-5 complete +- **Priority:** HIGH + +#### P6-8: Incident Response Drill +- [ ] Create incident simulation scenario +- [ ] Schedule drill with team +- [ ] Execute incident response playbook +- [ ] Time response actions +- [ ] Identify improvement areas +- [ ] Update playbook based on learnings +- **Effort:** 3 hours +- **Blockers:** P6-7 complete +- **Priority:** MEDIUM + +### Final Validation + +#### P6-9: External Security Audit +- [ ] Engage external security consultant (optional) +- [ ] Provide audit scope and access +- [ ] Review audit findings +- [ ] Address critical/high findings +- [ ] Document remediation +- [ ] Obtain sign-off +- **Effort:** Variable (external) +- **Blockers:** P6-4 complete +- **Priority:** MEDIUM (optional but recommended) + +#### P6-10: Production Deployment Approval +- [ ] Complete deployment checklist +- [ ] Review all test results +- [ ] Confirm zero critical vulnerabilities +- [ ] Obtain stakeholder approval +- [ ] Schedule production deployment +- [ ] Execute deployment +- [ ] Monitor for issues +- **Effort:** 2 hours +- **Blockers:** All tasks complete +- **Priority:** CRITICAL + +### Phase 6 Completion Criteria +- [ ] All integration tests passing +- [ ] Performance impact <50ms +- [ ] Penetration testing complete (no critical findings) +- [ ] All security documentation complete +- [ ] Operational runbooks tested +- [ ] Team training complete (100% attendance) +- [ ] Incident response drill successful +- [ ] External audit passed (if conducted) +- [ ] Production deployment approved +- [ ] Post-implementation review complete + +**Progress:** 0 / 10 tasks complete (0%) + +--- + +## Maintenance Schedule + +### Daily Checks (5 minutes) +- [ ] Review security dashboard +- [ ] Check for critical alerts +- [ ] Verify fail2ban status +- [ ] Check ClamAV daemon running + +### Weekly Tasks (30 minutes) +- [ ] Review weekly security report +- [ ] Analyze attack patterns +- [ ] Review quarantined files +- [ ] Update YARA rules if needed + +### Monthly Tasks (2 hours) +- [ ] Verify ClamAV definitions updating +- [ ] Review and adjust alert thresholds +- [ ] Update security tool versions +- [ ] Review access control lists +- [ ] Security metrics review meeting + +### Quarterly Tasks (1 day) +- [ ] Comprehensive security audit +- [ ] Penetration testing +- [ ] Team training refresher +- [ ] Review incident response playbook +- [ ] Update security documentation + +--- + +## Risk Register + +| Risk | Likelihood | Impact | Mitigation | Owner | Status | +|------|------------|--------|------------|-------|--------| +| ClamAV false positives | Medium | Medium | Whitelist mechanism, manual review | SysAdmin | ⚪ | +| Redis failure impacts rate limiting | Low | High | Fallback to in-memory | Developer | ⚪ | +| Performance degradation | Medium | Medium | Benchmarking, optimization | Developer | ⚪ | +| Alert fatigue | Medium | High | Threshold tuning | Security Team | ⚪ | +| Tool incompatibility | Low | Medium | Version control, testing | SysAdmin | ⚪ | +| Zero-day exploits | Low | High | Defense in depth, monitoring | Security Team | ⚪ | + +--- + +## Notes & Decisions + +### 2025-10-14: Initial Tracker Creation +- Created 6-phase implementation tracker +- Added Phase 0 for quick wins (80/20 approach) +- Quick wins: Security headers, input validation, rate limiting, CSRF, logging, response sanitization +- Target: Get basic security in place within 1 day + +### Decisions Log +- [ ] Decision: Start with Phase 0 (quick wins) before full implementation +- [ ] Decision: Use in-memory rate limiting initially, upgrade to Redis in Phase 4 +- [ ] Decision: Defer email stack if no email submissions yet +- [ ] Decision: ProtonMail Business for secure communications +- [ ] Decision: Signal for team notifications and video calls + +--- + +## Contact & Escalation + +**Security Team:** +- Project Owner: [Name] +- Lead Developer: [Name] +- System Administrator: [Name] +- Security Reviewer: [Name] + +**Escalation Path:** +1. Low: Email security@tractatus.digital +2. Medium: Email + Signal text +3. High: Signal text + phone call +4. Critical: Signal video call (immediate) + +**External Resources:** +- Security Consultant: [Contact] +- Legal Counsel: [Contact] +- Incident Response: [Contact] + +--- + +**Last Updated:** 2025-10-14 +**Next Review:** After Phase 0 completion +**Tracker Version:** 1.0 diff --git a/src/middleware/input-validation.middleware.js b/src/middleware/input-validation.middleware.js new file mode 100644 index 00000000..834fd6b0 --- /dev/null +++ b/src/middleware/input-validation.middleware.js @@ -0,0 +1,179 @@ +/** + * Input Validation Middleware (inst_043 - Quick Win Version) + * Sanitizes and validates all user input + * + * QUICK WIN: Basic HTML sanitization and length limits + * Full version in Phase 3 will add NoSQL/XSS detection, type validation + */ + +const validator = require('validator'); +const { logSecurityEvent, getClientIp } = require('../utils/security-logger'); + +// Input length limits per field type (inst_043) +const LENGTH_LIMITS = { + email: 254, + url: 2048, + phone: 20, + name: 100, + title: 200, + description: 5000, + case_study: 50000, + default: 5000 +}; + +/** + * Basic HTML sanitization (removes HTML tags) + * Full version will use DOMPurify for more sophisticated sanitization + */ +function sanitizeHTML(input) { + if (typeof input !== 'string') return ''; + + // Remove HTML tags (basic approach) + return input + .replace(/<[^>]*>/g, '') // Remove HTML tags + .replace(/javascript:/gi, '') // Remove javascript: URLs + .replace(/on\w+\s*=/gi, '') // Remove event handlers + .trim(); +} + +/** + * Validate email format + */ +function isValidEmail(email) { + return validator.isEmail(email); +} + +/** + * Validate URL format + */ +function isValidURL(url) { + return validator.isURL(url, { require_protocol: true }); +} + +/** + * Create input validation middleware + */ +function createInputValidationMiddleware(schema) { + return async (req, res, next) => { + const clientIp = getClientIp(req); + const errors = []; + const sanitized = {}; + + try { + for (const [field, config] of Object.entries(schema)) { + const value = req.body[field]; + + // Required field check + if (config.required && !value) { + errors.push(`${field} is required`); + continue; + } + + // Skip validation if optional and not provided + if (!value && !config.required) { + continue; + } + + // Length validation + const maxLength = config.maxLength || LENGTH_LIMITS[config.type] || LENGTH_LIMITS.default; + if (value && value.length > maxLength) { + errors.push(`${field} exceeds maximum length of ${maxLength} characters`); + continue; + } + + // Type-specific validation + if (config.type === 'email' && !isValidEmail(value)) { + errors.push(`${field} must be a valid email address`); + continue; + } + + if (config.type === 'url' && !isValidURL(value)) { + errors.push(`${field} must be a valid URL`); + continue; + } + + // HTML sanitization (always applied to text fields) + if (typeof value === 'string') { + sanitized[field] = sanitizeHTML(value); + + // Log if sanitization changed the input (potential XSS attempt) + if (sanitized[field] !== value) { + await logSecurityEvent({ + type: 'input_sanitized', + sourceIp: clientIp, + userId: req.user?.id, + endpoint: req.path, + userAgent: req.get('user-agent'), + details: { + field, + original_length: value.length, + sanitized_length: sanitized[field].length + }, + action: 'sanitized', + severity: 'low' + }); + } + } else { + sanitized[field] = value; + } + } + + // If validation errors, reject request + if (errors.length > 0) { + await logSecurityEvent({ + type: 'input_validation_failure', + sourceIp: clientIp, + userId: req.user?.id, + endpoint: req.path, + userAgent: req.get('user-agent'), + details: { + errors, + fields: Object.keys(schema) + }, + action: 'rejected', + severity: 'medium' + }); + + return res.status(400).json({ + error: 'Validation failed', + details: errors + }); + } + + // Replace req.body with sanitized values + req.body = { ...req.body, ...sanitized }; + req.validationPassed = true; + + next(); + + } catch (error) { + console.error('[INPUT VALIDATION ERROR]', error); + + await logSecurityEvent({ + type: 'input_validation_error', + sourceIp: clientIp, + userId: req.user?.id, + endpoint: req.path, + userAgent: req.get('user-agent'), + details: { + error: error.message + }, + action: 'rejected', + severity: 'high' + }); + + return res.status(500).json({ + error: 'Validation failed', + message: 'An error occurred during input validation' + }); + } + }; +} + +module.exports = { + createInputValidationMiddleware, + sanitizeHTML, + isValidEmail, + isValidURL, + LENGTH_LIMITS +}; diff --git a/src/middleware/rate-limit.middleware.js b/src/middleware/rate-limit.middleware.js new file mode 100644 index 00000000..f71e8d1a --- /dev/null +++ b/src/middleware/rate-limit.middleware.js @@ -0,0 +1,96 @@ +/** + * Rate Limiting Middleware (inst_045 - Quick Win Version) + * Prevents brute force, DoS, and spam attacks + * + * QUICK WIN: In-memory rate limiting (no Redis required) + * Full version in Phase 4 will use Redis for distributed rate limiting + */ + +const rateLimit = require('express-rate-limit'); +const { logSecurityEvent, getClientIp } = require('../utils/security-logger'); + +/** + * Create rate limiter with custom handler for security logging + */ +function createRateLimiter(options) { + const { + windowMs, + max, + tier, + message, + skipSuccessfulRequests = false + } = options; + + return rateLimit({ + windowMs, + max, + skipSuccessfulRequests, + standardHeaders: true, + legacyHeaders: false, + handler: async (req, res) => { + const clientIp = getClientIp(req); + + await logSecurityEvent({ + type: 'rate_limit_exceeded', + sourceIp: clientIp, + userId: req.user?.id || req.user?.userId, + endpoint: req.path, + userAgent: req.get('user-agent'), + details: { + tier, + limit: max, + window_ms: windowMs, + window_display: `${windowMs / 1000} seconds` + }, + action: 'blocked', + severity: 'medium' + }); + + res.status(429).json({ + error: 'Rate limit exceeded', + message: message || `Too many requests. Limit: ${max} per ${windowMs / 1000} seconds`, + retryAfter: Math.ceil(windowMs / 1000) + }); + } + }); +} + +/** + * Public endpoints: 100 requests per 15 minutes per IP (inst_045) + */ +const publicRateLimiter = createRateLimiter({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, + tier: 'public', + message: 'Too many requests from this IP. Please try again later.' +}); + +/** + * Form submissions: 5 requests per minute per IP (inst_043) + * More restrictive for form spam prevention + */ +const formRateLimiter = createRateLimiter({ + windowMs: 60 * 1000, // 1 minute + max: 5, + tier: 'form', + message: 'Too many form submissions. Please wait before submitting again.' +}); + +/** + * Authentication endpoints: 10 attempts per 5 minutes + * Prevents brute force authentication attacks + */ +const authRateLimiter = createRateLimiter({ + windowMs: 5 * 60 * 1000, // 5 minutes + max: 10, + tier: 'auth', + message: 'Too many authentication attempts. Please try again later.', + skipSuccessfulRequests: true // Don't count successful logins +}); + +module.exports = { + publicRateLimiter, + formRateLimiter, + authRateLimiter, + createRateLimiter +}; diff --git a/src/middleware/response-sanitization.middleware.js b/src/middleware/response-sanitization.middleware.js new file mode 100644 index 00000000..0b73985a --- /dev/null +++ b/src/middleware/response-sanitization.middleware.js @@ -0,0 +1,115 @@ +/** + * Response Sanitization Middleware (inst_013, inst_045) + * Prevents information disclosure in error responses + * + * QUICK WIN: Hide stack traces and sensitive data in production + * NEVER expose: stack traces, internal paths, environment details + */ + +/** + * Sanitize error responses + * Production: Generic error messages only + * Development: More detailed errors for debugging + */ +function sanitizeErrorResponse(err, req, res, next) { + const isProduction = process.env.NODE_ENV === 'production'; + + // Log full error details internally (always) + console.error('[ERROR]', { + message: err.message, + stack: err.stack, + path: req.path, + method: req.method, + ip: req.ip, + user: req.user?.id || req.user?.userId, + timestamp: new Date().toISOString() + }); + + // Determine status code + const statusCode = err.statusCode || err.status || 500; + + // Generic error messages for common status codes + const genericErrors = { + 400: 'Bad Request', + 401: 'Unauthorized', + 403: 'Forbidden', + 404: 'Not Found', + 405: 'Method Not Allowed', + 413: 'Payload Too Large', + 429: 'Too Many Requests', + 500: 'Internal Server Error', + 502: 'Bad Gateway', + 503: 'Service Unavailable' + }; + + // Production: Generic error messages only + if (isProduction) { + return res.status(statusCode).json({ + error: genericErrors[statusCode] || 'Error', + message: err.message || 'An error occurred', + // NEVER include in production: stack, file paths, internal details + }); + } + + // Development: More detailed errors (but still sanitized) + res.status(statusCode).json({ + error: err.name || 'Error', + message: err.message, + statusCode, + // Stack trace only in development + stack: process.env.NODE_ENV === 'development' ? err.stack : undefined + }); +} + +/** + * Remove sensitive fields from objects + * Useful for sanitizing database results before sending to client + */ +function removeSensitiveFields(data, sensitiveFields = ['password', 'passwordHash', 'apiKey', 'secret', 'token']) { + if (Array.isArray(data)) { + return data.map(item => removeSensitiveFields(item, sensitiveFields)); + } + + if (typeof data === 'object' && data !== null) { + const sanitized = { ...data }; + + // Remove sensitive fields + for (const field of sensitiveFields) { + delete sanitized[field]; + } + + // Recursively sanitize nested objects + for (const key in sanitized) { + if (typeof sanitized[key] === 'object' && sanitized[key] !== null) { + sanitized[key] = removeSensitiveFields(sanitized[key], sensitiveFields); + } + } + + return sanitized; + } + + return data; +} + +/** + * Middleware to sanitize response data + * Apply before sending responses with user/database data + */ +function sanitizeResponseData(req, res, next) { + // Store original json method + const originalJson = res.json.bind(res); + + // Override json method to sanitize data + res.json = function(data) { + const sanitized = removeSensitiveFields(data); + return originalJson(sanitized); + }; + + next(); +} + +module.exports = { + sanitizeErrorResponse, + removeSensitiveFields, + sanitizeResponseData +}; diff --git a/src/middleware/security-headers.middleware.js b/src/middleware/security-headers.middleware.js new file mode 100644 index 00000000..7b7a0f22 --- /dev/null +++ b/src/middleware/security-headers.middleware.js @@ -0,0 +1,63 @@ +/** + * Security Headers Middleware (inst_044 - Quick Win Version) + * Implements comprehensive HTTP security headers + * + * QUICK WIN: Low effort, high value security improvement + * - Prevents XSS, clickjacking, MIME sniffing attacks + * - Enforces HTTPS, limits referrer leakage + * - Restricts dangerous browser features + */ + +/** + * Apply security headers to all HTTP responses + */ +function securityHeadersMiddleware(req, res, next) { + // Content Security Policy (enforces inst_008 at HTTP level) + // Allows Tailwind inline styles, blocks inline scripts + res.setHeader( + 'Content-Security-Policy', + [ + "default-src 'self'", + "script-src 'self'", + "style-src 'self' 'unsafe-inline'", // Tailwind requires inline styles + "img-src 'self' data: https:", + "font-src 'self' https://fonts.gstatic.com https://cdnjs.cloudflare.com", + "connect-src 'self'", + "frame-ancestors 'none'", + "base-uri 'self'", + "form-action 'self'", + "upgrade-insecure-requests", + "block-all-mixed-content" + ].join('; ') + ); + + // Prevent MIME type sniffing attacks + res.setHeader('X-Content-Type-Options', 'nosniff'); + + // Prevent clickjacking via iframes + res.setHeader('X-Frame-Options', 'DENY'); + + // Enable browser XSS filter (legacy browsers) + res.setHeader('X-XSS-Protection', '1; mode=block'); + + // Enforce HTTPS (HSTS) - only add if HTTPS is available + if (req.secure || req.get('x-forwarded-proto') === 'https') { + res.setHeader( + 'Strict-Transport-Security', + 'max-age=31536000; includeSubDomains' // 1 year + ); + } + + // Limit referrer information leakage + res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin'); + + // Restrict dangerous browser features + res.setHeader( + 'Permissions-Policy', + 'geolocation=(), microphone=(), camera=(), payment=()' + ); + + next(); +} + +module.exports = { securityHeadersMiddleware }; diff --git a/src/utils/security-logger.js b/src/utils/security-logger.js new file mode 100644 index 00000000..dd4f2a04 --- /dev/null +++ b/src/utils/security-logger.js @@ -0,0 +1,71 @@ +/** + * Security Event Logger (inst_046 - Quick Win Version) + * Centralized logging for all security events + * + * QUICK WIN: Simple file-based logging with JSON format + * Full version in Phase 5 will add ProtonMail/Signal alerts + */ + +const fs = require('fs').promises; +const path = require('path'); + +const SECURITY_LOG_PATH = '/var/log/tractatus/security-audit.log'; + +/** + * Log a security event to audit trail + * + * @param {Object} event - Security event details + * @param {string} event.type - Event type (e.g., 'rate_limit_violation') + * @param {string} event.sourceIp - Source IP address + * @param {string} event.userId - User ID (if authenticated) + * @param {string} event.endpoint - Request endpoint + * @param {string} event.userAgent - User agent string + * @param {Object} event.details - Additional event details + * @param {string} event.action - Action taken (e.g., 'blocked', 'logged') + * @param {string} event.severity - Severity level ('low', 'medium', 'high', 'critical') + */ +async function logSecurityEvent(event) { + const logEntry = { + timestamp: new Date().toISOString(), + event_type: event.type || 'unknown', + source_ip: event.sourceIp || 'unknown', + user_id: event.userId || 'anonymous', + endpoint: event.endpoint || 'unknown', + user_agent: event.userAgent || 'unknown', + violation_details: event.details || {}, + action_taken: event.action || 'logged', + severity: event.severity || 'medium' + }; + + const logLine = JSON.stringify(logEntry) + '\n'; + + try { + // Ensure log directory exists + const logDir = path.dirname(SECURITY_LOG_PATH); + await fs.mkdir(logDir, { recursive: true, mode: 0o750 }); + + // Append to log file + await fs.appendFile(SECURITY_LOG_PATH, logLine, { encoding: 'utf-8' }); + } catch (error) { + // Fallback to console if file logging fails + console.error('[SECURITY LOGGER ERROR]', error.message); + console.error('[SECURITY EVENT]', logEntry); + } +} + +/** + * Helper: Extract client IP from request (handles proxies) + */ +function getClientIp(req) { + return ( + req.ip || + req.headers['x-forwarded-for']?.split(',')[0]?.trim() || + req.connection.remoteAddress || + 'unknown' + ); +} + +module.exports = { + logSecurityEvent, + getClientIp +};