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
- Install Helmet: Run
npm install helmet. Verify the existing cors package is present.
- 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).
- 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.
- 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).
- 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.
- 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.
- 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
- 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.
- 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.
- Make a request from a disallowed origin — verify
Access-Control-Allow-Origin is not present (browser would block the response).
- Set
CORS_ORIGINS=https://app.equipchain.io and verify that only that origin is allowed; http://localhost is rejected.
- Run
npm test and verify all security integration tests pass, including header assertions and CORS preflight tests.
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
corspackage (already in dependencies) needs proper configuration. A whitelist of allowed origins should be configurable viaCORS_ORIGINSenvironment variable (comma-separated list). The CORS middleware should handle preflight requests (OPTIONSmethod) 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
helmetpackage 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), andPermissions-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: Expressheader (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 (not0.0.0.0in production without explicit configuration). Remove any debug endpoints or development-only routes in production mode.Technical Context & Impact
helmet(^8.x),cors(already in package.json). No additional dependencies. All configuration is handled via environment variables.src/middleware/security.js. Applied globally insrc/index.jsbefore any route handlers. Environment-specific behavior viaNODE_ENVand custom env vars.Step-by-Step Implementation Guide
npm install helmet. Verify the existingcorspackage is present.src/middleware/security.jsexporting a function that returns an array of middleware. Configurehelmet()with:contentSecurityPolicy: false(API doesn't serve HTML, CSP is unnecessary overhead), or set a minimal policy. Enable all other default helmet protections. Configurecors()dynamically based onCORS_ORIGINSenv var (parse comma-separated list, support*for development).CORS_ORIGINSenv 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). Setcredentials: trueto allow JWT cookies/headers.app.disable('x-powered-by')insrc/index.js. Settrust proxyif behind a reverse proxy (for correct IP logging and rate limiting).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.NODE_ENV=production, the server refuses to start ifCORS_ORIGINSis not explicitly set (fail-safe). Add a startup validation check.tests/integration/security.test.jstesting: 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
GET /— verify response headers include:X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Strict-Transport-Security,Referrer-Policy. ConfirmX-Powered-Byis absent.http://localhost:5173) — verifyAccess-Control-Allow-Originmatches the origin andAccess-Control-Allow-Methodsincludes relevant methods.Access-Control-Allow-Originis not present (browser would block the response).CORS_ORIGINS=https://app.equipchain.ioand verify that only that origin is allowed;http://localhostis rejected.npm testand verify all security integration tests pass, including header assertions and CORS preflight tests.