From 362754a6333eaaab1a90e718d9d1827fa21bf2bc Mon Sep 17 00:00:00 2001 From: Dotta Date: Sun, 9 Aug 2026 16:19:49 +0000 Subject: [PATCH] fix(runner): pin Phase 7I proxy authority Co-Authored-By: Paperclip --- .../scripts/run-phase7i-demo.sh | 1 + .../src/phase7/phase7i-loopback-proxy.ts | 29 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/packages/paperclip-runner/scripts/run-phase7i-demo.sh b/packages/paperclip-runner/scripts/run-phase7i-demo.sh index fb9a025d335..d4f75b79ae9 100755 --- a/packages/paperclip-runner/scripts/run-phase7i-demo.sh +++ b/packages/paperclip-runner/scripts/run-phase7i-demo.sh @@ -69,6 +69,7 @@ fi env -i \ PATH=/usr/local/bin:/usr/bin:/bin \ NODE_ENV=production \ + PHASE7I_PUBLIC_ORIGIN="$PHASE7I_PUBLIC_ORIGIN" \ PHASE7I_PROXY_PORT="$PHASE7I_PROXY_PORT" \ PHASE7I_SOCKET_PATH="$socket_path" \ node \ diff --git a/packages/paperclip-runner/src/phase7/phase7i-loopback-proxy.ts b/packages/paperclip-runner/src/phase7/phase7i-loopback-proxy.ts index 6facf02a81f..9e2281897ca 100644 --- a/packages/paperclip-runner/src/phase7/phase7i-loopback-proxy.ts +++ b/packages/paperclip-runner/src/phase7/phase7i-loopback-proxy.ts @@ -16,22 +16,20 @@ const FORWARDED_HEADERS = new Set([ "tailscale-user-name", "user-agent", "x-forwarded-for", - "x-forwarded-host", - "x-forwarded-proto", ]); -function selectedHeaders(headers: IncomingHttpHeaders): Record { +function selectedHeaders( + headers: IncomingHttpHeaders, + publicHost: string, +): Record { const selected: Record = {}; for (const [name, value] of Object.entries(headers)) { if (!FORWARDED_HEADERS.has(name) || value === undefined) continue; selected[name] = value; } - selected["x-forwarded-proto"] = Array.isArray(headers["x-forwarded-proto"]) - ? headers["x-forwarded-proto"][0] ?? "https" - : headers["x-forwarded-proto"] ?? "https"; - selected["x-forwarded-host"] = Array.isArray(headers["x-forwarded-host"]) - ? headers["x-forwarded-host"][0] ?? String(headers.host ?? "") - : headers["x-forwarded-host"] ?? String(headers.host ?? ""); + selected.host = publicHost; + selected["x-forwarded-proto"] = "https"; + selected["x-forwarded-host"] = publicHost; selected["x-phase7i-proxy"] = "v1"; return selected; } @@ -39,8 +37,15 @@ function selectedHeaders(headers: IncomingHttpHeaders): Record 65_535) { - throw new Error("PHASE7I_SOCKET_PATH and a valid PHASE7I_PROXY_PORT are required"); + const publicOrigin = new URL(process.env.PHASE7I_PUBLIC_ORIGIN ?? ""); + if ( + !socketPath + || !Number.isInteger(port) + || port < 1 + || port > 65_535 + || publicOrigin.protocol !== "https:" + ) { + throw new Error("PHASE7I_SOCKET_PATH, PHASE7I_PUBLIC_ORIGIN, and a valid PHASE7I_PROXY_PORT are required"); } const server = createServer((req, res) => { @@ -55,7 +60,7 @@ function main(): void { socketPath, method: req.method, path: req.url, - headers: selectedHeaders(req.headers), + headers: selectedHeaders(req.headers, publicOrigin.host), timeout: 35_000, }, (upstreamResponse) => { res.writeHead(upstreamResponse.statusCode ?? 502, upstreamResponse.headers);