Skip to content

fix(net): respect HTTP proxy env vars in web_fetch SSRF dispatcher#24625

Closed
makew0rld wants to merge 1 commit intoopenclaw:mainfrom
eqtylab:fix/web-fetch-proxy-support
Closed

fix(net): respect HTTP proxy env vars in web_fetch SSRF dispatcher#24625
makew0rld wants to merge 1 commit intoopenclaw:mainfrom
eqtylab:fix/web-fetch-proxy-support

Conversation

@makew0rld
Copy link

@makew0rld makew0rld commented Feb 23, 2026

Summary

  • Problem: web_fetch (and all fetchWithSsrFGuard callers) ignore HTTP_PROXY/HTTPS_PROXY env vars because createPinnedDispatcher creates a plain undici Agent that overrides the global dispatcher, bypassing all proxy settings.
  • Why it matters: Users behind corporate proxies, VPNs, or restricted networks cannot use web_fetch at all, even when proxy env vars are correctly configured and work for other HTTP clients (e.g., Anthropic API calls, curl).
  • What changed: createPinnedDispatcher now detects proxy env vars and returns an undici EnvHttpProxyAgent (which reads HTTP_PROXY, HTTPS_PROXY, NO_PROXY automatically) instead of a plain Agent. Added 4 tests covering all env var variants.
  • What did NOT change (scope boundary): SSRF hostname/IP pre-checks in resolvePinnedHostnameWithPolicy still run before the dispatcher is created. The non-proxy code path (plain Agent with DNS pinning) is untouched. web_search bare fetch() calls are not in scope.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

web_fetch (and other tools using fetchWithSsrFGuard) now route through the user's configured HTTP proxy when HTTP_PROXY/HTTPS_PROXY (or lowercase variants) env vars are set. NO_PROXY is also respected via EnvHttpProxyAgent.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? Yes — when proxy env vars are set, web_fetch HTTP requests are routed through the proxy instead of directly. This is user-initiated behavior (requires explicit proxy env var configuration).
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • Risk + mitigation: DNS pinning is skipped when proxying (the proxy handles DNS). SSRF hostname and resolved-IP pre-checks in resolvePinnedHostnameWithPolicy still execute before the dispatcher is created, maintaining protection against requests to private/internal addresses. The proxy path only activates when the user has explicitly configured proxy env vars.

Repro + Verification

Environment

  • OS: Linux (tested on VM behind HTTP proxy)
  • Runtime/container: Node.js 22+
  • Integration/channel: N/A (agent tool)
  • Relevant config: HTTP_PROXY=http://proxy:8080, HTTPS_PROXY=http://proxy:8080

Proxy setup

For systemd-managed OpenClaw (e.g. gateway running as a service), env vars can be set globally via a drop-in override:

sudo systemctl edit openclaw-gateway

Then add:

[Service]
Environment=HTTP_PROXY=http://proxy-host:port
Environment=HTTPS_PROXY=http://proxy-host:port
Environment=NODE_EXTRA_CA_CERTS=/path/to/ca.pem

Then sudo systemctl daemon-reload && sudo systemctl restart openclaw-gateway.

Note: it is unclear whether setting proxy vars in openclaw.json config is supported — the env var approach above is the tested path.

Steps

  1. Set HTTP_PROXY/HTTPS_PROXY env vars pointing to a proxy server (via systemd override, shell, etc.)
  2. Run OpenClaw gateway with these env vars
  3. Use web_fetch to fetch any URL

Expected

Request is routed through the configured proxy.

Actual (before fix)

Request bypasses proxy — the custom undici Agent dispatcher overrides global proxy settings.

Evidence

  • Failing test/log before + passing after
  • 4 new unit tests verify EnvHttpProxyAgent is used when proxy env vars are set, and plain Agent when not
  • Manually verified on a VM behind an HTTP proxy: web_fetch requests now appear in proxy logs

Human Verification (required)

  • Verified scenarios: web_fetch successfully routes through proxy on a VM with HTTPS_PROXY set via systemd override; all existing SSRF tests pass (29 tests across 3 test files)
  • Edge cases checked: lowercase env vars (http_proxy), missing env vars (falls back to plain Agent), mixed env var configurations
  • What you did not verify: NO_PROXY exclusion behavior (delegated to undici's EnvHttpProxyAgent implementation), web_search tool (uses bare fetch(), out of scope)

Compatibility / Migration

  • Backward compatible? Yes — no behavior change when proxy env vars are not set
  • Config/env changes? No — reads existing standard env vars
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Unset HTTP_PROXY/HTTPS_PROXY env vars to fall back to plain Agent (existing behavior)
  • Files/config to restore: src/infra/net/ssrf.ts
  • Known bad symptoms reviewers should watch for: web_fetch failing with connection errors when proxy env vars are set but proxy is unreachable

Risks and Mitigations

  • Risk: DNS pinning is bypassed when using a proxy, which widens the TOCTOU window for DNS rebinding.
    • Mitigation: SSRF hostname and resolved-IP pre-checks still execute before the dispatcher is created. The proxy itself performs DNS resolution, and the user has explicitly opted into proxy routing.

AI-assisted: This PR was developed with Claude Code (Opus). Fully tested on a real proxy setup. I understand what the code does.

Greptile Summary

Adds HTTP proxy support to web_fetch by detecting HTTP_PROXY/HTTPS_PROXY env vars in createPinnedDispatcher and returning undici's EnvHttpProxyAgent instead of a plain Agent. SSRF hostname/IP pre-checks in resolvePinnedHostnameWithPolicy still execute before dispatcher creation. DNS pinning is skipped when proxying (proxy handles DNS resolution). Test coverage includes all four proxy env var variants (uppercase/lowercase HTTP_PROXY/HTTPS_PROXY) plus the no-proxy fallback path.

Confidence Score: 4/5

  • Safe to merge with low risk — backward compatible, explicit user opt-in via env vars, SSRF pre-checks maintained
  • Implementation is clean with proper test coverage. SSRF protections execute before proxy dispatcher creation. DNS pinning bypass when proxying is documented and acceptable (proxy performs DNS). Only concern is NO_PROXY behavior is untested but delegated to undici's implementation.
  • No files require special attention

Last reviewed commit: 26024cf

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

When HTTP_PROXY/HTTPS_PROXY env vars are set, createPinnedDispatcher now
returns an undici EnvHttpProxyAgent instead of a plain Agent. This allows
web_fetch (and all fetchWithSsrFGuard callers) to route through the
configured proxy. DNS pinning is skipped when proxying since the proxy
handles resolution; SSRF hostname/IP pre-checks still run beforehand.

Closes openclaw#2102
Related openclaw#8534

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@steipete
Copy link
Contributor

Closing as AI-assisted stale-fix triage.

Linked issue #2102 ("[Bug]: HTTP_PROXY is ignored") is currently CLOSED and was closed on 2026-02-24T04:30:36Z with state reason NOT_PLANNED.
Given that issue state, this fix PR is no longer needed in the active queue and is being closed as stale.

If the underlying bug is still reproducible on current main, please reopen this PR (or open a new focused fix PR) and reference both #2102 and #24625 for fast re-triage.

@steipete
Copy link
Contributor

Closed after AI-assisted stale-fix triage (closed issue duplicate/stale fix).

@steipete steipete closed this Feb 24, 2026
makew0rld added a commit to eqtylab/openclaw that referenced this pull request Feb 24, 2026
When HTTP_PROXY/HTTPS_PROXY env vars are set, createPinnedDispatcher now
returns an undici EnvHttpProxyAgent instead of a plain Agent. This allows
web_fetch (and all fetchWithSsrFGuard callers) to route through the
configured proxy. DNS pinning is skipped when proxying since the proxy
handles resolution; SSRF hostname/IP pre-checks still run beforehand.

Related openclaw#2102
Related openclaw#8534
Supersedes openclaw#24625

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@makew0rld
Copy link
Author

Reopened as #25573

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: HTTP_PROXY is ignored

2 participants