Skip to content

Commit 960815c

Browse files
authored
host parse (#10553)
1 parent 4a1d361 commit 960815c

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

.changeset/old-plums-perform.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@remix-run/express": patch
3+
---
4+
5+
Better validation of `x-forwarded-host` header to preent potential security issues.

packages/remix-express/__tests__/server-test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,28 @@ describe("express createRemixRequest", () => {
219219
);
220220
expect(remixRequest.headers.get("host")).toBe("localhost:3000");
221221
});
222+
223+
it("validates parsed port", async () => {
224+
let expressRequest = createRequest({
225+
url: "/foo/bar",
226+
method: "GET",
227+
protocol: "http",
228+
hostname: "localhost",
229+
headers: {
230+
"Cache-Control": "max-age=300, s-maxage=3600",
231+
Host: "localhost:3000",
232+
"x-forwarded-host": ":/spoofed",
233+
},
234+
});
235+
let expressResponse = createResponse();
236+
237+
let remixRequest = createRemixRequest(expressRequest, expressResponse);
238+
239+
expect(remixRequest.method).toBe("GET");
240+
expect(remixRequest.headers.get("cache-control")).toBe(
241+
"max-age=300, s-maxage=3600"
242+
);
243+
expect(remixRequest.headers.get("host")).toBe("localhost:3000");
244+
expect(remixRequest.url).toBe("http://localhost:3000/foo/bar");
245+
});
222246
});

packages/remix-express/server.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,15 @@ export function createRemixRequest(
8989
): Request {
9090
// req.hostname doesn't include port information so grab that from
9191
// `X-Forwarded-Host` or `Host`
92-
let [, hostnamePort] = req.get("X-Forwarded-Host")?.split(":") ?? [];
93-
let [, hostPort] = req.get("host")?.split(":") ?? [];
94-
let port = hostnamePort || hostPort;
92+
let [, hostnamePortStr] = req.get("X-Forwarded-Host")?.split(":") ?? [];
93+
let [, hostPortStr] = req.get("host")?.split(":") ?? [];
94+
let hostnamePort = Number.parseInt(hostnamePortStr, 10);
95+
let hostPort = Number.parseInt(hostPortStr, 10);
96+
let port = Number.isSafeInteger(hostnamePort)
97+
? hostnamePort
98+
: Number.isSafeInteger(hostPort)
99+
? hostPort
100+
: "";
95101
// Use req.hostname here as it respects the "trust proxy" setting
96102
let resolvedHost = `${req.hostname}${port ? `:${port}` : ""}`;
97103
// Use `req.originalUrl` so Remix is aware of the full path

0 commit comments

Comments
 (0)