Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
54 lines
2 KiB
JavaScript
54 lines
2 KiB
JavaScript
// backend/middleware/corsConfig.js
|
|
// ADR-064 Phase 1 Task 4: Strict CORS in Production
|
|
// Extracted CORS origin handler for testability and security
|
|
|
|
import { logger } from '../utils/logger.js';
|
|
|
|
/**
|
|
* Parse CORS_ORIGINS environment variable into an array of allowed origins.
|
|
* Returns null if not configured.
|
|
* @returns {string[] | null}
|
|
*/
|
|
function parseAllowedOrigins() {
|
|
const raw = process.env.CORS_ORIGINS;
|
|
if (!raw) return null;
|
|
|
|
const origins = raw.split(',').map((origin) => origin.trim()).filter(Boolean);
|
|
return origins.length > 0 ? origins : null;
|
|
}
|
|
|
|
/**
|
|
* Create a CORS origin handler function compatible with the `cors` middleware.
|
|
*
|
|
* Behavior:
|
|
* - Production + no CORS_ORIGINS: reject ALL requests with error (security fail-safe)
|
|
* - Any env + no origin header (server-to-server, curl): allow
|
|
* - Dev + no CORS_ORIGINS: allow all origins (permissive for local development)
|
|
* - Whitelist configured: check origin against whitelist
|
|
*
|
|
* @returns {(origin: string | undefined, callback: Function) => void}
|
|
*/
|
|
export function createCorsOriginHandler() {
|
|
const allowedOrigins = parseAllowedOrigins();
|
|
const isProduction = process.env.NODE_ENV === 'production';
|
|
|
|
return (origin, callback) => {
|
|
// ADR-064: In production, CORS_ORIGINS must be set
|
|
if (isProduction && (!allowedOrigins || !allowedOrigins.length)) {
|
|
logger.error('CORS_ORIGINS not configured in production!');
|
|
return callback(new Error('CORS not configured'));
|
|
}
|
|
|
|
// Allow requests with no origin (server-to-server, curl) or null origin (UXP desktop plugins, file://)
|
|
if (!origin || origin === 'null') return callback(null, true);
|
|
|
|
// Dev: allow all if no origins configured
|
|
if (!allowedOrigins || !allowedOrigins.length) return callback(null, true);
|
|
|
|
// Check whitelist
|
|
if (allowedOrigins.includes(origin)) return callback(null, true);
|
|
|
|
logger.warn({ origin }, 'Blocked CORS origin');
|
|
return callback(new Error('Not allowed by CORS'));
|
|
};
|
|
}
|