mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 01:18:28 +00:00
refactor(agent): dedupe harness and command workflows
This commit is contained in:
@@ -28,6 +28,30 @@ function textResponse(body: string): Response {
|
||||
} as Response;
|
||||
}
|
||||
|
||||
function setMockFetch(impl?: (...args: unknown[]) => unknown) {
|
||||
const fetchSpy = vi.fn(impl);
|
||||
global.fetch = fetchSpy as typeof fetch;
|
||||
return fetchSpy;
|
||||
}
|
||||
|
||||
async function createWebFetchToolForTest(params?: {
|
||||
firecrawl?: { enabled?: boolean; apiKey?: string };
|
||||
}) {
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
return createWebFetchTool({
|
||||
config: {
|
||||
tools: {
|
||||
web: {
|
||||
fetch: {
|
||||
cacheTtlMinutes: 0,
|
||||
firecrawl: params?.firecrawl ?? { enabled: false },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe("web_fetch SSRF protection", () => {
|
||||
const priorFetch = global.fetch;
|
||||
|
||||
@@ -45,22 +69,9 @@ describe("web_fetch SSRF protection", () => {
|
||||
});
|
||||
|
||||
it("blocks localhost hostnames before fetch/firecrawl", async () => {
|
||||
const fetchSpy = vi.fn();
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = fetchSpy;
|
||||
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
const tool = createWebFetchTool({
|
||||
config: {
|
||||
tools: {
|
||||
web: {
|
||||
fetch: {
|
||||
cacheTtlMinutes: 0,
|
||||
firecrawl: { apiKey: "firecrawl-test" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
const fetchSpy = setMockFetch();
|
||||
const tool = await createWebFetchToolForTest({
|
||||
firecrawl: { apiKey: "firecrawl-test" },
|
||||
});
|
||||
|
||||
await expect(tool?.execute?.("call", { url: "http://localhost/test" })).rejects.toThrow(
|
||||
@@ -71,16 +82,8 @@ describe("web_fetch SSRF protection", () => {
|
||||
});
|
||||
|
||||
it("blocks private IP literals without DNS", async () => {
|
||||
const fetchSpy = vi.fn();
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = fetchSpy;
|
||||
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
const tool = createWebFetchTool({
|
||||
config: {
|
||||
tools: { web: { fetch: { cacheTtlMinutes: 0, firecrawl: { enabled: false } } } },
|
||||
},
|
||||
});
|
||||
const fetchSpy = setMockFetch();
|
||||
const tool = await createWebFetchToolForTest();
|
||||
|
||||
await expect(tool?.execute?.("call", { url: "http://127.0.0.1/test" })).rejects.toThrow(
|
||||
/private|internal|blocked/i,
|
||||
@@ -100,16 +103,8 @@ describe("web_fetch SSRF protection", () => {
|
||||
return [{ address: "10.0.0.5", family: 4 }];
|
||||
});
|
||||
|
||||
const fetchSpy = vi.fn();
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = fetchSpy;
|
||||
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
const tool = createWebFetchTool({
|
||||
config: {
|
||||
tools: { web: { fetch: { cacheTtlMinutes: 0, firecrawl: { enabled: false } } } },
|
||||
},
|
||||
});
|
||||
const fetchSpy = setMockFetch();
|
||||
const tool = await createWebFetchToolForTest();
|
||||
|
||||
await expect(tool?.execute?.("call", { url: "https://private.test/resource" })).rejects.toThrow(
|
||||
/private|internal|blocked/i,
|
||||
@@ -120,19 +115,11 @@ describe("web_fetch SSRF protection", () => {
|
||||
it("blocks redirects to private hosts", async () => {
|
||||
lookupMock.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]);
|
||||
|
||||
const fetchSpy = vi.fn().mockResolvedValueOnce(redirectResponse("http://127.0.0.1/secret"));
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = fetchSpy;
|
||||
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
const tool = createWebFetchTool({
|
||||
config: {
|
||||
tools: {
|
||||
web: {
|
||||
fetch: { cacheTtlMinutes: 0, firecrawl: { apiKey: "firecrawl-test" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
const fetchSpy = setMockFetch().mockResolvedValueOnce(
|
||||
redirectResponse("http://127.0.0.1/secret"),
|
||||
);
|
||||
const tool = await createWebFetchToolForTest({
|
||||
firecrawl: { apiKey: "firecrawl-test" },
|
||||
});
|
||||
|
||||
await expect(tool?.execute?.("call", { url: "https://example.com" })).rejects.toThrow(
|
||||
@@ -144,16 +131,8 @@ describe("web_fetch SSRF protection", () => {
|
||||
it("allows public hosts", async () => {
|
||||
lookupMock.mockResolvedValue([{ address: "93.184.216.34", family: 4 }]);
|
||||
|
||||
const fetchSpy = vi.fn().mockResolvedValue(textResponse("ok"));
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = fetchSpy;
|
||||
|
||||
const { createWebFetchTool } = await import("./web-tools.js");
|
||||
const tool = createWebFetchTool({
|
||||
config: {
|
||||
tools: { web: { fetch: { cacheTtlMinutes: 0, firecrawl: { enabled: false } } } },
|
||||
},
|
||||
});
|
||||
setMockFetch().mockResolvedValue(textResponse("ok"));
|
||||
const tool = await createWebFetchToolForTest();
|
||||
|
||||
const result = await tool?.execute?.("call", { url: "https://example.com" });
|
||||
expect(result?.details).toMatchObject({
|
||||
|
||||
Reference in New Issue
Block a user