Skip to content

fix(shared): block cloud-metadata hosts under default remote-image guard - #11755

Merged
diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.51from
santosraju99-hub:fix/remote-image-fetch-block-metadata-guard
Aug 30, 2026
Merged

diegosouzapw merged 1 commit into
cheaper-inference:release/v3.8.51from
santosraju99-hub:fix/remote-image-fetch-block-metadata-guard

Conversation

@santosraju99-hub

Copy link
Copy Markdown
Contributor

Summary

  • validateRemoteImageUrl() in src/shared/network/remoteImageFetch.ts only special-cased the "public-only" guard mode; the default "block-metadata" mode (getProviderOutboundGuard()'s local-first default) fell through to the unchecked parseOutboundUrl(), so remote-image/media fetches could reach cloud-metadata and link-local endpoints (SSRF → IAM-credential pivot) even though 3 other call sites of this guard mode already route it through parseAndValidateNonMetadataUrl().
  • Added the missing "block-metadata" branch, matching the existing pattern in safeOutboundFetch.ts.
  • Added regression tests for the default guard mode — every existing test in remote-image-fetch.test.ts passed guard: "public-only" explicitly, which is exactly why this branch went untested.

⚠️ base-red inherited: #9985

Test plan

  • node --import tsx/esm --test tests/unit/remote-image-fetch.test.ts tests/unit/remote-media-fetch.test.ts — 10/10 pass
  • npx eslint src/shared/network/remoteImageFetch.ts tests/unit/remote-image-fetch.test.ts — clean

validateRemoteImageUrl() only special-cased "public-only", so the
default "block-metadata" guard mode (getProviderOutboundGuard()'s
local-first default) fell through to the unchecked parseOutboundUrl(),
letting remote-image/media fetches reach cloud-metadata and
link-local endpoints (SSRF -> IAM-credential pivot). Route
"block-metadata" through parseAndValidateNonMetadataUrl(), matching
the other three call sites of that guard mode.

Add coverage for the default guard mode: every existing test passed
guard: "public-only" explicitly, which is why this branch went
untested.
@diegosouzapw
diegosouzapw changed the base branch from release/v3.8.50 to release/v3.8.51 August 30, 2026 06:41
@diegosouzapw
diegosouzapw merged commit faebf6d into cheaper-inference:release/v3.8.51 Aug 30, 2026
3 checks passed
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ard (cheaper-inference#11755)

Boarded in a combined worktree: typecheck:core, check:dashboard-typecheck, check:file-size, check:changelog-integrity, check:complexity, check:cognitive-complexity, check:cycles, check-deps all green; 10/10 focused tests pass. Real SSRF gap confirmed — the default "block-metadata" guard mode fell through to the unchecked parseOutboundUrl() while 3 other call sites of the same guard mode already routed through parseAndValidateNonMetadataUrl(). Good catch that the existing test suite only ever exercised "public-only" explicitly. Retargeted from the stale release/v3.8.50 base to release/v3.8.51. Thanks for closing a real cloud-metadata SSRF exposure.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants