import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import http from 'http'; import { AddressInfo } from 'net'; vi.mock('dns/promises', () => { return { default: { lookup: vi.fn() }, lookup: vi.fn(), }; }); async function setMockLookup(impl: (hostname: string) => Array<{ address: string; family: number }>) { const dns = await import('dns/promises'); (dns.default.lookup as any).mockImplementation(async (h: string) => impl(h)); (dns.lookup as any).mockImplementation(async (h: string) => impl(h)); } async function loadPinnedFetch() { return await import('../src/utils/pinned-fetch'); } describe('pinnedFetch DNS rebinding defence', () => { let server: http.Server; let serverPort: number; beforeEach(async () => { server = http.createServer((_req, res) => { res.writeHead(200, { 'content-type': 'text/html' }); res.end('

ok

'); }); await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve)); serverPort = (server.address() as AddressInfo).port; }); afterEach(async () => { await new Promise((resolve) => server.close(() => resolve())); }); it('refuses hostnames whose DNS returns a loopback record', async () => { await setMockLookup(() => [{ address: '127.0.0.1', family: 4 }]); const { pinnedFetch } = await loadPinnedFetch(); await expect( pinnedFetch(`http://evil.example:${serverPort}/x`), ).rejects.toMatchObject({ message: expect.stringContaining('private') }); }); it('refuses hostnames where ANY A record is private (dual-answer rebinding)', async () => { await setMockLookup(() => [ { address: '8.8.8.8', family: 4 }, { address: '192.168.1.2', family: 4 }, ]); const { pinnedFetch } = await loadPinnedFetch(); await expect( pinnedFetch(`http://evil.example:${serverPort}/x`), ).rejects.toMatchObject({ message: expect.stringContaining('private') }); }); it('refuses hostnames that resolve only to IPv6 ULA', async () => { await setMockLookup(() => [{ address: 'fc00::1', family: 6 }]); const { pinnedFetch } = await loadPinnedFetch(); await expect( pinnedFetch(`http://evil.example:${serverPort}/x`), ).rejects.toMatchObject({ message: expect.stringContaining('private') }); }); it('refuses metadata service IP directly', async () => { await setMockLookup(() => [{ address: '169.254.169.254', family: 4 }]); const { pinnedFetch } = await loadPinnedFetch(); await expect( pinnedFetch(`http://evil.example:${serverPort}/x`), ).rejects.toMatchObject({ message: expect.stringContaining('private') }); }); it('refuses when DNS returns no records', async () => { await setMockLookup(() => []); const { pinnedFetch } = await loadPinnedFetch(); await expect( pinnedFetch(`http://evil.example:${serverPort}/x`), ).rejects.toMatchObject({ message: expect.stringContaining('DNS') }); }); });