/** * Decide whether to auto-upgrade a provider HTTP request into * `TRUSTED_ENV_PROXY` mode based on the runtime environment. * * This is gated conservatively to avoid the SSRF bypasses the initial * auto-upgrade path exposed (see openclaw#64974 review threads): * * 1. If the caller supplied an explicit `dispatcherPolicy` — custom proxy URL, * `proxyTls`, or `connect` options — do NOT override it. Trusted-env mode * builds an `EnvHttpProxyAgent` that would silently drop those overrides, * breaking enterprise proxy/mTLS configs. * * 2. Only auto-upgrade when `HTTP_PROXY` or `HTTPS_PROXY` (lower- or * upper-case) is configured for the target protocol. `ALL_PROXY` is * explicitly ignored by `EnvHttpProxyAgent`, so counting it would * auto-upgrade requests that then make direct connections while skipping * pinned-DNS/SSRF hostname checks. * * 3. If `NO_PROXY` would bypass the proxy for this target, do NOT auto-upgrade. * `EnvHttpProxyAgent` makes direct connections for `NO_PROXY` matches, but * in `TRUSTED_ENV_PROXY` mode `fetchWithSsrFGuard` skips * `resolvePinnedHostnameWithPolicy` — so those direct connections would * bypass SSRF protection. Keep strict mode for `NO_PROXY` matches.
*/ function shouldAutoUpgradeToTrustedEnvProxy(params: {
url: string;
dispatcherPolicy: PinnedDispatcherPolicy | undefined;
}): boolean { if (params.dispatcherPolicy) { returnfalse;
}
if (!hasEnvHttpProxyConfigured(protocol)) { returnfalse;
}
if (matchesNoProxy(params.url)) { returnfalse;
}
returntrue;
}
export async function fetchWithTimeoutGuarded(
url: string,
init: RequestInit,
timeoutMs: number | undefined,
fetchFn: typeof fetch,
options?: {
ssrfPolicy?: SsrFPolicy;
lookupFn?: LookupFn;
pinDns?: boolean;
dispatcherPolicy?: PinnedDispatcherPolicy;
auditContext?: string;
mode?: GuardedFetchMode;
},
): Promise<GuardedFetchResult> { // Provider HTTP helpers (image/music/video generation, transcription, etc.) // call this function from every provider that talks to a remote API. When // the host has HTTP_PROXY/HTTPS_PROXY configured, the lower-level strict // mode would force Node-level `dns.lookup()` on the target hostname before // dialing the proxy — which fails with EAI_AGAIN in proxy-only environments // (containers, restricted sandboxes, corporate networks with DNS-over-proxy, // Clash TUN fake-IP, etc.). Auto-upgrade to trusted env proxy mode in that // case so the request goes through the configured proxy agent instead of // doing a local DNS pre-resolution. // // This does not weaken SSRF protection when the auto-upgrade fires: an HTTP // CONNECT proxy on the egress path performs hostname resolution itself and // client-side DNS pinning cannot meaningfully constrain the target IP. But // the auto-upgrade is gated (see `shouldAutoUpgradeToTrustedEnvProxy`) to // avoid three SSRF-bypass edge cases: caller-provided `dispatcherPolicy`, // `ALL_PROXY`-only envs, and `NO_PROXY` target matches. Callers that // explicitly need strict pinned-DNS can still opt in by passing // `mode: GUARDED_FETCH_MODE.STRICT` here or by using `fetchWithSsrFGuard` // directly. // // See openclaw#52162 for the reported failure mode on memory embeddings, // which shares this code path with image/music/video/audio generation. const resolvedMode =
options?.mode ??
(shouldAutoUpgradeToTrustedEnvProxy({
url,
dispatcherPolicy: options?.dispatcherPolicy,
})
? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY
: undefined); return await fetchWithSsrFGuard({
url,
fetchImpl: fetchFn,
init,
timeoutMs: resolveGuardedHttpTimeoutMs(timeoutMs),
policy: options?.ssrfPolicy,
lookupFn: options?.lookupFn,
pinDns: options?.pinDns,
dispatcherPolicy: options?.dispatcherPolicy,
auditContext: sanitizeAuditContext(options?.auditContext),
...(resolvedMode ? { mode: resolvedMode } : {}),
});
}
type GuardedPostRequestOptions = NonNullable<Parameters<typeof fetchWithTimeoutGuarded>[4]>;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.