tractatus/docs/plans/QUICK_WINS_IMPLEMENTATION.md
TheFlow ac2db33732 fix(submissions): restructure Economist package and fix article display
- Create Economist SubmissionTracking package correctly:
  * mainArticle = full blog post content
  * coverLetter = 216-word SIR— letter
  * Links to blog post via blogPostId
- Archive 'Letter to The Economist' from blog posts (it's the cover letter)
- Fix date display on article cards (use published_at)
- Target publication already displaying via blue badge

Database changes:
- Make blogPostId optional in SubmissionTracking model
- Economist package ID: 68fa85ae49d4900e7f2ecd83
- Le Monde package ID: 68fa2abd2e6acd5691932150

Next: Enhanced modal with tabs, validation, export

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-24 08:47:42 +13:00

427 lines
11 KiB
Markdown

# 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":"<script>alert(1)</script>","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