diff --git a/src/infra/net/ssrf.dispatcher.test.ts b/src/infra/net/ssrf.dispatcher.test.ts index 27060cdb89e..3303bf8ffaa 100644 --- a/src/infra/net/ssrf.dispatcher.test.ts +++ b/src/infra/net/ssrf.dispatcher.test.ts @@ -210,9 +210,29 @@ describe("createPinnedDispatcher", () => { expect(proxyAgentCtor).toHaveBeenCalledWith({ uri: "http://127.0.0.1:7890", + requestTls: { lookup }, proxyTls: { autoSelectFamily: false, }, }); }); + + it("passes pinned lookup via requestTls when proxyTls is absent", () => { + const lookup = vi.fn() as unknown as PinnedHostname["lookup"]; + const pinned: PinnedHostname = { + hostname: "api.telegram.org", + addresses: ["149.154.167.220"], + lookup, + }; + + createPinnedDispatcher(pinned, { + mode: "explicit-proxy", + proxyUrl: "http://127.0.0.1:7890", + }); + + expect(proxyAgentCtor).toHaveBeenCalledWith({ + uri: "http://127.0.0.1:7890", + requestTls: { lookup }, + }); + }); }); diff --git a/src/infra/net/ssrf.ts b/src/infra/net/ssrf.ts index fd633fcb20d..2e053885b46 100644 --- a/src/infra/net/ssrf.ts +++ b/src/infra/net/ssrf.ts @@ -416,11 +416,16 @@ export function createPinnedDispatcher( } const proxyUrl = policy.proxyUrl.trim(); + // Always pass the pinned lookup via requestTls so DNS resolution for the + // origin server goes through the SSRF-safe pinned lookup, not the default + // resolver. Without this, ProxyAgent bypasses DNS pinning (#46685). + const requestTls = withPinnedLookup(pinned.lookup); if (!policy.proxyTls) { - return new ProxyAgent(proxyUrl); + return new ProxyAgent({ uri: proxyUrl, requestTls }); } return new ProxyAgent({ uri: proxyUrl, + requestTls, proxyTls: { ...policy.proxyTls }, }); }