diff --git a/src/http/handlers/cors/cors-handler.spec.ts b/src/http/handlers/cors/cors-handler.spec.ts index b84754a..741fcc4 100644 --- a/src/http/handlers/cors/cors-handler.spec.ts +++ b/src/http/handlers/cors/cors-handler.spec.ts @@ -378,12 +378,13 @@ describe('CorsHandler', () => { expect(sendSpy).toHaveBeenCalled(); }); - it('should reject preflight with 403 when requested headers are not allowed', async () => { + it('should reject preflight with 403 when ANY requested header is not allowed', async () => { const handler = new CorsHandler({ allowedHeaders: ['Content-Type', 'Authorization'], }); setupRequest('https://example.com', 'OPTIONS'); - mockReq.headers!['access-control-request-headers'] = 'X-Custom-Header, X-Forbidden'; + // Content-Type is allowed, but X-Forbidden is not + mockReq.headers!['access-control-request-headers'] = 'Content-Type, X-Forbidden'; const handled = await handleCors(handler); diff --git a/src/http/handlers/cors/cors-handler.ts b/src/http/handlers/cors/cors-handler.ts index 1a6a8c9..3e1d5e0 100644 --- a/src/http/handlers/cors/cors-handler.ts +++ b/src/http/handlers/cors/cors-handler.ts @@ -162,14 +162,14 @@ export class CorsHandler { // User explicitly configured allowedHeaders - validate requested headers const requested = requestedHeaders.split(',').map((h) => h.trim().toLowerCase()); const allowed = this.options.allowedHeaders.map((h) => h.toLowerCase()); - const validated = requested.filter((h) => allowed.includes(h)); + const isValid = requested.every((h) => allowed.includes(h)); - if (validated.length === 0) { - // Requested headers not allowed - reject preflight + if (!isValid) { + // One or more requested headers are not allowed - reject preflight res.status(403).send(); return true; } - allowedHeadersToSend = validated.join(', '); + allowedHeadersToSend = requested.join(', '); } else if (requestedHeaders) { // No allowedHeaders configured or empty array - echo back (permissive mode) allowedHeadersToSend = requestedHeaders;