From 24c08b9cd93088f2c09f6a0e377c41207f10f5d2 Mon Sep 17 00:00:00 2001 From: jesse-merhi <79823012+jesse-merhi@users.noreply.github.com> Date: Mon, 4 May 2026 02:30:40 +1000 Subject: [PATCH] fix(infra): redact APNs proxy URL params --- CHANGELOG.md | 2 +- src/infra/net/http-connect-tunnel.test.ts | 28 +++++++++++++++++++++++ src/infra/net/http-connect-tunnel.ts | 4 +--- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e21be706ee..544049021f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -278,7 +278,7 @@ Docs: https://docs.openclaw.ai - Slack: collapse routine Socket Mode pong-timeout reconnects into one OpenClaw reconnect line and suppress the duplicate Slack SDK pong warning. - Gateway/diagnostics: abort-drain embedded runs after an extended no-progress stall so a single dead session no longer leaves queued Discord/channel turns blocked behind repeated `recovery=none` liveness warnings. - Plugins/ClawHub: accept the live artifact resolver `kind`/`sha256` field names alongside the typed `artifactKind`/`artifactSha256` form so `clawhub:` installs of npm-pack and legacy ZIP packages no longer miss downloadable artifacts. Thanks @romneyda. -- Direct APNs: route direct HTTP/2 delivery through the active managed proxy so push requests honor configured egress controls, and let `openclaw proxy validate --apns-reachable` prove APNs is reachable through the proxy before deployment. (#74905) Thanks @jesse-merhi. +- Direct APNs: route direct HTTP/2 delivery through the active managed proxy with redacted proxy diagnostics, so push requests honor configured egress controls and `openclaw proxy validate --apns-reachable` can prove APNs is reachable through the proxy before deployment. (#74905) Thanks @jesse-merhi. - Control UI/Sessions: avoid full `sessions.list` reloads for chat-turn `sessions.changed` payloads, so large session stores no longer add multi-second delays while chat responses are being delivered. (#76676) Thanks @VACInc. - Gateway/watch: run `doctor --fix --non-interactive` once and retry when the dev Gateway child exits during startup, so stale local plugin install/config state does not leave the tmux watch session disappearing without a repair attempt. - Doctor/Telegram: warn when selected Telegram quote replies can suppress `streaming.preview.toolProgress`, and document the `replyToMode` trade-off without changing runtime delivery. Fixes #73487. Thanks @GodsBoy. diff --git a/src/infra/net/http-connect-tunnel.test.ts b/src/infra/net/http-connect-tunnel.test.ts index 048d9912d77..46806e57ff5 100644 --- a/src/infra/net/http-connect-tunnel.test.ts +++ b/src/infra/net/http-connect-tunnel.test.ts @@ -184,6 +184,34 @@ describe("openHttpConnectTunnel", () => { expect(proxySocket.destroyed).toBe(true); }); + it("redacts proxy URL query and fragment values when CONNECT fails", async () => { + const proxySocket = new FakeSocket("HTTP/1.1 407 Proxy Authentication Required\r\n\r\n"); + setNextNetSocket(proxySocket); + const { openHttpConnectTunnel } = await import("./http-connect-tunnel.js"); + + let caught: unknown; + try { + await openHttpConnectTunnel({ + proxyUrl: "http://user:secret@proxy.example:8080/?token=hidden#fragment", + targetHost: "api.push.apple.com", + targetPort: 443, + }); + } catch (err) { + caught = err; + } + + expect(caught).toBeInstanceOf(Error); + if (!(caught instanceof Error)) { + throw new Error("expected CONNECT failure"); + } + expect(caught.message).toBe( + "Proxy CONNECT failed via http://proxy.example:8080: HTTP/1.1 407 Proxy Authentication Required", + ); + expect(caught.message).not.toContain("secret"); + expect(caught.message).not.toContain("hidden"); + expect(caught.message).not.toContain("fragment"); + }); + it("rejects malformed proxy credentials through the normal cleanup path", async () => { const proxySocket = new FakeSocket(); setNextNetSocket(proxySocket); diff --git a/src/infra/net/http-connect-tunnel.ts b/src/infra/net/http-connect-tunnel.ts index e2e3f229fcb..c2d70560187 100644 --- a/src/infra/net/http-connect-tunnel.ts +++ b/src/infra/net/http-connect-tunnel.ts @@ -13,9 +13,7 @@ const MAX_CONNECT_RESPONSE_HEADER_BYTES = 16 * 1024; function redactProxyUrl(proxyUrl: string): string { try { const parsed = new URL(proxyUrl); - parsed.username = ""; - parsed.password = ""; - return parsed.toString().replace(/\/$/, ""); + return parsed.origin; } catch { return ""; }