openclaw - ✅(Solved) Fix [Bug]: allowRfc2544BenchmarkRange SSRF exemption does not cover IPv6 ULA addresses from fake-ip proxies [2 pull requests, 4 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#74351Fetched 2026-04-30 06:25:08
View on GitHub
Comments
4
Participants
3
Timeline
10
Reactions
2
Author
Timeline (top)
commented ×4cross-referenced ×2labeled ×2closed ×1

When fake-ip proxy tools (sing-box, Clash, Surge) are used, DNS returns both IPv4 addresses in the 198.18.0.0/15 (RFC 2544 benchmark) range AND IPv6 addresses in the fc00::/7 (Unique Local Address) range. Setting tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true correctly exempts the IPv4 range but the IPv6 ULA range remains unconditionally blocked, causing all web_fetch requests through fake-ip proxies to fail with "Blocked: resolves to private/internal/special-use IP address".

Root Cause

When fake-ip proxy tools (sing-box, Clash, Surge) are used, DNS returns both IPv4 addresses in the 198.18.0.0/15 (RFC 2544 benchmark) range AND IPv6 addresses in the fc00::/7 (Unique Local Address) range. Setting tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true correctly exempts the IPv4 range but the IPv6 ULA range remains unconditionally blocked, causing all web_fetch requests through fake-ip proxies to fail with "Blocked: resolves to private/internal/special-use IP address".

Fix Action

Fixed

PR fix notes

PR #74391: fix(ssrf): extend allowRfc2544BenchmarkRange to cover IPv6 uniqueLocal (fc00::/7) (#74351)

Description (problem / solution / changelog)

Summary

Fixes #74351.

Fake-ip proxy tools (sing-box, Clash, Surge) resolve foreign domains to both IPv4 198.18.0.0/15 (RFC 2544 range) and IPv6 fc00::/7 (uniqueLocal). Setting tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true correctly exempted the IPv4 side but isBlockedSpecialUseIpv6Address had no options parameter, so the IPv6 ULA range remained unconditionally blocked — causing web_fetch to fail for all foreign domains through fake-ip proxies.

Root cause: isPrivateIpAddress in src/infra/net/ssrf.ts called isBlockedSpecialUseIpv6Address(strictIp) without forwarding the policy options that were already threaded for IPv4.

Fix (2 files, backward-compatible):

  • src/shared/net/ip.ts: add Ipv6SpecialUseBlockOptions type (mirrors Ipv4SpecialUseBlockOptions); extend isBlockedSpecialUseIpv6Address with an optional options param (default {}); exempt uniqueLocal range when allowRfc2544BenchmarkRange === true
  • src/infra/net/ssrf.ts: add resolveIpv6SpecialUseBlockOptions helper (mirrors resolveIpv4SpecialUseBlockOptions); pass it to the IPv6 check

Pre-implement audit:

  1. Existing helper: reusing isBlockedSpecialUseIpv6Address — extended in-place, not duplicated ✓
  2. Shared helper callers: called in 2 places (ip.ts:237, ssrf.ts:186) — default {} preserves backward compatibility for both ✓
  3. Rival scan: no competing PR found for #74351 ✓

Test plan

  • isBlockedSpecialUseIpv6Address(fc00::1)true (default, no exemption)
  • isBlockedSpecialUseIpv6Address(fc00::1, { allowRfc2544BenchmarkRange: true })false (exempted)
  • isBlockedSpecialUseIpv6Address(::1, { allowRfc2544BenchmarkRange: true })true (loopback not exempted)
  • isPrivateIpAddress("fc00::1", { allowRfc2544BenchmarkRange: true })false (end-to-end via ssrf.ts)
  • isPrivateIpAddress("fc00::1")true (default still blocks)

🤖 Generated with Claude Code

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/infra/net/ssrf.ts (modified, +9/-1)
  • src/shared/net/ip.test.ts (modified, +21/-0)
  • src/shared/net/ip.ts (modified, +14/-1)

PR #74571: fix(ssrf): allow opt-in IPv6 unique-local exemption for fake-ip proxies

Description (problem / solution / changelog)

Closes #74351. AI-assisted, fully tested.

Sing-box / Clash / Surge fake-ip proxy stacks resolve foreign domains
to BOTH IPv4 198.18.0.0/15 AND IPv6 fc00::/7 simultaneously. Setting
`tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true` already
exempted the IPv4 leg, but the IPv6 ULA range stayed unconditionally
blocked, so every web_fetch through a fake-ip proxy still failed with
"Blocked: resolves to private/internal/special-use IP address".

## Approach

Adds a separate, opt-in `allowIpv6UniqueLocalRange` flag rather than
extending `allowRfc2544BenchmarkRange`'s semantics. Reasons:

- No silent behavior change for existing `allowRfc2544BenchmarkRange:
  true` users — their IPv6 surface stays exactly as restrictive as it
  was.
- Operators can mix and match: only IPv4 fake-ip ranges, only IPv6
  ULA, or both, depending on which proxy they actually run.
- Matches the issue's "Alternatively, provide a separate configuration
  option for exempting the IPv6 ULA range" suggestion, which is the
  conservative of the two presented options.

## Implementation

- `src/shared/net/ip.ts`: new `Ipv6SpecialUseBlockOptions` type;
  `isBlockedSpecialUseIpv6Address` now takes optional opts and returns
  false for `range() === "uniqueLocal"` only when
  `allowUniqueLocalRange === true`. Loopback (`::1`), unspecified
  (`::`), multicast (`ff00::/8`), discard, reserved, and the
  deprecated site-local `fec0::/10` keep their unconditional block —
  the exemption is scoped to ULA, not "any reserved IPv6 range".
- `src/infra/net/ssrf.ts`: new `allowIpv6UniqueLocalRange` field on
  `SsrFPolicy`, mirrored into `normalizeSsrFPolicyForComparison` so
  `isSameSsrFPolicy` participates in policy-cache invalidation. New
  `resolveIpv6SpecialUseBlockOptions` helper threaded through the
  `isPrivateIpAddress` path. The `media/parse.ts` call site keeps the
  default options (no opt-in), so media URL safety stays unchanged.

## Tests

- `src/shared/net/ip.test.ts` — 2 new unit tests covering the wrapper
  contract and the explicit "exemption is scoped to ULA only" invariant.
- `src/infra/net/ssrf.test.ts` — 7 new `it.each` rows covering the
  policy-threading: ULA blocked by default; exempt with the new flag;
  other reserved ranges still blocked; the new flag is independent of
  `allowRfc2544BenchmarkRange`. Plus a new `isSameSsrFPolicy` case
  asserting the new field participates in semantic equality.

`pnpm test src/shared/net/ip.test.ts src/infra/net/ssrf.test.ts
src/infra/net/ssrf.pinning.test.ts src/infra/net/fetch-guard.ssrf.test.ts`
— 108 passed across 4 files.

`pnpm exec oxfmt --check` — clean. `pnpm exec oxlint` — 0 warnings,
0 errors.

## AI-assisted PR

- [x] Mark as AI-assisted (Claude). Lightly tested via targeted Vitest
  shards on the four ssrf/ip-policy files; not exercised end-to-end
  against a live fake-ip proxy stack — operator confirmation welcome.
- [x] Confirm I understand what the code does: yes — the SSRF gate
  is delegating to `isBlockedSpecialUseIpv6Address`, and the new flag
  is a per-call, per-policy opt-out for one specific IPv6 range.

Closes #74351

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • docs/.generated/config-baseline.sha256 (modified, +3/-3)
  • docs/tools/web-fetch.md (modified, +8/-0)
  • packages/memory-host-sdk/src/host/ssrf-policy.ts (modified, +1/-0)
  • src/agents/tools/web-fetch.ssrf.test.ts (modified, +25/-1)
  • src/agents/tools/web-fetch.ts (modified, +12/-3)
  • src/config/schema.base.generated.ts (modified, +11/-0)
  • src/config/schema.help.ts (modified, +2/-0)
  • src/config/schema.labels.ts (modified, +1/-0)
  • src/config/schema.test.ts (modified, +2/-0)
  • src/config/types.tools.ts (modified, +2/-0)
  • src/config/zod-schema.agent-runtime.ts (modified, +1/-0)
  • src/infra/net/ssrf.test.ts (modified, +34/-0)
  • src/infra/net/ssrf.ts (modified, +18/-1)
  • src/plugin-sdk/ssrf-policy.test.ts (modified, +2/-0)
  • src/plugin-sdk/ssrf-policy.ts (modified, +3/-0)
  • src/shared/net/ip.test.ts (modified, +49/-0)
  • src/shared/net/ip.ts (modified, +28/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Beta release blocker

No

Summary

When fake-ip proxy tools (sing-box, Clash, Surge) are used, DNS returns both IPv4 addresses in the 198.18.0.0/15 (RFC 2544 benchmark) range AND IPv6 addresses in the fc00::/7 (Unique Local Address) range. Setting tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true correctly exempts the IPv4 range but the IPv6 ULA range remains unconditionally blocked, causing all web_fetch requests through fake-ip proxies to fail with "Blocked: resolves to private/internal/special-use IP address".

Steps to reproduce

  1. Configure a fake-ip proxy (sing-box, Clash, Surge, etc.) that resolves foreign domains to both IPv4 198.18.0.0/15 and IPv6 fc00::/7 addresses
  2. Set tools.web.fetch.ssrfPolicy.allowRfc2544BenchmarkRange: true in openclaw.json
  3. Run web_fetch against any foreign domain (e.g., https://httpbin.org/ip)
  4. Observe "Blocked: resolves to private/internal/special-use IP address"

Expected behavior

allowRfc2544BenchmarkRange: true should exempt ALL fake-ip proxy addresses from SSRF blocking, including both IPv4 198.18.0.0/15 (RFC 2544 benchmark) AND IPv6 fc00::/7 (Unique Local Address) ranges, since both are commonly used by fake-ip proxy implementations. Alternatively, provide a separate configuration option for exempting the IPv6 ULA range.

Actual behavior

web_fetch returns "Blocked: resolves to private/internal/special-use IP address" for ALL foreign domains when using fake-ip proxy, even with allowRfc2544BenchmarkRange: true. DNS lookup confirms both A (198.18.0.x) and AAAA (fc00::x) records are returned. The IPv4 addresses pass the exemption, but the IPv6 ULA addresses are unconditionally blocked by isBlockedSpecialUseIpv6Address() in ip-zu3JmZlh.js.

OpenClaw version

2026.4.26

Operating system

Ubuntu 24.04

Install method

npm global

Model

cucoud/DeepSeek-V4-Pro

Provider / routing chain

openclaw -> ds2api -> sing-box fakeip proxy

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

TL;DR

The issue can be fixed by adding a separate configuration option to exempt the IPv6 ULA range from SSRF blocking.

Guidance

  • The current allowRfc2544BenchmarkRange option only exempts the IPv4 range, and a separate option is needed for the IPv6 ULA range.
  • To verify the issue, check the DNS lookup results to confirm that both A and AAAA records are returned, and the IPv4 addresses pass the exemption while the IPv6 ULA addresses are blocked.
  • A potential workaround is to modify the isBlockedSpecialUseIpv6Address() function in ip-zu3JmZlh.js to exempt the IPv6 ULA range, but this may require additional configuration options.
  • Consider adding a new configuration option, such as allowUniqueLocalAddressRange, to exempt the IPv6 ULA range from SSRF blocking.

Example

No code example is provided as it would require modifying the ip-zu3JmZlh.js file, which is not recommended without further guidance.

Notes

The issue is specific to the OpenClaw version 2026.4.26 and the sing-box fake-ip proxy, and the solution may not apply to other versions or configurations.

Recommendation

Apply a workaround by modifying the isBlockedSpecialUseIpv6Address() function or adding a new configuration option to exempt the IPv6 ULA range, as upgrading to a fixed version is not available.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

allowRfc2544BenchmarkRange: true should exempt ALL fake-ip proxy addresses from SSRF blocking, including both IPv4 198.18.0.0/15 (RFC 2544 benchmark) AND IPv6 fc00::/7 (Unique Local Address) ranges, since both are commonly used by fake-ip proxy implementations. Alternatively, provide a separate configuration option for exempting the IPv6 ULA range.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: allowRfc2544BenchmarkRange SSRF exemption does not cover IPv6 ULA addresses from fake-ip proxies [2 pull requests, 4 comments, 3 participants]