test: avoid web fetch barrel in ssrf tests

This commit is contained in:
Peter Steinberger
2026-04-18 20:50:17 +01:00
parent b928f360a1
commit 60baaf6e04

View File

@@ -1,6 +1,7 @@
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import * as ssrf from "../../infra/net/ssrf.js";
import { type FetchMock, withFetchPreconnect } from "../../test-utils/fetch-mock.js";
import { createWebFetchTool } from "./web-fetch.js";
import { makeFetchHeaders } from "./web-fetch.test-harness.js";
import "./web-fetch.test-mocks.js";
@@ -33,12 +34,11 @@ function setMockFetch(
return fetchSpy;
}
async function createWebFetchToolForTest(params?: {
function createWebFetchToolForTest(params?: {
firecrawlApiKey?: string;
ssrfPolicy?: { allowRfc2544BenchmarkRange?: boolean };
cacheTtlMinutes?: number;
}) {
const { createWebFetchTool } = await import("./web-tools.js");
return createWebFetchTool({
config: {
plugins: params?.firecrawlApiKey
@@ -69,7 +69,7 @@ async function createWebFetchToolForTest(params?: {
}
async function expectBlockedUrl(
tool: Awaited<ReturnType<typeof createWebFetchToolForTest>>,
tool: ReturnType<typeof createWebFetchToolForTest>,
url: string,
expectedMessage: RegExp,
) {
@@ -93,7 +93,7 @@ describe("web_fetch SSRF protection", () => {
it("blocks localhost hostnames before fetch/firecrawl", async () => {
const fetchSpy = setMockFetch();
const tool = await createWebFetchToolForTest({
const tool = createWebFetchToolForTest({
firecrawlApiKey: "firecrawl-test", // pragma: allowlist secret
});
@@ -104,7 +104,7 @@ describe("web_fetch SSRF protection", () => {
it("blocks private IP literals without DNS", async () => {
const fetchSpy = setMockFetch();
const tool = await createWebFetchToolForTest();
const tool = createWebFetchToolForTest();
const cases = ["http://127.0.0.1/test", "http://[::ffff:127.0.0.1]/"] as const;
for (const url of cases) {
@@ -123,7 +123,7 @@ describe("web_fetch SSRF protection", () => {
});
const fetchSpy = setMockFetch();
const tool = await createWebFetchToolForTest();
const tool = createWebFetchToolForTest();
await expectBlockedUrl(tool, "https://private.test/resource", /private|internal|blocked/i);
expect(fetchSpy).not.toHaveBeenCalled();
@@ -135,7 +135,7 @@ describe("web_fetch SSRF protection", () => {
const fetchSpy = setMockFetch().mockResolvedValueOnce(
redirectResponse("http://127.0.0.1/secret"),
);
const tool = await createWebFetchToolForTest({
const tool = createWebFetchToolForTest({
firecrawlApiKey: "firecrawl-test", // pragma: allowlist secret
});
@@ -147,7 +147,7 @@ describe("web_fetch SSRF protection", () => {
lookupMock.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]);
setMockFetch().mockResolvedValue(textResponse("ok"));
const tool = await createWebFetchToolForTest();
const tool = createWebFetchToolForTest();
const result = await tool?.execute?.("call", { url: "https://example.com" });
expect(result?.details).toMatchObject({
@@ -160,11 +160,11 @@ describe("web_fetch SSRF protection", () => {
const url = "http://198.18.0.153/file";
lookupMock.mockResolvedValue([{ address: "198.18.0.153", family: 4 }]);
const deniedTool = await createWebFetchToolForTest({ cacheTtlMinutes: 1 });
const deniedTool = createWebFetchToolForTest({ cacheTtlMinutes: 1 });
await expectBlockedUrl(deniedTool, url, /private|internal|blocked/i);
const fetchSpy = setMockFetch().mockResolvedValue(textResponse("benchmark ok"));
const allowedTool = await createWebFetchToolForTest({
const allowedTool = createWebFetchToolForTest({
ssrfPolicy: { allowRfc2544BenchmarkRange: true },
cacheTtlMinutes: 1,
});
@@ -175,7 +175,7 @@ describe("web_fetch SSRF protection", () => {
extractor: "raw",
});
expect(fetchSpy).toHaveBeenCalledTimes(1);
const stricterTool = await createWebFetchToolForTest({ cacheTtlMinutes: 1 });
const stricterTool = createWebFetchToolForTest({ cacheTtlMinutes: 1 });
await expectBlockedUrl(stricterTool, url, /private|internal|blocked/i);
});
});