From a6afc02091cdb1ee999f7f5438cac198bd85ceb8 Mon Sep 17 00:00:00 2001 From: Stephen Wade Date: Wed, 9 Apr 2025 19:04:46 -0400 Subject: [PATCH 1/3] ci: add failing test --- test/server/same-origin.test.js | 41 +++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 test/server/same-origin.test.js diff --git a/test/server/same-origin.test.js b/test/server/same-origin.test.js new file mode 100644 index 0000000000..ef4403d89a --- /dev/null +++ b/test/server/same-origin.test.js @@ -0,0 +1,41 @@ +"use strict"; + +const webpack = require("webpack"); +const Server = require("../../lib/Server"); +const config = require("../fixtures/simple-config/webpack.config"); + +describe("isSameOrigin", () => { + let server; + + beforeEach(async () => { + const compiler = webpack(config); + server = new Server({}, compiler); + }); + + it("should return true for localhost", () => { + const headers = { + host: "localhost:8080", + origin: "http://localhost:8080", + }; + + expect(server.isSameOrigin(headers)).toBe(true); + }); + + it("should return true for localhost subdomains", () => { + const headers = { + host: "localhost:8080", + origin: "http://subdomain.localhost:8080", + }; + + expect(server.isSameOrigin(headers)).toBe(true); + }); + + it("should return false for cross-origin requests", () => { + const headers = { + origin: "http://example.com", + host: "attacker.com", + }; + + expect(server.isSameOrigin(headers)).toBe(false); + }); +}); From e81b33040855a26a05ba49d6f1a9ac0eb291bda6 Mon Sep 17 00:00:00 2001 From: Stephen Wade Date: Wed, 9 Apr 2025 18:35:44 -0400 Subject: [PATCH 2/3] fix: always allow localhost --- lib/Server.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/Server.js b/lib/Server.js index 6e208128f6..263a4e7cfd 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -3121,6 +3121,10 @@ class Server { } // always allow localhost host, for convenience + if (value === "localhost" || value.endsWith(".localhost")) { + return true; + } + // allow if value is in allowedHosts if (Array.isArray(allowedHosts) && allowedHosts.length > 0) { for (let hostIdx = 0; hostIdx < allowedHosts.length; hostIdx++) { From 2ee695cddccc9056b7931e345d75c9a202d83fcc Mon Sep 17 00:00:00 2001 From: Stephen Wade Date: Wed, 9 Apr 2025 18:36:22 -0400 Subject: [PATCH 3/3] chore: remove unnecessary localhost check (covered by isHostAllowed) --- lib/Server.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/Server.js b/lib/Server.js index 263a4e7cfd..2aaf372a55 100644 --- a/lib/Server.js +++ b/lib/Server.js @@ -3214,14 +3214,10 @@ class Server { // an IPv6-address in URLs, // these are removed from the hostname in url.parse(), // so we have the pure IPv6-address in hostname. - // For convenience, always allow localhost (hostname === 'localhost') - // and its subdomains (hostname.endsWith(".localhost")). // allow hostname of listening address (hostname === this.options.host) const isValidHostname = ipaddr.IPv4.isValid(hostname) || ipaddr.IPv6.isValid(hostname) || - hostname === "localhost" || - hostname.endsWith(".localhost") || hostname === this.options.host; if (isValidHostname) {