-
-
Notifications
You must be signed in to change notification settings - Fork 0
Security Hardening: CORS and CSRF Protection #730
Copy link
Copy link
Open
Description
Issue Summary
CodeQL security scanning has flagged the Express application for serving cookies without CSRF protection. Additionally, the current CORS configuration is overly permissive and poses security risks.
Current Security State
Authentication Model
- Uses CouchDB session tokens for authentication
- Tokens stored as browser cookies
- Cross-origin requests between
example.com↔express.example.com
Current CORS Configuration
app.use(cors({
credentials: true,
origin: true, // ⚠️ SECURITY RISK: Allows ANY origin
}));Current Cookie Handling
app.use(cookieParser()); // ⚠️ No CSRF protectionSecurity Vulnerabilities
- CSRF Attacks: No protection against Cross-Site Request Forgery
- Overly Permissive CORS:
origin: trueallows malicious sites to make authenticated requests - Missing Security Headers: No helmet or CSP protection
Recommended Solutions
Phase 1: Immediate Fixes (Low Risk)
1. Secure CORS Configuration
app.use(cors({
credentials: true,
origin: [
/^https?:\/\/[^.]*\.example\.com$/, // Any subdomain of example.com
'http://localhost:3000', // Development
'http://localhost:5173', // Vite dev server
],
methods: ['GET', 'POST', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization', 'Cookie']
}));2. Environment-Based Origins
// .env configuration
ALLOWED_ORIGINS=https://example.com,https://app.example.com,https://admin.example.com
// Code
origin: process.env.ALLOWED_ORIGINS?.split(',') || defaultOrigins3. Basic Security Headers
import helmet from 'helmet';
app.use(helmet({
crossOriginEmbedderPolicy: false, // May interfere with CouchDB
contentSecurityPolicy: false, // Enable later when ready
}));Phase 2: CSRF Protection (Medium Risk)
Option A: Full CSRF Protection
import csrf from 'csurf';
const csrfProtection = csrf({
cookie: {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict'
}
});
app.use(csrfProtection);
// Provide token endpoint
app.get('/csrf-token', (req, res) => {
res.json({ csrfToken: req.csrfToken() });
});Option B: SameSite Cookie Protection
// Configure CouchDB session cookies with SameSite
app.use(session({
cookie: {
sameSite: 'lax', // or 'strict' for better security
secure: process.env.NODE_ENV === 'production',
domain: '.example.com'
}
}));Phase 3: Advanced Security (Future)
- Content Security Policy: Implement proper CSP headers
- Rate Limiting: Add request rate limiting
- Input Validation: Comprehensive request validation
- Security Audit: Third-party security review
Implementation Priority
High Priority (Address Soon)
- Fix CORS origin configuration
- Add environment-based origin allowlist
- Add basic helmet security headers
Medium Priority (Next Sprint)
- Implement CSRF protection
- Configure secure cookie options
- Add security testing to CI/CD
Low Priority (Future Improvements)
- Implement full CSP policy
- Add comprehensive rate limiting
- Security audit and penetration testing
Testing Requirements
Security Testing
- Verify CORS policy blocks unauthorized origins
- Test CSRF protection blocks forged requests
- Validate cookie security settings
- Cross-browser compatibility testing
Functionality Testing
- Ensure legitimate cross-origin requests still work
- Verify authentication flow remains intact
- Test development environment compatibility
Dependencies
helmet- Security headers middlewarecsurf- CSRF protection (if implementing Option A)- Environment configuration updates
Migration Notes
- Backwards Compatibility: Changes may require frontend updates to handle CSRF tokens
- Development Impact: Localhost origins need explicit allowlisting
- Production Deployment: Coordinate with DevOps for environment variables
References
Acceptance Criteria
- CodeQL security warnings resolved
- CORS policy restricts origins to known domains
- CSRF protection implemented (Phase 2)
- Security headers properly configured
- All existing functionality preserved
- Documentation updated with security practices
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels