Skip to content

fix(discord): add allowRfc2544BenchmarkRange to attachment and sticker downloads#26436

Open
cncoder wants to merge 2 commits intoopenclaw:mainfrom
cncoder:fix/discord-ssrf-rfc2544
Open

fix(discord): add allowRfc2544BenchmarkRange to attachment and sticker downloads#26436
cncoder wants to merge 2 commits intoopenclaw:mainfrom
cncoder:fix/discord-ssrf-rfc2544

Conversation

@cncoder
Copy link

@cncoder cncoder commented Feb 25, 2026

Summary

  • Problem: Discord attachment and sticker downloads fail when OpenClaw runs behind a local proxy with virtual-IP DNS mode. These proxies resolve external domains like cdn.discordapp.com to the 198.18.0.0/15 range (RFC 2544 benchmark addresses), which the SSRF guard blocks since 2026.2.22.
  • Why it matters: Voice messages, images, files, and stickers are silently dropped for all affected Discord users. 60+ GitHub issues reported.
  • What changed: Added ssrfPolicy: { allowRfc2544BenchmarkRange: true } to two Discord-specific fetchRemoteMedia call sites in message-utils.ts, plus updated test assertions.
  • What did NOT change (scope boundary): No changes to the generic media-understanding layer (attachments.ts), no changes to SSRF guard logic itself, no new config options. Only the Discord channel module is touched, following the same pattern already in Telegram (delivery.ts:43).

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

Discord attachments (voice messages, images, files, stickers) now download correctly when the host resolves CDN domains to RFC 2544 benchmark addresses (198.18.0.0/15), typically caused by local proxies with virtual-IP DNS mode.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No — same fetchRemoteMedia calls, just with relaxed SSRF policy for the RFC 2544 range
  • Command/tool execution surface changed? No
  • Data access scope changed? No
  • Note: allowRfc2544BenchmarkRange is already used in the Telegram module (src/telegram/bot/delivery.ts:43). This PR extends the same policy to Discord. The RFC 2544 range (198.18.0.0/15) is not routable on the public internet — it only appears when a local proxy assigns virtual IPs from this range.

Repro + Verification

Environment

  • OS: macOS 15.5 (Apple Silicon M4)
  • Runtime: Node.js v24.3.0
  • Model/provider: Claude Opus 4.6 via AWS Bedrock
  • Integration/channel: Discord (DM channel)
  • Relevant config: Local proxy with virtual-IP DNS mode (198.18.0.0/15), OpenClaw 2026.2.23

Steps

  1. Run a local proxy with virtual-IP DNS mode (assigns 198.18.0.0/15 range)
  2. Send a voice message or image attachment via Discord DM to OpenClaw bot
  3. Observe gateway error log

Expected

Attachment downloads successfully and is processed (e.g., voice → ASR transcription → reply).

Actual (before fix)

[security] blocked URL fetch (url-fetch)
  target=https://cdn.discordapp.com/attachments/.../voice-message.ogg
  reason=Blocked: resolves to private/internal/special-use IP address

Evidence

  • Failing log before: [security] blocked URL fetch (url-fetch) target=https://cdn.discordapp.com/attachments/.../voice-message.ogg reason=Blocked: resolves to private/internal/special-use IP address
  • Passing after: Voice message downloaded → transcribed via ASR → correct reply sent back to Discord. Tested with 5 separate voice messages, all successful.
  • Test results: npx vitest run src/discord/monitor/message-utils.test.ts — 15/15 passed
  • Type check: npx tsc --noEmit — zero errors

Human Verification (required)

  • Verified scenarios: Sent multiple Discord voice messages through a local proxy with virtual-IP DNS mode → all downloaded successfully → ASR transcription → correct replies.
  • Edge cases checked: Verified Telegram module already has this flag and works correctly. Confirmed media-understanding/attachments.ts reads local file after Discord downloads it (does not re-download), so does not need this fix.
  • What I did not verify: Sticker downloads not tested end-to-end (no sticker test setup), but the code path is identical to attachments.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert: Revert this single commit. Or remove the two ssrfPolicy lines from src/discord/monitor/message-utils.ts.
  • Files to restore: src/discord/monitor/message-utils.ts, src/discord/monitor/message-utils.test.ts
  • Known bad symptoms: If RFC 2544 addresses were somehow used maliciously (extremely unlikely — not routable on the public internet), Discord could fetch from unintended local services. Mitigation: only allowRfc2544BenchmarkRange is relaxed; all other private/internal ranges remain blocked.

Risks and Mitigations

  • Risk: Relaxing SSRF for the RFC 2544 range could theoretically allow fetching from services bound to 198.18.x.x on the local machine.
  • Mitigation: RFC 2544 (198.18.0.0/15) is a benchmark-only range per RFC 2544, not used for real services. The Telegram module already sets this flag without issue. Only Discord attachment/sticker URLs are affected (not arbitrary user-supplied URLs).

🤖 AI-assisted: Analysis, fix, and PR developed with OpenClaw + Claude Code. Fully tested and manually verified by human.

Greptile Summary

Added ssrfPolicy: { allowRfc2544BenchmarkRange: true } to Discord attachment and sticker downloads to fix failures when OpenClaw runs behind local proxies with virtual-IP DNS mode (resolves cdn.discordapp.com to RFC 2544 benchmark range 198.18.0.0/15).

  • Applies the same SSRF policy pattern already used in Telegram module (src/telegram/bot/delivery.ts:43)
  • Fixes two call sites: appendResolvedMediaFromAttachments and appendResolvedMediaFromStickers in src/discord/monitor/message-utils.ts
  • Test assertions updated to match new parameter

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation correctly mirrors the existing Telegram pattern for handling RFC 2544 addresses. The fix is narrowly scoped to only Discord attachment and sticker downloads, uses an established API, and includes corresponding test updates. The RFC 2544 range (198.18.0.0/15) is a benchmark-only range per RFC 2544 that only appears when local proxies use virtual-IP DNS mode, making this a legitimate use case with no security implications for production environments.
  • No files require special attention

Last reviewed commit: 7148456

(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!

…r downloads

Discord attachment and sticker downloads fail when the host uses a local
proxy with virtual-IP DNS mode (198.18.0.0/15, RFC 2544 benchmark range).
The SSRF guard blocks these addresses by default.

This follows the same pattern already applied in the Telegram module
(src/telegram/bot/delivery.ts:43) by passing ssrfPolicy with
allowRfc2544BenchmarkRange: true to fetchRemoteMedia calls.

Only Discord-specific call sites are modified to keep the fix scoped:
- appendResolvedMediaFromAttachments (voice messages, images, files)
- appendResolvedMediaFromStickers

Updated corresponding test assertions to expect the new ssrfPolicy parameter.

Fixes openclaw#25215
Related: openclaw#25086, openclaw#24973, openclaw#24454
@openclaw-barnacle openclaw-barnacle bot added channel: discord Channel integration: discord size: XS labels Feb 25, 2026
@ArcticLampyrid
Copy link

I don’t think we should add special definitions for every RFC address block.

It would be better to simply allow users to define their own list of CIDR blocks to block.

@ArcticLampyrid
Copy link

Additionally, other reasonable contexts (for example, accessing GitHub via web_fetch) should also be allowed.

@openclaw-barnacle
Copy link

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle bot added the stale Marked as stale due to inactivity label Mar 3, 2026
@thewilloftheshadow
Copy link
Member

Superseded by #33275: #33275

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

Labels

channel: discord Channel integration: discord size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

web_fetch SSRF check blocks Clash/mihomo fake-ip range (198.18.0.0/15) — regression in 2026.2.22-2

3 participants