Skip to content

Commit 5c9378b

Browse files
authored
Merge commit from fork
BREAKING CHANGE: cross origin requests are not allowed unless allowed by `Access-Control-Allow-Origin` header
1 parent d2575ad commit 5c9378b

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

lib/Server.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1970,6 +1970,32 @@ class Server {
19701970
},
19711971
});
19721972

1973+
// Register setup cross origin request check for security
1974+
middlewares.push({
1975+
name: "cross-origin-header-check",
1976+
/**
1977+
* @param {Request} req
1978+
* @param {Response} res
1979+
* @param {NextFunction} next
1980+
* @returns {void}
1981+
*/
1982+
middleware: (req, res, next) => {
1983+
const headers =
1984+
/** @type {{ [key: string]: string | undefined }} */
1985+
(req.headers);
1986+
if (
1987+
headers["sec-fetch-mode"] === "no-cors" &&
1988+
headers["sec-fetch-site"] === "cross-site"
1989+
) {
1990+
res.statusCode = 403;
1991+
res.end("Cross-Origin request blocked");
1992+
return;
1993+
}
1994+
1995+
next();
1996+
},
1997+
});
1998+
19731999
const isHTTP2 =
19742000
/** @type {ServerConfiguration<A, S>} */ (this.options.server).type ===
19752001
"http2";

test/e2e/cross-origin-request.test.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
"use strict";
2+
3+
const webpack = require("webpack");
4+
const Server = require("../../lib/Server");
5+
const config = require("../fixtures/client-config/webpack.config");
6+
const runBrowser = require("../helpers/run-browser");
7+
const [port1, port2] = require("../ports-map")["cross-origin-request"];
8+
9+
describe("cross-origin requests", () => {
10+
const devServerPort = port1;
11+
const htmlServerPort = port2;
12+
const htmlServerHost = "127.0.0.1";
13+
14+
it("should return 403 for cross-origin no-cors non-module script tag requests", async () => {
15+
const compiler = webpack(config);
16+
const devServerOptions = {
17+
port: devServerPort,
18+
allowedHosts: "auto",
19+
};
20+
const server = new Server(devServerOptions, compiler);
21+
22+
await server.start();
23+
24+
// Start a separate server for serving the HTML file
25+
const http = require("http");
26+
const htmlServer = http.createServer((req, res) => {
27+
res.writeHead(200, { "Content-Type": "text/html" });
28+
res.end(`
29+
<html>
30+
<head>
31+
<script src="http://localhost:${devServerPort}/main.js"></script>
32+
</head>
33+
<body></body>
34+
</html>
35+
`);
36+
});
37+
htmlServer.listen(htmlServerPort, htmlServerHost);
38+
39+
const { page, browser } = await runBrowser();
40+
try {
41+
const pageErrors = [];
42+
43+
page.on("pageerror", (error) => {
44+
pageErrors.push(error);
45+
});
46+
47+
const scriptTagRequest = page.waitForResponse(
48+
`http://localhost:${devServerPort}/main.js`,
49+
);
50+
51+
await page.goto(`http://${htmlServerHost}:${htmlServerPort}`);
52+
53+
const response = await scriptTagRequest;
54+
55+
expect(response.status()).toBe(403);
56+
} catch (error) {
57+
throw error;
58+
} finally {
59+
await browser.close();
60+
await server.stop();
61+
htmlServer.close();
62+
}
63+
});
64+
65+
it("should return 200 for cross-origin cors non-module script tag requests", async () => {
66+
const compiler = webpack(config);
67+
const devServerOptions = {
68+
port: devServerPort,
69+
allowedHosts: "auto",
70+
headers: {
71+
"Access-Control-Allow-Origin": "*",
72+
},
73+
};
74+
const server = new Server(devServerOptions, compiler);
75+
76+
await server.start();
77+
78+
// Start a separate server for serving the HTML file
79+
const http = require("http");
80+
const htmlServer = http.createServer((req, res) => {
81+
res.writeHead(200, { "Content-Type": "text/html" });
82+
res.end(`
83+
<html>
84+
<head>
85+
<script src="http://localhost:${devServerPort}/main.js" crossorigin></script>
86+
</head>
87+
<body></body>
88+
</html>
89+
`);
90+
});
91+
htmlServer.listen(htmlServerPort, htmlServerHost);
92+
93+
const { page, browser } = await runBrowser();
94+
try {
95+
const pageErrors = [];
96+
97+
page.on("pageerror", (error) => {
98+
pageErrors.push(error);
99+
});
100+
101+
const scriptTagRequest = page.waitForResponse(
102+
`http://localhost:${devServerPort}/main.js`,
103+
);
104+
105+
await page.goto(`http://${htmlServerHost}:${htmlServerPort}`);
106+
107+
const response = await scriptTagRequest;
108+
109+
expect(response.status()).toBe(200);
110+
} catch (error) {
111+
throw error;
112+
} finally {
113+
await browser.close();
114+
await server.stop();
115+
htmlServer.close();
116+
}
117+
});
118+
});

test/ports-map.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ const listOfTests = {
8181
"setup-middlewares-option": 1,
8282
"options-request-response": 2,
8383
app: 1,
84+
"cross-origin-request": 2,
8485
};
8586

8687
let startPort = 8089;

0 commit comments

Comments
 (0)