diff --git a/src/HttpAgent.ts b/src/HttpAgent.ts index 54feaa46..e26eecd4 100644 --- a/src/HttpAgent.ts +++ b/src/HttpAgent.ts @@ -6,7 +6,7 @@ import { buildConnector, } from 'undici'; -export type CheckAddressFunction = (ip: string, family: number | string) => boolean; +export type CheckAddressFunction = (ip: string, family: number | string, hostname: string) => boolean; export type HttpAgentOptions = { lookup?: LookupFunction; @@ -46,13 +46,13 @@ export class HttpAgent extends Agent { if (options.checkAddress) { // dnsOptions.all set to default on Node.js >= 20, dns.lookup will return address array object if (typeof address === 'string') { - if (!options.checkAddress(address, family)) { + if (!options.checkAddress(address, family, hostname)) { err = new IllegalAddressError(hostname, address, family); } } else if (Array.isArray(address)) { const addresses = address as { address: string, family: number }[]; for (const addr of addresses) { - if (!options.checkAddress(addr.address, addr.family)) { + if (!options.checkAddress(addr.address, addr.family, hostname)) { err = new IllegalAddressError(hostname, addr.address, addr.family); break; } @@ -79,7 +79,7 @@ export class HttpAgent extends Agent { const family = isIP(hostname); if (family === 4 || family === 6) { // if request hostname is ip, custom lookup won't execute - if (!this.#checkAddress(hostname, family)) { + if (!this.#checkAddress(hostname, family, hostname)) { throw new IllegalAddressError(hostname, hostname, family); } } diff --git a/test/HttpClient.test.ts b/test/HttpClient.test.ts index ff1bf204..59bda980 100644 --- a/test/HttpClient.test.ts +++ b/test/HttpClient.test.ts @@ -313,5 +313,32 @@ describe('HttpClient.test.ts', () => { return true; }); }); + + it('should allow hostname check', async () => { + let hostname: string; + const httpclient = new HttpClient({ + checkAddress(ip, family, aHostname) { + hostname = aHostname; + return true; + }, + lookup(hostname, options, callback) { + if ( + process.version.startsWith('v18') + || process.version.startsWith('v16') + || process.version.startsWith('v14') + ) { + return callback(null, '127.0.0.1', 4); + } + return callback(null, [{ + address: '127.0.0.1', + family: 4, + }]); + }, + }); + + const response = await httpclient.request(_url.replace('localhost', 'check-host-ssrf.com')); + assert.equal(hostname, 'check-host-ssrf.com'); + assert.equal(response.status, 200); + }); }); });