fix(ssrf): handle Node 20+ Happy Eyeballs dns lookup signature in pinned agent
Node 20+ enables autoSelectFamily by default, causing internal dns lookups to be called with `all: true`. This expects the callback to receive an array of address objects instead of a flat (address, family) pair, causing webhook requests to fail with "Invalid IP address: undefined".
This commit is contained in:
@@ -112,10 +112,15 @@ export async function checkSsrf(rawUrl: string, bypassInternalIpAllowed: boolean
|
|||||||
*/
|
*/
|
||||||
export function createPinnedAgent(resolvedIp: string, protocol: string): http.Agent | https.Agent {
|
export function createPinnedAgent(resolvedIp: string, protocol: string): http.Agent | https.Agent {
|
||||||
const options = {
|
const options = {
|
||||||
lookup: (_hostname: string, _opts: unknown, callback: (err: Error | null, addr: string, family: number) => void) => {
|
lookup: (_hostname: string, opts: Record<string, unknown>, callback: Function) => {
|
||||||
// Determine address family from IP format
|
// Determine address family from IP format
|
||||||
const family = resolvedIp.includes(':') ? 6 : 4;
|
const family = resolvedIp.includes(':') ? 6 : 4;
|
||||||
callback(null, resolvedIp, family);
|
// Node.js 18+ may call lookup with `all: true`, expecting an array of address objects
|
||||||
|
if (opts && opts.all) {
|
||||||
|
callback(null, [{ address: resolvedIp, family }]);
|
||||||
|
} else {
|
||||||
|
callback(null, resolvedIp, family);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return protocol === 'https:' ? new https.Agent(options) : new http.Agent(options);
|
return protocol === 'https:' ? new https.Agent(options) : new http.Agent(options);
|
||||||
|
|||||||
Reference in New Issue
Block a user