Skip to content

[Security] Add CORS, Helmet, and Other Security Middleware for Production Hardening #24

Description

@KarenZita01

Description

The EquipChain API needs production-grade security hardening to protect against common web vulnerabilities. While basic middleware was introduced in Issue #6, additional security measures are required before the API can be exposed to the public internet. This issue implements CORS configuration, Helmet security headers, and other security best practices.

CORS (Cross-Origin Resource Sharing): The existing cors package (already in dependencies) needs proper configuration. A whitelist of allowed origins should be configurable via CORS_ORIGINS environment variable (comma-separated list). The CORS middleware should handle preflight requests (OPTIONS method) correctly, support credentials (Authorization header for JWT), and expose appropriate headers. In development, allow localhost origins; in production, restrict to the domain(s) serving the frontend.

Helmet: The helmet package sets various HTTP security headers including: Content-Security-Policy (restrict script/style sources), X-Content-Type-Options (nosniff), X-Frame-Options (DENY — prevent clickjacking), X-XSS-Protection,Strict-Transport-Security (HSTS — force HTTPS), Referrer-Policy (no-referrer), and Permissions-Policy (restrict browser features). The configuration should be tuned for an API (not serving HTML), so CSP can be restrictive.

Additional Hardening: Disable the X-Powered-By: Express header (information disclosure). Configure HTTP parameter pollution protection. Add request size limits (body parser limit of 1MB, aligned with Issue #30). Ensure the server listens only on the configured host (not 0.0.0.0 in production without explicit configuration). Remove any debug endpoints or development-only routes in production mode.

Technical Context & Impact

  • Dependencies: helmet (^8.x), cors (already in package.json). No additional dependencies. All configuration is handled via environment variables.
  • Architecture: Security middleware configuration in src/middleware/security.js. Applied globally in src/index.js before any route handlers. Environment-specific behavior via NODE_ENV and custom env vars.
  • Impact: Critical for production deployment. Without these headers and protections, the API is vulnerable to common attacks: clickjacking, MIME-type sniffing, cross-origin data theft, and information disclosure. Many security audits and compliance frameworks require these headers.

Step-by-Step Implementation Guide

  1. Install Helmet: Run npm install helmet. Verify the existing cors package is present.
  2. Create Security Configuration: Write src/middleware/security.js exporting a function that returns an array of middleware. Configure helmet() with: contentSecurityPolicy: false (API doesn't serve HTML, CSP is unnecessary overhead), or set a minimal policy. Enable all other default helmet protections. Configure cors() dynamically based on CORS_ORIGINS env var (parse comma-separated list, support * for development).
  3. Configure CORS Dynamically: In the security module, read CORS_ORIGINS env var. If set, parse as comma-separated origins. If not set, default to * in development and block all origins in production (must be explicitly configured). Set credentials: true to allow JWT cookies/headers.
  4. Disable X-Powered-By: Add app.disable('x-powered-by') in src/index.js. Set trust proxy if behind a reverse proxy (for correct IP logging and rate limiting).
  5. Apply Middleware: In src/index.js, apply security middleware (helmet, cors) before the logger middleware. Verify the ordering: security headers should be set as early as possible in the response lifecycle.
  6. Environment-Specific Behavior: Ensure that in NODE_ENV=production, the server refuses to start if CORS_ORIGINS is not explicitly set (fail-safe). Add a startup validation check.
  7. Write Tests: Create tests/integration/security.test.js testing: CORS headers in OPTIONS preflight, security headers in responses (using supertest to check response headers), CORS origin restriction (test allowed and disallowed origins).

Verification & Testing Steps

  1. Start the server and make a request to GET / — verify response headers include: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Strict-Transport-Security, Referrer-Policy. Confirm X-Powered-By is absent.
  2. Make an OPTIONS request from an allowed origin (e.g., http://localhost:5173) — verify Access-Control-Allow-Origin matches the origin and Access-Control-Allow-Methods includes relevant methods.
  3. Make a request from a disallowed origin — verify Access-Control-Allow-Origin is not present (browser would block the response).
  4. Set CORS_ORIGINS=https://app.equipchain.io and verify that only that origin is allowed; http://localhost is rejected.
  5. Run npm test and verify all security integration tests pass, including header assertions and CORS preflight tests.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions