openclaw/src/agents/tools/web-guarded-fetch.ts

84 lines
2.4 KiB
TypeScript

import {
fetchWithSsrFGuard,
type GuardedFetchOptions,
type GuardedFetchResult,
withStrictGuardedFetchMode,
withTrustedEnvProxyGuardedFetchMode,
} from "../../infra/net/fetch-guard.js";
import type { SsrFPolicy } from "../../infra/net/ssrf.js";
const WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY: SsrFPolicy = {
dangerouslyAllowPrivateNetwork: true,
allowRfc2544BenchmarkRange: true,
};
type WebToolGuardedFetchOptions = Omit<
GuardedFetchOptions,
"mode" | "proxy" | "dangerouslyAllowEnvProxyWithoutPinnedDns"
> & {
timeoutSeconds?: number;
useEnvProxy?: boolean;
};
type WebToolEndpointFetchOptions = Omit<WebToolGuardedFetchOptions, "policy" | "useEnvProxy">;
function resolveTimeoutMs(params: {
timeoutMs?: number;
timeoutSeconds?: number;
}): number | undefined {
if (typeof params.timeoutMs === "number" && Number.isFinite(params.timeoutMs)) {
return params.timeoutMs;
}
if (typeof params.timeoutSeconds === "number" && Number.isFinite(params.timeoutSeconds)) {
return params.timeoutSeconds * 1000;
}
return undefined;
}
export async function fetchWithWebToolsNetworkGuard(
params: WebToolGuardedFetchOptions,
): Promise<GuardedFetchResult> {
const { timeoutSeconds, useEnvProxy, ...rest } = params;
const resolved = {
...rest,
timeoutMs: resolveTimeoutMs({ timeoutMs: rest.timeoutMs, timeoutSeconds }),
};
return fetchWithSsrFGuard(
useEnvProxy
? withTrustedEnvProxyGuardedFetchMode(resolved)
: withStrictGuardedFetchMode(resolved),
);
}
async function withWebToolsNetworkGuard<T>(
params: WebToolGuardedFetchOptions,
run: (result: { response: Response; finalUrl: string }) => Promise<T>,
): Promise<T> {
const { response, finalUrl, release } = await fetchWithWebToolsNetworkGuard(params);
try {
return await run({ response, finalUrl });
} finally {
await release();
}
}
export async function withTrustedWebToolsEndpoint<T>(
params: WebToolEndpointFetchOptions,
run: (result: { response: Response; finalUrl: string }) => Promise<T>,
): Promise<T> {
return await withWebToolsNetworkGuard(
{
...params,
policy: WEB_TOOLS_TRUSTED_NETWORK_SSRF_POLICY,
useEnvProxy: true,
},
run,
);
}
export async function withStrictWebToolsEndpoint<T>(
params: WebToolEndpointFetchOptions,
run: (result: { response: Response; finalUrl: string }) => Promise<T>,
): Promise<T> {
return await withWebToolsNetworkGuard(params, run);
}