Skip to content

fix(slack): prevent undici dispatcher leak to globalThis.fetch causing media download failure Markdown#62239

Merged
obviyus merged 3 commits intoopenclaw:mainfrom
openperf:fix/slack-media-ssrf-dispatcher
Apr 7, 2026
Merged

fix(slack): prevent undici dispatcher leak to globalThis.fetch causing media download failure Markdown#62239
obviyus merged 3 commits intoopenclaw:mainfrom
openperf:fix/slack-media-ssrf-dispatcher

Conversation

@openperf
Copy link
Copy Markdown
Member

@openperf openperf commented Apr 7, 2026

Summary

  • Problem: Slack file and image attachments fail to download silently. The issue occurs in extensions/slack/src/monitor/media.ts where createSlackMediaFetch is used.
  • Root Cause: The SSRF guard (fetchWithSsrFGuard) creates an undici 8.x dispatcher and passes it in the init object to the custom fetchImpl. Inside createSlackMediaFetch, the init object is destructured using ...rest and passed directly to globalThis.fetch (Node's built-in fetch, which uses undici 7.x). The built-in fetch does not recognize the undici 8.x dispatcher's onRequestStart method, throwing an InvalidArgumentError which is then silently swallowed by a catch { return null; } block in resolveSlackMedia.
  • Fix: Explicitly destructure and exclude the dispatcher property from the init object inside createSlackMediaFetch before passing ...rest to globalThis.fetch. This prevents the incompatible project-level undici dispatcher from leaking into the Node-bundled fetch runtime.
  • What changed:
    • extensions/slack/src/monitor/media.ts: Stripped dispatcher from init in createSlackMediaFetch.
    • extensions/slack/src/monitor/media.test.ts: Added a unit test to verify dispatcher is not forwarded to globalThis.fetch.
  • What did NOT change (scope boundary): The SSRF guard logic itself, other extensions' fetch implementations, and the general Slack media resolution flow remain unchanged.

Reproduction

  1. Configure a Slack bot with the OpenClaw gateway.
  2. Send a message containing an image or file attachment in a monitored Slack channel.
  3. Observe that the bot fails to download the attachment (no placeholder or file is saved), and no error is logged.

Risk / Mitigation

  • Risk: The SSRF guard relies on the dispatcher to enforce network policies. Stripping it might bypass the SSRF protection for Slack media downloads.
  • Mitigation: This is safe because createSlackMediaFetch is only used for fetching from Slack's own CDN (files.slack.com etc.), which are trusted external URLs. The SSRF guard's primary purpose is to prevent access to internal/private networks, which is not a risk when fetching from known Slack domains. The added unit test ensures the dispatcher is correctly stripped without affecting the rest of the request initialization.

Change Type (select all)

  • Bug fix

Scope (select all touched areas)

  • Gateway
  • Slack Extension

Linked Issue/PR

Fixes #62218

@openclaw-barnacle openclaw-barnacle Bot added channel: slack Channel integration: slack size: XS labels Apr 7, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 7, 2026

Greptile Summary

Strips the undici dispatcher from the init object inside createSlackMediaFetch before forwarding to globalThis.fetch, fixing silent Slack media download failures. The SSRF guard's undici 8.x dispatcher was leaking into Node's built-in fetch (which uses a different undici runtime), causing an InvalidArgumentError that was silently swallowed. SSRF policy enforcement remains intact at the fetchWithSsrFGuard layer — the hostname allowlist and pinned DNS resolution both run before the request reaches the custom fetch function. A regression test is included that verifies the dispatcher is not forwarded.

Confidence Score: 5/5

Safe to merge — the fix is minimal, well-scoped, and SSRF policy is still enforced at the fetch-guard layer before the dispatcher is used.

No P0 or P1 findings. The fix correctly strips the incompatible dispatcher at exactly the right boundary, SSRF protection is preserved via the allowlist and pinned-DNS checks in fetchWithSsrFGuard, and the regression test meaningfully validates the fix.

No files require special attention.

Reviews (1): Last reviewed commit: "fix(slack ): prevent undici dispatcher l..." | Re-trigger Greptile

@mjamiv
Copy link
Copy Markdown
Contributor

mjamiv commented Apr 7, 2026

+1 from production — we confirmed this exact failure across 4 OpenShell sandbox agents on Node 22.22.1 with undici 8.0.2. All Slack file downloads silently broken since 2026.4.5.

Detailed root cause analysis and workaround posted on the companion PR #62241. Both PRs address the same underlying issue — the npm undici dispatcher leaking into Node's built-in fetch.

Copy link
Copy Markdown
Contributor

@obviyus obviyus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed latest changes; landing now.

@obviyus obviyus force-pushed the fix/slack-media-ssrf-dispatcher branch from eb3ef65 to 6e48619 Compare April 7, 2026 05:45
@obviyus obviyus merged commit e8fb140 into openclaw:main Apr 7, 2026
7 checks passed
@obviyus
Copy link
Copy Markdown
Contributor

obviyus commented Apr 7, 2026

Landed on main.

Thanks @openperf.

coletebou added a commit to coletebou/openclaw that referenced this pull request Apr 13, 2026
…hment downloads on Node 24+

The SSRF guard pinned-DNS dispatcher is an undici 8.x Agent, but Node 24
built-in globalThis.fetch uses undici 7.x internally. Passing the 8.x
dispatcher to the native fetch causes 'invalid onRequestStart method'
errors, breaking all BlueBubbles attachment downloads.

Route through fetchWithRuntimeDispatcher (bundled undici own fetch) when
a dispatcher is present, matching the approach used by the Slack extension
(openclaw#62239). This preserves SSRF DNS pinning instead of stripping the
dispatcher entirely.
coletebou added a commit to coletebou/openclaw that referenced this pull request Apr 13, 2026
…hment downloads on Node 24+

The SSRF guard pinned-DNS dispatcher is an undici 8.x Agent, but Node 24
built-in globalThis.fetch uses undici 7.x internally. Passing the 8.x
dispatcher to native fetch causes 'invalid onRequestStart method' errors,
breaking all BlueBubbles attachment downloads.

Route through fetchWithRuntimeDispatcher (bundled undici own fetch) when
a dispatcher is present, matching the Slack extension (openclaw#62239). Preserves
SSRF DNS pinning, forwards opts.timeoutMs via AbortSignal.timeout (default
10s), and honours test-installed globalThis.fetch mocks via isMockedFetch
guard.
lovewanwan pushed a commit to lovewanwan/openclaw that referenced this pull request Apr 28, 2026
…openperf)

* fix(slack ): prevent undici dispatcher leak to globalThis.fetch causing media download failure

* fix(slack): preserve guarded media transport

* fix: preserve Slack guarded media transport (openclaw#62239) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
ogt-redknie pushed a commit to ogt-redknie/OPENX that referenced this pull request May 2, 2026
…openperf)

* fix(slack ): prevent undici dispatcher leak to globalThis.fetch causing media download failure

* fix(slack): preserve guarded media transport

* fix: preserve Slack guarded media transport (openclaw#62239) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request May 9, 2026
…openperf)

* fix(slack ): prevent undici dispatcher leak to globalThis.fetch causing media download failure

* fix(slack): preserve guarded media transport

* fix: preserve Slack guarded media transport (openclaw#62239) (thanks @openperf)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: slack Channel integration: slack maintainer Maintainer-authored PR size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Slack inbound file attachments silently fail in 2026.4.5 (undici 8.x SSRF dispatcher incompatible with Node built-in fetch)

3 participants