Skip to content

fetchWithSsrFGuard strict mode resolves DNS locally before managed proxy #98925

Description

@sandl99

Summary

fetchWithSsrFGuard still performs local DNS pinning for STRICT fetches when OpenClaw's managed proxy lifecycle is active. In proxy-only sandboxes, local DNS can fail or disagree with the managed proxy resolver, so strict/default guarded fetches fail before the proxy can resolve the target and enforce its egress policy.

This is showing up as repeated downstream patches in NemoClaw/OpenShell integrations. The common shape is not one plugin-specific bug: many OpenClaw call paths either call withStrictGuardedFetchMode(...) directly or omit mode, which defaults to STRICT.

Current behavior

resolveGuardedFetchMode() defaults missing mode to STRICT.

In STRICT mode, fetchWithSsrFGuard() currently does this even when OPENCLAW_PROXY_ACTIVE=1 and proxy env vars are configured:

  1. Call resolvePinnedHostnameWithPolicy(...).
  2. That helper uses local dns.lookup(..., { all: true }).
  3. Only after local DNS succeeds does the fetch use the env proxy dispatcher.

That means proxy-only environments can fail with local DNS errors such as EAI_AGAIN / ENOTFOUND, or can reject fake/sentinel DNS results, before the managed proxy has a chance to resolve and apply policy.

Affected call paths observed downstream

Examples in current OpenClaw source:

  • src/cron/isolated-agent/model-preflight.runtime.ts: probeLocalProviderEndpoint() calls fetchWithSsrFGuard() for managed inference preflight with a policy but no mode, so it defaults to STRICT.
  • extensions/googlechat/src/auth.ts: fetchChatCerts() fetches Google Chat JWT verification certs with no mode or policy.
  • extensions/googlechat/src/api.ts: withGoogleChatResponse() is used by outbound sends, edits, uploads, media fetches, and reactions; it passes no mode or policy.
  • extensions/mattermost/src/mattermost/client.ts: the Mattermost guarded client wrapper passes a policy but no mode.
  • extensions/mattermost/src/mattermost/probe.ts: the Mattermost reachability probe passes a policy but no mode.
  • src/media/fetch.ts: media fetch can explicitly choose withStrictGuardedFetchMode(...).
  • src/agents/tools/web-guarded-fetch.ts: web tools explicitly choose strict mode unless useEnvProxy is enabled.

Downstream references

NemoClaw has had to patch or work around this repeatedly:

Related OpenClaw issue history shows the same class in individual call paths:

Expected behavior

When OpenClaw's managed proxy lifecycle is active (OPENCLAW_PROXY_ACTIVE=1) and the env HTTP proxy applies to the target URL, STRICT fetches should keep the pre-DNS SSRF checks that do not require local resolution:

  • URL parsing and scheme checks
  • hostname allowlist checks
  • blocked hostname checks
  • IP literal/private/internal/special-use checks
  • redirect revalidation

Then the request should use the managed env proxy dispatcher without local DNS pinning. The managed proxy should own DNS resolution and private-IP enforcement for the final target in this mode.

This matches the trust boundary already implied by the managed proxy lifecycle and avoids requiring every plugin/call path to remember to opt into TRUSTED_ENV_PROXY.

Security notes

The fix should not make ordinary STRICT mode proxy-aware just because HTTP_PROXY is present. It should be limited to the managed proxy lifecycle signal. It should also preserve direct-mode DNS pinning outside managed proxy mode.

Tests should prove:

  • default strict mode still ignores env proxy and pins local DNS
  • strict mode with OPENCLAW_PROXY_ACTIVE=1 and env proxy configured uses the env proxy without local lookup
  • blocked hostnames and private IP literals are still rejected before fetch
  • redirects still re-run the pre-DNS policy checks

Activity

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

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:fix-shape-clearClawSweeper found a clear likely implementation shape for this issue.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:message-lossChannel message delivery can be lost, duplicated, or misrouted.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maturity:stableBroken existing behavior primarily owned by an M4/M5 scorecard surface.

Type

No type

Fields

Priority

None yet

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions