Skip to content

Security Hardening: CORS and CSRF Protection #730

@NiloCK

Description

@NiloCK

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.comexpress.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 protection

Security Vulnerabilities

  1. CSRF Attacks: No protection against Cross-Site Request Forgery
  2. Overly Permissive CORS: origin: true allows malicious sites to make authenticated requests
  3. 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(',') || defaultOrigins

3. 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)

  1. Content Security Policy: Implement proper CSP headers
  2. Rate Limiting: Add request rate limiting
  3. Input Validation: Comprehensive request validation
  4. 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 middleware
  • csurf - CSRF protection (if implementing Option A)
  • Environment configuration updates

Migration Notes

  1. Backwards Compatibility: Changes may require frontend updates to handle CSRF tokens
  2. Development Impact: Localhost origins need explicit allowlisting
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions