fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode for remote embeddings in proxy environments#71506
Conversation
Greptile SummaryThis PR routes remote memory embedding requests through the environment-configured HTTP proxy by switching to
Confidence Score: 3/5Not safe to merge — the proxy detection gate can disable SSRF guards without routing traffic through a proxy in two concrete scenarios (ALL_PROXY-only and NO_PROXY exclusions). Two P1 security findings where SSRF protections are stripped without the proxy actually intercepting the traffic, introduced in both copies of the changed file. The fix is small and well-documented within the codebase itself. Both src/memory-host-sdk/host/remote-http.ts and packages/memory-host-sdk/src/host/remote-http.ts need the proxy gate condition corrected before merging.
|
| auditContext: params.auditContext ?? "memory-remote", | ||
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
There was a problem hiding this comment.
SSRF checks disabled when traffic bypasses the proxy
hasProxyEnvConfigured() returns true for ALL_PROXY/all_proxy, but EnvHttpProxyAgent (used by TRUSTED_ENV_PROXY mode) explicitly ignores ALL_PROXY (see the comment in proxy-env.ts line 32). So when only ALL_PROXY is set, SSRF guards are stripped while the request still goes direct — no proxy, no protection.
The same issue applies to NO_PROXY: if the target URL is listed in NO_PROXY, undici routes it direct, but SSRF checks are already bypassed by the mode switch.
The existing codebase already documents the correct gating pattern for this exact scenario (see proxy-env.ts lines 74–79, which references #64974 and says to pair hasEnvHttpProxyConfigured with matchesNoProxy). The condition here should use hasEnvHttpProxyConfigured(protocol) and guard against NO_PROXY exclusions:
import { hasEnvHttpProxyConfigured, matchesNoProxy } from "../../infra/net/proxy-env.js";
const useTrustedProxy =
hasEnvHttpProxyConfigured("https") && !matchesNoProxy(params.url);
mode: useTrustedProxy ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined,Prompt To Fix With AI
This is a comment left during a code review.
Path: src/memory-host-sdk/host/remote-http.ts
Line: 23
Comment:
**SSRF checks disabled when traffic bypasses the proxy**
`hasProxyEnvConfigured()` returns `true` for `ALL_PROXY`/`all_proxy`, but `EnvHttpProxyAgent` (used by `TRUSTED_ENV_PROXY` mode) explicitly ignores `ALL_PROXY` (see the comment in `proxy-env.ts` line 32). So when only `ALL_PROXY` is set, SSRF guards are stripped while the request still goes direct — no proxy, no protection.
The same issue applies to `NO_PROXY`: if the target URL is listed in `NO_PROXY`, undici routes it direct, but SSRF checks are already bypassed by the mode switch.
The existing codebase already documents the correct gating pattern for this exact scenario (see `proxy-env.ts` lines 74–79, which references openclaw#64974 and says to pair `hasEnvHttpProxyConfigured` with `matchesNoProxy`). The condition here should use `hasEnvHttpProxyConfigured(protocol)` and guard against `NO_PROXY` exclusions:
```ts
import { hasEnvHttpProxyConfigured, matchesNoProxy } from "../../infra/net/proxy-env.js";
const useTrustedProxy =
hasEnvHttpProxyConfigured("https") && !matchesNoProxy(params.url);
mode: useTrustedProxy ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined,
```
How can I resolve this? If you propose a fix, please make it concise.| init: params.init, | ||
| policy: params.ssrfPolicy, | ||
| auditContext: params.auditContext ?? "memory-remote", | ||
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy |
There was a problem hiding this comment.
Same SSRF-bypass issue as in
src/memory-host-sdk/host/remote-http.ts
hasProxyEnvConfigured() returns true for ALL_PROXY/all_proxy, but undici's EnvHttpProxyAgent ignores those variables. If only ALL_PROXY is set, or the target URL is excluded via NO_PROXY, SSRF guards are stripped while traffic goes direct. The fix is the same: replace hasProxyEnvConfigured() with hasEnvHttpProxyConfigured("https") && !matchesNoProxy(params.url), mirroring the gating pattern documented in proxy-env.ts (#64974).
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/memory-host-sdk/src/host/remote-http.ts
Line: 35
Comment:
**Same SSRF-bypass issue as in `src/memory-host-sdk/host/remote-http.ts`**
`hasProxyEnvConfigured()` returns `true` for `ALL_PROXY`/`all_proxy`, but undici's `EnvHttpProxyAgent` ignores those variables. If only `ALL_PROXY` is set, or the target URL is excluded via `NO_PROXY`, SSRF guards are stripped while traffic goes direct. The fix is the same: replace `hasProxyEnvConfigured()` with `hasEnvHttpProxyConfigured("https") && !matchesNoProxy(params.url)`, mirroring the gating pattern documented in `proxy-env.ts` (openclaw#64974).
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Pull request overview
This PR adjusts the memory host SDK’s remote HTTP helper to route remote embedding requests through environment-configured HTTP(S) proxies by explicitly selecting GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY when proxy env vars are detected, addressing “fetch failed” issues in proxy-only DNS environments.
Changes:
- Add proxy-env detection to
withRemoteHttpResponseand passmode=TRUSTED_ENV_PROXYtofetchWithSsrFGuardwhen a proxy is configured. - Mirror the same change in the published
packages/memory-host-sdksource copy.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/memory-host-sdk/host/remote-http.ts | Enables trusted env-proxy mode for guarded fetches when proxy env vars are present. |
| packages/memory-host-sdk/src/host/remote-http.ts | Keeps the package copy in sync with the workspace implementation. |
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 518a9e7b7b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| auditContext: params.auditContext ?? "memory-remote", | ||
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
There was a problem hiding this comment.
Skip trusted env-proxy mode for NO_PROXY targets
This auto-upgrade uses hasProxyEnvConfigured() unconditionally, so withRemoteHttpResponse now forces TRUSTED_ENV_PROXY even when the target URL is covered by NO_PROXY. In fetchWithSsrFGuard, trusted-env mode bypasses resolvePinnedHostnameWithPolicy/hostname policy checks and relies on EnvHttpProxyAgent, but NO_PROXY targets are dispatched directly, which reintroduces the SSRF/pinned-DNS bypass path that strict mode previously prevented. The existing guard in src/media-understanding/shared.ts (matchesNoProxy) shows this case must stay in strict mode.
Useful? React with 👍 / 👎.
| auditContext: params.auditContext ?? "memory-remote", | ||
| // FIX: When env proxy is configured, skip local DNS resolution and route through the proxy | ||
| // This fixes remote embedding/copilot memory search failing with "fetch failed" in proxy environments | ||
| mode: hasProxyEnvConfigured() ? GUARDED_FETCH_MODE.TRUSTED_ENV_PROXY : undefined, |
There was a problem hiding this comment.
Ignore ALL_PROXY when enabling trusted env-proxy mode
hasProxyEnvConfigured() treats ALL_PROXY as sufficient to enable trusted env-proxy mode here, but src/infra/net/proxy-env.ts documents that EnvHttpProxyAgent ignores ALL_PROXY. That means this change can switch requests into TRUSTED_ENV_PROXY without an actual HTTP(S) proxy, causing guarded fetch to skip strict DNS/hostname enforcement and still connect directly. The mode gate should be based on HTTP(S)-proxy detection (e.g., protocol-aware hasEnvHttpProxyConfigured) rather than generic proxy-env presence.
Useful? React with 👍 / 👎.
…ponse When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard. This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies). Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy. Fixes: openclaw#52162
518a9e7 to
6740ab2
Compare
|
Landed via squash after rewriting the proxy gate to the shared EnvHttpProxyAgent semantics.
Thanks @DhtIsCoding! |
…s in proxy environments (openclaw#71506) * fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode in withRemoteHttpResponse When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard. This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies). Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy. Fixes: openclaw#52162 * fix: harden memory env proxy guard (openclaw#71506) (thanks @DhtIsCoding) --------- Co-authored-by: Dht <dht@openclaw.ai> Co-authored-by: Peter Steinberger <steipete@gmail.com>
…s in proxy environments (openclaw#71506) * fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode in withRemoteHttpResponse When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard. This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies). Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy. Fixes: openclaw#52162 * fix: harden memory env proxy guard (openclaw#71506) (thanks @DhtIsCoding) --------- Co-authored-by: Dht <dht@openclaw.ai> Co-authored-by: Peter Steinberger <steipete@gmail.com>
…s in proxy environments (openclaw#71506) * fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode in withRemoteHttpResponse When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard. This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies). Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy. Fixes: openclaw#52162 * fix: harden memory env proxy guard (openclaw#71506) (thanks @DhtIsCoding) --------- Co-authored-by: Dht <dht@openclaw.ai> Co-authored-by: Peter Steinberger <steipete@gmail.com>
…s in proxy environments (openclaw#71506) * fix(memory-host-sdk): use TRUSTED_ENV_PROXY mode in withRemoteHttpResponse When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard. This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies). Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy. Fixes: openclaw#52162 * fix: harden memory env proxy guard (openclaw#71506) (thanks @DhtIsCoding) --------- Co-authored-by: Dht <dht@openclaw.ai> Co-authored-by: Peter Steinberger <steipete@gmail.com>
…ponse
When a HTTP/HTTPS proxy is configured via environment variables (HTTPS_PROXY, HTTP_PROXY, ALL_PROXY), the withRemoteHttpResponse function now passes mode=TRUSTED_ENV_PROXY to fetchWithSsrFGuard.
This causes DNS resolution to skip the local resolver and route through the configured proxy, fixing 'fetch failed' errors for remote memory embeddings (including GitHub Copilot embeddings) in proxy environments (e.g. Clash TUN, corporate proxies).
Previously, without an explicit mode, fetchWithSsrFGuard defaulted to STRICT mode which performs local DNS pre-resolution via resolvePinnedHostnameWithPolicy(), failing in proxy environments where DNS must go through the proxy.
Fixes: #52162
Summary
Describe the problem and fix in 2–5 bullets:
If this PR fixes a plugin beta-release blocker, title it
fix(<plugin-id>): beta blocker - <summary>and link the matchingBeta blocker: <plugin-name> - <summary>issue labeledbeta-blocker. Contributors cannot label PRs, so the title is the PR-side signal for maintainers and automation.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
Root Cause (if applicable)
For bug fixes or regressions, explain why this happened, not just what changed. Otherwise write
N/A. If the cause is unclear, writeUnknown.Regression Test Plan (if applicable)
For bug fixes or regressions, name the smallest reliable test coverage that should catch this. Otherwise write
N/A.User-visible / Behavior Changes
List user-visible changes (including defaults/config).
If none, write
None.Diagram (if applicable)
For UI changes or non-trivial logic flows, include a small ASCII diagram reviewers can scan quickly. Otherwise write
N/A.Security Impact (required)
Yes/No)Yes/No)Yes/No)Yes/No)Yes/No)Yes, explain risk + mitigation:Repro + Verification
Environment
Steps
Expected
Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
Review Conversations
If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.
Compatibility / Migration
Yes/No)Yes/No)Yes/No)Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write
None.