fix(slack): prevent undici dispatcher leak to globalThis.fetch causing media download failure Markdown#62239
Conversation
Greptile SummaryStrips the undici Confidence Score: 5/5Safe 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 |
|
+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. |
8c40e16 to
bf910ef
Compare
obviyus
left a comment
There was a problem hiding this comment.
Reviewed latest changes; landing now.
eb3ef65 to
6e48619
Compare
…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.
…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.
…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>
…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>
…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>
Summary
extensions/slack/src/monitor/media.tswherecreateSlackMediaFetchis used.fetchWithSsrFGuard) creates an undici 8.xdispatcherand passes it in theinitobject to the customfetchImpl. InsidecreateSlackMediaFetch, theinitobject is destructured using...restand passed directly toglobalThis.fetch(Node's built-in fetch, which uses undici 7.x). The built-in fetch does not recognize the undici 8.x dispatcher'sonRequestStartmethod, throwing anInvalidArgumentErrorwhich is then silently swallowed by acatch { return null; }block inresolveSlackMedia.dispatcherproperty from theinitobject insidecreateSlackMediaFetchbefore passing...resttoglobalThis.fetch. This prevents the incompatible project-level undici dispatcher from leaking into the Node-bundled fetch runtime.extensions/slack/src/monitor/media.ts: StrippeddispatcherfrominitincreateSlackMediaFetch.extensions/slack/src/monitor/media.test.ts: Added a unit test to verifydispatcheris not forwarded toglobalThis.fetch.Reproduction
Risk / Mitigation
createSlackMediaFetchis only used for fetching from Slack's own CDN (files.slack.cometc.), 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)
Scope (select all touched areas)
Linked Issue/PR
Fixes #62218