diff --git a/CHANGELOG.md b/CHANGELOG.md index 67ae27f4a94..03cee239520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -133,6 +133,7 @@ Docs: https://docs.openclaw.ai - Agents/prompt composition: append bootstrap truncation warnings to the current-turn prompt and add regression coverage for stable system-prompt cache invariants. (#49237) Thanks @scoootscooob. - Gateway/auth: add regression coverage that keeps device-less trusted-proxy Control UI sessions off privileged pairing approval RPCs. Thanks @vincentkoc. - Plugins/runtime-api: pin extension runtime-api export seams with explicit guardrail coverage so future surface creep becomes a deliberate diff. Thanks @vincentkoc. +- Telegram/security: add regression coverage proving pinned fallback host overrides stay bound to Telegram and delegate non-matching hostnames back to the original lookup path. Thanks @vincentkoc. ### Breaking diff --git a/src/infra/net/ssrf.dispatcher.test.ts b/src/infra/net/ssrf.dispatcher.test.ts index af6fc8ae5e8..27060cdb89e 100644 --- a/src/infra/net/ssrf.dispatcher.test.ts +++ b/src/infra/net/ssrf.dispatcher.test.ts @@ -109,6 +109,37 @@ describe("createPinnedDispatcher", () => { expect(originalLookup).not.toHaveBeenCalled(); }); + it("keeps the override bound to the matching hostname only", () => { + const originalLookup = vi.fn( + (_hostname: string, callback: (err: null, address: string, family: number) => void) => { + callback(null, "93.184.216.34", 4); + }, + ) as unknown as PinnedHostname["lookup"]; + const pinned: PinnedHostname = { + hostname: "api.telegram.org", + addresses: ["149.154.167.221"], + lookup: originalLookup, + }; + + createPinnedDispatcher(pinned, { + mode: "direct", + pinnedHostname: { + hostname: "api.telegram.org", + addresses: ["149.154.167.220"], + }, + }); + + const firstCallArg = agentCtor.mock.calls.at(-1)?.[0] as + | { connect?: { lookup?: PinnedHostname["lookup"] } } + | undefined; + const lookup = firstCallArg?.connect?.lookup; + const callback = vi.fn(); + lookup?.("example.com", callback); + + expect(originalLookup).toHaveBeenCalledWith("example.com", expect.any(Function)); + expect(callback).toHaveBeenCalledWith(null, "93.184.216.34", 4); + }); + it("rejects pinned override addresses that violate SSRF policy", () => { const originalLookup = vi.fn() as unknown as PinnedHostname["lookup"]; const pinned: PinnedHostname = {