mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-10 05:52:45 +00:00
fix: preserve dns pinning for strict web SSRF fetches
This commit is contained in:
@@ -27,6 +27,8 @@ describe("web-guarded-fetch", () => {
|
||||
dangerouslyAllowPrivateNetwork: true,
|
||||
allowRfc2544BenchmarkRange: true,
|
||||
}),
|
||||
proxy: "env",
|
||||
dangerouslyAllowEnvProxyWithoutPinnedDns: true,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -47,5 +49,7 @@ describe("web-guarded-fetch", () => {
|
||||
);
|
||||
const call = vi.mocked(fetchWithSsrFGuard).mock.calls[0]?.[0];
|
||||
expect(call?.policy).toBeUndefined();
|
||||
expect(call?.proxy).toBeUndefined();
|
||||
expect(call?.dangerouslyAllowEnvProxyWithoutPinnedDns).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,10 +10,14 @@ const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = {
|
||||
allowRfc2544BenchmarkRange: true,
|
||||
};
|
||||
|
||||
type WebToolGuardedFetchOptions = Omit<GuardedFetchOptions, "proxy"> & {
|
||||
type WebToolGuardedFetchOptions = Omit<
|
||||
GuardedFetchOptions,
|
||||
"proxy" | "dangerouslyAllowEnvProxyWithoutPinnedDns"
|
||||
> & {
|
||||
timeoutSeconds?: number;
|
||||
useEnvProxy?: boolean;
|
||||
};
|
||||
type WebToolEndpointFetchOptions = Omit<WebToolGuardedFetchOptions, "policy">;
|
||||
type WebToolEndpointFetchOptions = Omit<WebToolGuardedFetchOptions, "policy" | "useEnvProxy">;
|
||||
|
||||
function resolveTimeoutMs(params: {
|
||||
timeoutMs?: number;
|
||||
@@ -31,11 +35,16 @@ function resolveTimeoutMs(params: {
|
||||
export async function fetchWithWebToolsNetworkGuard(
|
||||
params: WebToolGuardedFetchOptions,
|
||||
): Promise<GuardedFetchResult> {
|
||||
const { timeoutSeconds, ...rest } = params;
|
||||
const { timeoutSeconds, useEnvProxy, ...rest } = params;
|
||||
return fetchWithSsrFGuard({
|
||||
...rest,
|
||||
timeoutMs: resolveTimeoutMs({ timeoutMs: rest.timeoutMs, timeoutSeconds }),
|
||||
proxy: "env",
|
||||
...(useEnvProxy
|
||||
? {
|
||||
proxy: "env",
|
||||
dangerouslyAllowEnvProxyWithoutPinnedDns: true,
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -59,6 +68,7 @@ export async function withTrustedWebToolsEndpoint<T>(
|
||||
{
|
||||
...params,
|
||||
policy: WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY,
|
||||
useEnvProxy: true,
|
||||
},
|
||||
run,
|
||||
);
|
||||
|
||||
@@ -32,9 +32,9 @@ describe("web_search redirect resolution hardening", () => {
|
||||
url: "https://example.com/start",
|
||||
timeoutMs: 5000,
|
||||
init: { method: "HEAD" },
|
||||
proxy: "env",
|
||||
}),
|
||||
);
|
||||
expect(fetchWithSsrFGuardMock.mock.calls[0]?.[0]?.proxy).toBeUndefined();
|
||||
expect(fetchWithSsrFGuardMock.mock.calls[0]?.[0]?.policy).toBeUndefined();
|
||||
expect(release).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -258,7 +258,7 @@ describe("web_fetch extraction fallbacks", () => {
|
||||
expect(details?.warning).toContain("Response body truncated");
|
||||
});
|
||||
|
||||
it("uses proxy-aware dispatcher when HTTP_PROXY is configured", async () => {
|
||||
it("keeps DNS pinning for untrusted web_fetch URLs even when HTTP_PROXY is configured", async () => {
|
||||
vi.stubEnv("HTTP_PROXY", "http://127.0.0.1:7890");
|
||||
const mockFetch = installMockFetch((input: RequestInfo | URL) =>
|
||||
Promise.resolve({
|
||||
@@ -276,7 +276,8 @@ describe("web_fetch extraction fallbacks", () => {
|
||||
const requestInit = mockFetch.mock.calls[0]?.[1] as
|
||||
| (RequestInit & { dispatcher?: unknown })
|
||||
| undefined;
|
||||
expect(requestInit?.dispatcher).toBeInstanceOf(EnvHttpProxyAgent);
|
||||
expect(requestInit?.dispatcher).toBeDefined();
|
||||
expect(requestInit?.dispatcher).not.toBeInstanceOf(EnvHttpProxyAgent);
|
||||
});
|
||||
|
||||
// NOTE: Test for wrapping url/finalUrl/warning fields requires DNS mocking.
|
||||
|
||||
Reference in New Issue
Block a user