Skip to content

Commit 7c8c962

Browse files
committed
fix(node): validate host header
invalid host header like localhost:3001/abchehe? can cause inconsistent pathname in slowpath of FastURL
1 parent b6738bd commit 7c8c962

File tree

1 file changed

+17
-4
lines changed

1 file changed

+17
-4
lines changed

src/adapters/_node/url.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import type { NodeServerRequest } from "../../types.ts";
22
import { FastURL } from "../../_url.ts";
33

4+
/**
5+
* Validates an HTTP Host header value (domain, IPv4, or bracketed IPv6) with optional port.
6+
* Intended for preliminary filtering invalid values like "localhost:3000/foobar?"
7+
*/
8+
export const HOST_RE: RegExp =
9+
/^(\[(?:[A-Fa-f0-9:.]+)\]|(?:[A-Za-z0-9_-]+\.)*[A-Za-z0-9_-]+|(?:\d{1,3}\.){3}\d{1,3})(:\d{1,5})?$/;
10+
411
export class NodeRequestURL extends FastURL {
512
#req: NodeServerRequest;
613

@@ -11,10 +18,16 @@ export class NodeRequestURL extends FastURL {
1118
const pathname = qIndex === -1 ? path : path?.slice(0, qIndex) || "/";
1219
const search = qIndex === -1 ? "" : path?.slice(qIndex) || "";
1320

14-
const host =
15-
req.headers.host ||
16-
(req.headers[":authority"] as string) ||
17-
`${req.socket.localFamily === "IPv6" ? "[" + req.socket.localAddress + "]" : req.socket.localAddress}:${req.socket?.localPort || "80"}`;
21+
let host = req.headers.host || (req.headers[":authority"] as string);
22+
if (host) {
23+
if (!HOST_RE.test(host)) {
24+
throw new TypeError(`Invalid host header: ${host}`);
25+
}
26+
} else if (req.socket) {
27+
host = `${req.socket.localFamily === "IPv6" ? "[" + req.socket.localAddress + "]" : req.socket.localAddress}:${req.socket?.localPort || "80"}`;
28+
} else {
29+
host = "localhost";
30+
}
1831

1932
const protocol =
2033
(req.socket as any)?.encrypted ||

0 commit comments

Comments
 (0)