mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-15 19:21:08 +00:00
fix(net): skip DNS pinning before trusted env proxy dispatch
This commit is contained in:
committed by
Peter Steinberger
parent
b4034b32c3
commit
d7c3210cd6
@@ -7,6 +7,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Slack: honor ambient HTTP(S) proxy settings for Socket Mode WebSocket connections, including NO_PROXY exclusions, so proxy-only deployments can connect without a monkey patch. (#62878) Thanks @mjamiv.
|
||||
- Network/fetch guard: skip target DNS pinning when trusted env-proxy mode is active so proxy-only sandboxes can let the trusted proxy resolve outbound hosts. (#59007) Thanks @cluster2600.
|
||||
|
||||
## 2026.4.7-1
|
||||
|
||||
|
||||
@@ -81,6 +81,15 @@ async function expectRedirectFailure(params: {
|
||||
}
|
||||
|
||||
describe("fetchWithSsrFGuard hardening", () => {
|
||||
const PROXY_ENV_KEYS = [
|
||||
"HTTP_PROXY",
|
||||
"HTTPS_PROXY",
|
||||
"ALL_PROXY",
|
||||
"http_proxy",
|
||||
"https_proxy",
|
||||
"all_proxy",
|
||||
] as const;
|
||||
|
||||
type LookupFn = NonNullable<Parameters<typeof fetchWithSsrFGuard>[0]["lookupFn"]>;
|
||||
const CROSS_ORIGIN_REDIRECT_STRIPPED_HEADERS = [
|
||||
"authorization",
|
||||
@@ -100,10 +109,17 @@ describe("fetchWithSsrFGuard hardening", () => {
|
||||
const createPublicLookup = (): LookupFn =>
|
||||
vi.fn(async () => [{ address: "93.184.216.34", family: 4 }]) as unknown as LookupFn;
|
||||
|
||||
function clearProxyEnv(): void {
|
||||
for (const key of PROXY_ENV_KEYS) {
|
||||
vi.stubEnv(key, "");
|
||||
}
|
||||
}
|
||||
|
||||
async function runProxyModeDispatcherTest(params: {
|
||||
mode: (typeof GUARDED_FETCH_MODE)[keyof typeof GUARDED_FETCH_MODE];
|
||||
expectEnvProxy: boolean;
|
||||
}): Promise<void> {
|
||||
clearProxyEnv();
|
||||
vi.stubEnv("HTTP_PROXY", "http://127.0.0.1:7890");
|
||||
(globalThis as Record<string, unknown>)[TEST_UNDICI_RUNTIME_DEPS_KEY] = {
|
||||
Agent: agentCtor,
|
||||
@@ -1032,4 +1048,26 @@ describe("fetchWithSsrFGuard hardening", () => {
|
||||
).rejects.toThrow(/blocked/i);
|
||||
expect(fetchImpl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("falls back to DNS pinning in trusted proxy mode when no proxy env var is configured", async () => {
|
||||
clearProxyEnv();
|
||||
const lookupFn = createPublicLookup();
|
||||
const fetchImpl = vi.fn(async (_input: RequestInfo | URL, init?: RequestInit) => {
|
||||
const requestInit = init as RequestInit & { dispatcher?: unknown };
|
||||
expect(requestInit.dispatcher).toBeDefined();
|
||||
expect(getDispatcherClassName(requestInit.dispatcher)).not.toBe("EnvHttpProxyAgent");
|
||||
return okResponse();
|
||||
});
|
||||
|
||||
const result = await fetchWithSsrFGuard({
|
||||
url: "https://public.example/resource",
|
||||
fetchImpl,
|
||||
lookupFn,
|
||||
mode: GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY,
|
||||
});
|
||||
|
||||
expect(fetchImpl).toHaveBeenCalledTimes(1);
|
||||
expect(lookupFn).toHaveBeenCalledOnce();
|
||||
await result.release();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -313,10 +313,6 @@ export async function fetchWithSsrFGuard(params: GuardedFetchOptions): Promise<G
|
||||
try {
|
||||
assertExplicitProxySupportsPinnedDns(parsedUrl, params.dispatcherPolicy, params.pinDns);
|
||||
await assertExplicitProxyAllowed(params.dispatcherPolicy, params.lookupFn, params.policy);
|
||||
const pinned = await resolvePinnedHostnameWithPolicy(parsedUrl.hostname, {
|
||||
lookupFn: params.lookupFn,
|
||||
policy: params.policy,
|
||||
});
|
||||
const canUseTrustedEnvProxy =
|
||||
mode === GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY && hasProxyEnvConfigured();
|
||||
if (canUseTrustedEnvProxy) {
|
||||
@@ -324,6 +320,10 @@ export async function fetchWithSsrFGuard(params: GuardedFetchOptions): Promise<G
|
||||
} else if (params.pinDns === false) {
|
||||
dispatcher = createPolicyDispatcherWithoutPinnedDns(params.dispatcherPolicy);
|
||||
} else {
|
||||
const pinned = await resolvePinnedHostnameWithPolicy(parsedUrl.hostname, {
|
||||
lookupFn: params.lookupFn,
|
||||
policy: params.policy,
|
||||
});
|
||||
dispatcher = createPinnedDispatcher(pinned, params.dispatcherPolicy, params.policy);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user