CVE-2026-94483: the Next.js image optimizer SSRF, who is affected and how to fix it

CVE-2026-94483 is a server-side request forgery (SSRF) in the Next.js image optimizer, fixed in 16.3.8. On Next.js 16.0.0 to 16.3.7, a remote image URL that matches images.remotePatterns can resolve to a private IP address after it passes the checks, so your server fetches from your internal network. Apps without remotePatterns are not affected.

The team behind Keybrum's attacksUpdated 10 min read
CVE-2026-94483high · CVSS 8.3
Component
Next.js Image Optimization (next/image, /_next/image) (next)
Affected
Next.js 16.0.0 to 16.3.7, when images.remotePatterns is configured
Fixed in
16.3.8. Next.js 15 and older are not listed as affected. Latest releases: 16.4.5 and 15.5.29
Published
October 2, 2026
Exploited in the wild
No public report
Keybrum tests your live app for this one, and proves it if it works.

In short

  • Affected: next 16.0.0 to 16.3.7 with images.remotePatterns set. 16.3.8 fixes it; no 15.x or older version is listed.
  • The attacker needs control over DNS for a hostname your allow-list accepts. Patterns that accept any host make that easy.
  • GitHub, the CNA, scores it 8.3 High (CVSS 4.0); NVD scores it 6.5 Medium (CVSS 3.1). It is not in CISA's KEV catalog as of 8 November 2026, and no source we found reports exploitation.
  • Fix: upgrade to 16.3.8 or later (16.4.5 is current), then trim remotePatterns to exact hosts and block your server's outbound traffic to private ranges.
On this page

What CVE-2026-94483 is, in plain words

When a page shows a remote picture with next/image, the browser asks your own server for /_next/image?url=..., and the Next.js image optimizer fetches the original, resizes it and serves a smaller copy. A server that fetches URLs on request is the classic target for server-side request forgery (SSRF): getting a server to send requests for you, to places you cannot reach yourself, such as its private network.

Next.js has two guards. The first is the allow-list in images.remotePatterns: a URL that matches no pattern gets 400 Bad Request with the text "url" parameter is not allowed. The second arrived in 16.0.0: the optimizer refuses images from local and private IP addresses unless you set images.dangerouslyAllowLocalIP: true, which the Next.js docs advise against for most users because it could let malicious users reach content on your internal network.

CVE-2026-94483 gets around the second guard. Per the advisory, from 16.0.0 until 16.3.8 the optimizer "can follow attacker-controlled DNS resolution" for a URL that matches remotePatterns, so the fetch reaches a private IP address after the URL has passed the checks. CyCognito's analysis explains the mechanism: the check and the fetch looked up the hostname separately, so a hostname whose DNS the attacker controls can answer the check with a public address and the fetch with an internal one, a trick called DNS rebinding. The fix, a commit titled "Pin DNS resolution when fetching external images", connects to the address that passed the check instead of looking the name up a second time.

Severity and exploitation status

The two official scores differ because they use different CVSS versions. The facts box uses the score of the CNA, the organisation that assigned the CVE: GitHub, for the Next.js advisory.

SourceRatingDetail
GitHub, the CNA (CVSS 4.0)8.3 HighAV:N/AC:H/AT:P/PR:N/UI:N/VC:H/VI:L/VA:N: no account needed, high complexity, a precondition must be present
NVD (CVSS 3.1)6.5 MediumAV:N/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:N: same reading
CISA (SSVC, 6 October 2026)Exploitation: noneNot automatable, partial technical impact
CISA KEV catalogNot listedCatalog version 2026.11.06, checked 8 November 2026
FIRST EPSS0.33%Probability of exploitation in the next 30 days, 26th percentile, on 7 November 2026
SOCRadar CVE Radar1 public proof of conceptOne public PoC repository reported, none marked weaponized; active exploitation not confirmed

The high complexity is the precondition: control of DNS for a hostname your allow-list accepts. Your patterns decide how hard that is, so the next section matters more than the score. We found no public report of exploitation, but a proof of concept is listed in public, so treat the technique as known.

Who is affected

Your app is exposed when all four of these are true:

  1. It runs next 16.0.0 to 16.3.7.
  2. images.remotePatterns is set in next.config. The advisory is explicit: apps without it are not affected.
  3. Your own Next.js server runs the optimizer: next start, the standalone output in a Docker image, or any Node server you host.
  4. At least one allowed hostname has DNS that someone other than you can set or change.

The fourth point is where allow-lists differ. A pattern for your own domain, or a storage host your provider runs, is hard to abuse. A pattern that accepts any host lets anyone who owns a domain meet the precondition, and a wildcard such as **.some-platform.app does the same wherever strangers can create subdomains. The Next.js docs also warn that leaving out protocol, port, pathname or search implies the wildcard **, which "may allow malicious actors to optimize urls you did not intend".

SetupWhat applies
Self-hosted: next start, Docker, a VPS, a cloud VMAffected on 16.0.0 to 16.3.7 with remotePatterns. Internal services and cloud metadata endpoints sit next to the server.
VercelVercel optimizes images on its own infrastructure and checks your remotePatterns itself. The advisory does not say whether that service was affected. Upgrade anyway.
OpenNext on CloudflareNo dangerouslyAllowLocalIP support: its docs say local IP addresses are always allowed if the URL matches remotePatterns. The allow-list is your only guard, whatever the Next.js version.
Next.js 15 and olderNot listed as affected, and no private-address block either: allow only hosts you trust.

What a stranger gains is a request sent from inside your network: internal admin panels, services listening on a private address, cloud metadata endpoints such as 169.254.169.254. How much of the answer comes back depends on the target; the CNA rates the confidentiality impact high and the integrity impact low. The Next.js security guide covers the other server settings worth reviewing.

How to check your Next.js version

Check the version your lockfile resolves, not the range in package.json: "next": "^16.3.0" can install any 16.x from 16.3.0 up. Run one of these at the root of the project:

bash
# What is installed
npm ls next
pnpm why next
yarn why next

# The Next.js CLI prints its own version
npx next --version

# Straight from the lockfile
grep -A2 '"node_modules/next"' package-lock.json
grep -E "^  '?next@" pnpm-lock.yaml
grep -A1 -E '^"?next@' yarn.lock
Any version from 16.0.0 to 16.3.7 is affected if you use remotePatterns. 16.3.8 and later are fixed.

In a monorepo, check every app: each can resolve its own copy of next. npm audit and Dependabot report it as GHSA-cjq9-62q9-8jv4.

How to check your image config and your live app

Start with the allow-list itself:

bash
grep -rn -A8 -E "remotePatterns|domains|dangerouslyAllowLocalIP" next.config.*

For each entry, ask who controls that hostname's DNS. Your own domain, or a storage host your provider runs, such as YOUR_PROJECT_REF.supabase.co for Supabase Storage, is fine. A pattern that accepts any host, a wildcard over a shared platform, or a domain you might let expire should go or be narrowed. The advisory does not mention the deprecated domains list, so if you still use it, move to exact remotePatterns.

Then confirm the deployed app enforces the allow-list. Run this against your own app only:

bash
# Control: an image your allow-list accepts. Expect 200.
curl -s -o /dev/null -w "%{http_code}\n" \
  "https://YOUR_APP/_next/image?url=https%3A%2F%2FYOUR_IMAGE_HOST%2Fpath%2Fimage.png&w=64&q=75"

# Probe: a host you never allowed. Expect the text: "url" parameter is not allowed
curl -s -w "\n%{http_code}\n" \
  "https://YOUR_APP/_next/image?url=https%3A%2F%2Fexample.com%2Fimage.png&w=64&q=75"
Use a width from your deviceSizes or imageSizes config (64 is in the defaults) and an allowed quality (75 is the Next.js 16 default). Read the probe's text, not only its status: a refusal is 400 with "url" parameter is not allowed. Text that starts with "url" parameter is valid but upstream response means your server fetched the host, even with a 400 or 404. Hosts other than a Next.js server you run may word errors differently.

This proves the allow-list works. It does not test the DNS trick itself, which is not something to try on a production server: your version number answers that half.

Keybrum's attack web.nextjs-image-ssrf runs the live half on apps whose owner proved ownership. It is an out-of-band check: it asks /_next/image to optimize a unique URL on Keybrum's public callback server, then watches whether your server calls it. A hit proves your allow-list accepts a host that a stranger controls, which is this CVE's precondition. It never requests an internal address and does not try the DNS trick. A finding comes with the request that worked and the fix, which your coding agent reads through Keybrum's MCP server.

How to fix CVE-2026-94483

  1. 1

    Upgrade Next.js

    16.3.8 is the first fixed release. Go to the latest 16.x instead, 16.4.5 at the time of writing, which also carries the November 2026 security release: npm install [email protected], pnpm add [email protected], yarn add [email protected] or bun add [email protected].

  2. 2

    Commit the lockfile and redeploy

    The fix reaches production only through the lockfile. If you ship a Docker image, make sure the install step does not come from a stale build cache.

  3. 3

    Narrow images.remotePatterns

    List the exact hosts and paths you serve images from. Remove patterns that accept any host, and wildcards over platforms where strangers can create subdomains.

  4. 4

    Block what the server never needs to reach

    At the firewall or security group, stop the app server from connecting to 169.254.169.254 and to private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), except the internal hosts it uses, such as your database. That limits every SSRF.

js
// Before: any host, plus a wildcard over a shared platform
images: {
  remotePatterns: [
    { protocol: 'https', hostname: '**' },
    { protocol: 'https', hostname: '**.some-platform.app' },
  ],
},

// After: only the hosts and paths you serve images from
images: {
  remotePatterns: [
    {
      protocol: 'https',
      hostname: 'YOUR_PROJECT_REF.supabase.co',
      pathname: '/storage/v1/object/public/**',
      search: '',
    },
    new URL('https://cdn.your-domain.com/images/**'),
  ],
},
next.config.js or next.config.ts. URL objects in remotePatterns work since Next.js 15.3.

What to do after upgrading

  • npm ls next, or the pnpm or yarn equivalent, shows 16.3.8 or later for every app in the repository.
  • The deployed build was rebuilt from the new lockfile, not served from a cached image.
  • The control request above still returns 200, and the probe still answers "url" parameter is not allowed.
  • images.remotePatterns lists exact hosts, and dangerouslyAllowLocalIP is absent or false outside local development.
  • Server or proxy logs for /_next/image show no url= hosts you do not recognise. If they do and the server holds cloud credentials, rotate them.

The same 16.3.8 release also patched cache poisoning and information disclosure advisories, so the upgrade is worth it even without remotePatterns.

  • CVE-2024-34351: the earlier Next.js SSRF, in Server Actions, where a forged Host header steered a server-side fetch. Fixed in 14.1.1.
  • CVE-2025-29927: the middleware bypass through the internal x-middleware-subrequest header.
  • CVE-2026-44575: a middleware bypass through .rsc and segment-prefetch URLs.
  • CVE-2026-27978: Server Actions accepting cross-site calls sent with Origin: null.
  • CVE-2026-94543 and CVE-2026-94484: cache poisoning of SSG and ISR pages, fixed the same day in 16.3.8 and, for 15.x, in 15.5.27.

If a coding agent wrote your next.config, review its allow-lists too: the security risks of vibe-coded apps covers the rest.

Timeline

DateEvent
30 September 2026Advisory GHSA-cjq9-62q9-8jv4 published; Next.js 16.3.8 released with the fix.
2 October 2026CVE record published on cve.org and in NVD.
6 October 2026CISA records no known exploitation. NVD record last updated, with its CVSS 3.1 score of 6.5. Next.js 16.4.0 ships.
7 October 2026GitHub Advisory Database marks the advisory reviewed, which feeds npm audit and Dependabot.
8 November 2026Not in CISA's KEV catalog (version of 6 November). EPSS 0.33% on 7 November.

Questions

Is my Next.js 15 app affected by CVE-2026-94483?

Not by this CVE. The advisory lists only next 16.0.0 to 16.3.7, and the private-address block it bypasses arrived in 16.0.0, so 15.x has none to bypass. On 15.x the allow-list is the only guard: keep it to hosts you trust, and stay on the latest 15.5 release (15.5.29 today), which also carries the cache poisoning fixes of 15.5.27.

What is the Next.js image optimizer SSRF?

The image optimizer at /_next/image downloads remote images on your server before resizing them. An SSRF there means a stranger can make your server fetch an address it should refuse, including private addresses inside your network. CVE-2026-94483 is one case, through DNS answers for an allow-listed host; an allow-list that accepts any host is another.

Does CVE-2026-94483 affect apps hosted on Vercel?

On Vercel, images are optimized by Vercel's own infrastructure, which applies your remotePatterns itself. The advisory does not say whether that service was affected. The fix is a version bump, so upgrade wherever you host.

Am I affected if I do not use remotePatterns?

Not by this CVE: the advisory says apps without images.remotePatterns are not affected. If your config still uses the deprecated domains list, the advisory does not mention it, so treat it as an allow-list and move to exact remotePatterns.

Is there a workaround if I cannot upgrade?

Remove every host from images.remotePatterns whose DNS you do not control or trust, which is the advisory's own workaround. Blocking the server's outbound connections to private ranges and to 169.254.169.254 limits the damage of any SSRF while you schedule the upgrade.

Does Keybrum test for CVE-2026-94483?

Keybrum's web.nextjs-image-ssrf attack is an out-of-band check: it asks your optimizer to fetch a unique URL on Keybrum's public callback server and reports a finding only if your server calls it. A hit proves your allow-list accepts a host a stranger controls, which is this CVE's precondition. It never requests an internal address and does not try the DNS trick, so your version check covers that part.

Sources

  1. 1.GHSA-cjq9-62q9-8jv4: Server-Side Request Forgery in Image Optimization, Vercel, GitHub Security Advisory
  2. 2.CVE-2026-94483, NIST National Vulnerability Database
  3. 3.CVE-2026-94483, CVE Program
  4. 4.GHSA-cjq9-62q9-8jv4: Next.js has Server-Side Request Forgery in Image Optimization, GitHub Advisory Database
  5. 5.fix(next/image): Pin DNS resolution when fetching external images, vercel/next.js on GitHub
  6. 6.Next.js v16.3.8 release notes, vercel/next.js on GitHub
  7. 7.Next.js v15.5.27 release notes, vercel/next.js on GitHub
  8. 8.Image component: remotePatterns and dangerouslyAllowLocalIP, Next.js Docs
  9. 9.Known Exploited Vulnerabilities Catalog, CISA
  10. 10.EPSS score for CVE-2026-94483, FIRST
  11. 11.Image Optimization, Vercel Docs
  12. 12.Image optimization, OpenNext
  13. 13.next: versions, npm
  14. 14.Emerging threat: CVE-2026-94483, Next.js server-side request forgery via Image Optimization, CyCognito
  15. 15.Next.js November 2026 security release, Next.js
  16. 16.CVE-2026-94483, SOCRadar CVE Radar

Your app is public. So are its mistakes.

Check what any attacker can already see in it, free, in ten seconds. The full attack, with proof and fixes: €49 once, or €29 a month on a plan.

or continue with Google or GitHub