From 5e3e4b030801257b7e8f885580b8638827d6ed28 Mon Sep 17 00:00:00 2001 From: Filbert Alfredo Saputro <188670416+filbertsaputro@users.noreply.github.com> Date: Tue, 26 May 2026 10:15:32 +0700 Subject: [PATCH] fix(@angular-devkit/build-angular): remove unconditional CORS wildcard from webpack dev-server The legacy webpack-based dev-server unconditionally sets `Access-Control-Allow-Origin: *` on every response. This overrides webpack-dev-server v5's cross-origin protections and leaves the local dev server readable by any web page the developer visits in the same browser session. The modern `@angular/build` dev-server (Vite-based) already does not set this header by default; its test contract explicitly asserts that `Access-Control-Allow-Origin` is absent unless the user configures it. This change brings the legacy webpack dev-server in line with that contract. Users who relied on the previous behavior can opt back in explicitly via the existing `headers` option in `angular.json`: "serve": { "options": { "headers": { "Access-Control-Allow-Origin": "*" } } } --- .../dev-server/tests/options/headers_spec.ts | 65 +++++++++++++++++++ .../src/tools/webpack/configs/dev-server.ts | 5 +- 2 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/headers_spec.ts diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/headers_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/headers_spec.ts new file mode 100644 index 000000000000..d87def49b30e --- /dev/null +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/options/headers_spec.ts @@ -0,0 +1,65 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { executeDevServer } from '../../index'; +import { executeOnceAndFetch } from '../execute-fetch'; +import { describeServeBuilder } from '../jasmine-helpers'; +import { BASE_OPTIONS, DEV_SERVER_BUILDER_INFO } from '../setup'; + +describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => { + describe('option: "headers"', () => { + beforeEach(async () => { + setupTarget(harness, { + styles: ['src/styles.css'], + }); + + // Application code is not needed for these tests + await harness.writeFile('src/main.ts', ''); + await harness.writeFile('src/styles.css', ''); + }); + + it('index response headers should include configured header', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + headers: { + 'x-custom': 'foo', + }, + }); + + const { result, response } = await executeOnceAndFetch(harness, '/'); + + expect(result?.success).toBeTrue(); + expect(await response?.headers.get('x-custom')).toBe('foo'); + }); + + it('should include configured Access-Control-Allow-Origin header', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + headers: { + 'Access-Control-Allow-Origin': 'http://example.com', + }, + }); + + const { result, response } = await executeOnceAndFetch(harness, '/main.js'); + + expect(result?.success).toBeTrue(); + expect(await response?.headers.get('access-control-allow-origin')).toBe('http://example.com'); + }); + + it('should not include Access-Control-Allow-Origin header by default', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, '/main.js'); + + expect(result?.success).toBeTrue(); + expect(await response?.headers.has('access-control-allow-origin')).toBeFalse(); + }); + }); +}); diff --git a/packages/angular_devkit/build_angular/src/tools/webpack/configs/dev-server.ts b/packages/angular_devkit/build_angular/src/tools/webpack/configs/dev-server.ts index 5ba21e328ec3..99b63b4f4c37 100644 --- a/packages/angular_devkit/build_angular/src/tools/webpack/configs/dev-server.ts +++ b/packages/angular_devkit/build_angular/src/tools/webpack/configs/dev-server.ts @@ -60,10 +60,7 @@ export async function getDevServerConfig( devServer: { host, port, - headers: { - 'Access-Control-Allow-Origin': '*', - ...headers, - }, + headers, historyApiFallback: !!index && { index: posix.join(servePath, getIndexOutputFile(index)), disableDotRule: true,