Skip to content

security: add remotePatterns validation to /cdn-cgi/image/ handler - #1330

Open
Ashutosh0x wants to merge 1 commit into
opennextjs:mainfrom
Ashutosh0x:security/validate-cdn-cgi-image-urls
Open

security: add remotePatterns validation to /cdn-cgi/image/ handler#1330
Ashutosh0x wants to merge 1 commit into
opennextjs:mainfrom
Ashutosh0x:security/validate-cdn-cgi-image-urls

Conversation

@Ashutosh0x

@Ashutosh0x Ashutosh0x commented Aug 6, 2026

Copy link
Copy Markdown

Summary

The handleCdnCgiImageRequest() handler in images.ts performs etch(parseResult.url) with zero URL validation, unlike handleImageRequest() which validates URLs via hasRemoteMatch() against
emotePatterns.

This was the root cause of CVE-2026-3125. The original patch blocked the backslash path normalization bypass at the edge, but did NOT add code-level validation to the handler.

The Problem

handleCdnCgiImageRequest() is documented as development-only (worker.ts L27-28), but:

  1. The handler is compiled into ALL production builds via compileImages()
  2. Internal service binding requests (WORKER_SELF_REFERENCE.fetch()) bypass edge interception and reach the handler directly
  3. The handler performs etch(parseResult.url) on ANY https:// URL without validation

The Fix

This patch adds
emotePatterns validation to handleCdnCgiImageRequest(), matching the validation already performed by handleImageRequest() via hasRemoteMatch(). Remote URLs that don't match the configured patterns are rejected with a 400 response.

Related


Open in Devin Review

@changeset-bot

changeset-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9d417ed

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@opennextjs/cloudflare Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment on lines +216 to +218
if (!hasRemoteMatch(__IMAGES_REMOTE_PATTERNS__, parsedUrl)) {
return new Response('"url" parameter is not allowed', { status: 400 });
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Remote images stop working in local development for apps using the Cloudflare image loader

Remote image URLs served through the development image handler are now rejected (hasRemoteMatch(...) at packages/cloudflare/src/cli/templates/images.ts:216) unless they are listed in the app's remote image allow-list, so images that load fine in production show as broken during development.
Impact: Developers using the Cloudflare image loader without configuring an allow-list see 400 errors and broken remote images locally, while the same pages work once deployed.

Why dev/prod parity is broken by the new allow-list check

/cdn-cgi/image/... requests never reach the worker in production (packages/cloudflare/src/cli/templates/worker.ts:27-30); Cloudflare's edge fetches the origin image with no remotePatterns check. The handler exists specifically to emulate that edge behavior in dev (changelog entry "make dev /cdn-cgi/image behaves like prod for consistency").

When a custom image loader (e.g. the Cloudflare loader) is used, Next.js does not require images.remotePatterns to be configured, so __IMAGES_REMOTE_PATTERNS__ (populated from the images manifest in packages/cloudflare/src/cli/build/open-next/compile-images.ts:21) is frequently []. With an empty list hasRemoteMatch always returns false (packages/cloudflare/src/cli/templates/images.ts:727-735), so every absolute-URL image request returns "url" parameter is not allowed in dev while working in prod.

If the goal is defense-in-depth for service-binding calls, consider only rejecting when patterns are configured, or gating the check so it does not regress the dev emulation path.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread .changeset/fix-cdn-cgi-image-ssrf.md Outdated
"@opennextjs/cloudflare": patch
---

security: add remotePatterns validation to /cdn-cgi/image/ handler

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changeset uses a change type that is not allowed by the contribution rules

The new changeset entry starts with security: (.changeset/fix-cdn-cgi-image-ssrf.md:5), but the repository requires one of feature | fix | refactor | docs | chore, so the generated changelog will not follow the project's documented format.
Impact: The released changelog entry is inconsistent with every other entry in the project.

Rule reference

AGENTS.md ("Changesets") and CONTRIBUTING.md ("Changeset message format") both state the TYPE must be one of feature, fix, refactor, docs or chore.

Suggested change
security: add remotePatterns validation to /cdn-cgi/image/ handler
fix: add remotePatterns validation to /cdn-cgi/image/ handler
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@Ashutosh0x
Ashutosh0x force-pushed the security/validate-cdn-cgi-image-urls branch from a4fc348 to 9d417ed Compare August 6, 2026 20:10
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.

1 participant