diff --git a/lib/config.ts b/lib/config.ts index 4d00167..f2ca6fc 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -67,8 +67,11 @@ function loadOverrides(path: string): Record { } function intOr(value: string | undefined, fallback: number): number { - const parsed = Number.parseInt(value ?? "", 10); - return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback; + const text = value?.trim() ?? ""; + if (!/^\d+$/.test(text)) return fallback; + + const parsed = Number(text); + return Number.isSafeInteger(parsed) && parsed > 0 && parsed <= 65_535 ? parsed : fallback; } function truthy(value: string | undefined): boolean { diff --git a/tests/config.test.ts b/tests/config.test.ts new file mode 100644 index 0000000..4540cca --- /dev/null +++ b/tests/config.test.ts @@ -0,0 +1,29 @@ +import { describe, test } from "node:test"; +import assert from "node:assert/strict"; +import { loadConfig } from "../lib/config.ts"; + +describe("config", () => { + test("rejects malformed and out-of-range port values", () => { + for (const value of ["443junk", "1.5", "0", "-1", "65536", "Infinity"]) { + const config = loadConfig({ + MOSHPIT_PROXY_DIR: "unused", + MOSHPIT_PROXY_PORT: value, + MOSHPIT_GATEWAY_PORT: value, + }); + + assert.equal(config.listenPort, 8443, `listen port should reject ${value}`); + assert.equal(config.gatewayPort, 443, `gateway port should reject ${value}`); + } + }); + + test("accepts trimmed ports across the full valid range", () => { + const config = loadConfig({ + MOSHPIT_PROXY_DIR: "unused", + MOSHPIT_PROXY_PORT: " 1 ", + MOSHPIT_GATEWAY_PORT: "65535", + }); + + assert.equal(config.listenPort, 1); + assert.equal(config.gatewayPort, 65_535); + }); +});