---
id: 2026-09-nextjs-og-imageresponse-satori-svg-rce
title: "Next.js 16.2.0–16.3.5: remote code execution in `next/og` ImageResponse (Node.js runtime) through an upstream Satori SVG-escaping bug (CVE-2026-94545, CVSS 9.5) — out-of-band fix 16.3.6 / 15.5.26 on 2026-09-22; any OG-image route that puts request input into SVG text, attributes or styles is the exposure"
date_disclosed: 2026-09-22
last_updated: 2026-09-25
severity: critical
status: patched
ecosystems: [npm, javascript, nextjs, satori]
tools_affected: ["Next.js >= 16.2.0 < 16.3.6 (Node.js ImageResponse from next/og)", "satori >= 0.0.27 < 0.33.5", "any Next.js app with a dynamic OG-image route that renders request-controlled values", "self-hosted and Vercel-hosted Next.js 16.2/16.3"]
tags: [cve, rce, nextjs, satori, og-image, svg, upstream-dependency, security-release-program, image-generation, out-of-band]
---

## TL;DR
On **2026-09-22** Vercel shipped an out-of-band Next.js security release — **16.3.6** (Active LTS) and **15.5.26** (Maintenance LTS) — for **[GHSA-vcvr-r3jv-pc5j](https://github.com/vercel/next.js/security/advisories/GHSA-vcvr-r3jv-pc5j), CVE-2026-94545, Critical, CVSS 4.0 9.5**: "Remote Code Execution in `next/og` ImageResponse." The Node.js implementation of `ImageResponse` "is affected by an upstream vulnerability" — **[Satori](https://github.com/vercel/satori/security/advisories/GHSA-wx4j-mvgx-mqwp)**, Vercel's HTML/CSS-to-SVG engine, "does not properly escape certain values before including them in generated SVG output," so crafted values are "interpreted as SVG markup," and per Vercel "improper escaping in SVG output generated by Satori could lead to remote code execution due to vulnerabilities in other upstream dependencies" that render that SVG. Affected: **Next.js ≥ 16.2.0 < 16.3.6**; **15.x is not affected** by the RCE (15.5.26 is "related hardening" only); the Edge `ImageResponse` is not affected. The exposed pattern is the standard dynamic-OG-image route — `searchParams.get('title')` dropped into the JSX that `ImageResponse` rasterises. Upgrade to 16.3.6 (or Satori 0.33.5 if you call it directly); until then, stop passing attacker-controlled values into SVG content, attributes or styles. NVD has no record for CVE-2026-94545 yet (checked 2026-09-22).

## What happened

**The pre-announcement (2026-09-22, morning).** Following the Security Release Program cadence it adopted in July, Vercel posted "Upcoming Next.js Security Update for a Critical Upstream Issue": "A critical security issue has been identified in an upstream dependency. We plan to publish Next.js 16.3.6 and 15.5.26 in an out-of-band update on September 22, 2026. The full advisory, GHSA-vcvr-r3jv-pc5j, will be published with the update." The natural guess — after August's `sharp`/`libheif` AVIF critical and its Astro and Discourse recurrences — was another image-decoding bug. It was not.

**The release (2026-09-22, afternoon UTC).** The npm registry records `satori@0.33.5` at 15:57 UTC ("Harden SVG serialization (#814)"), `next@16.3.6` at 16:19 UTC and `next@15.5.26` at 17:03 UTC. Vercel's security-update post: "These releases upgrade upstream dependencies, including Satori, to address an issue that could lead to remote code execution in affected Next.js versions. Version 15.5.26 includes related hardening, but Next.js 15.x is not affected by the remote code execution issue."

**The Next.js advisory (GHSA-vcvr-r3jv-pc5j).** "The Node.js `ImageResponse` implementation from `next/og` is affected by an upstream vulnerability. This can lead to remote code execution. Affected applications pass attacker-controlled values into SVG content, attributes, or styles during image generation." The example is exactly the route most OG-image tutorials produce — a handler reading `value` from the query string and returning `new ImageResponse(<svg …><title>{value}</title></svg>)`. Exclusion: "Applications using the Edge `ImageResponse` implementation, or applications that do not pass attacker-controlled values into SVG content, attributes, or styles, are not affected." Affected `>= 16.2.0 < 16.3.6`, patched `16.3.6`. Vector `CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H` — network, no privileges, no user interaction, "attack requirements: present" (the app must feed input into the SVG). Finder credited: rafabd1.

**The Satori advisory (GHSA-wx4j-mvgx-mqwp, same CVE).** Satori is the engine under `next/og` (and under `@vercel/og`, Astro/Nuxt OG-image integrations and dozens of standalone OG generators). Its own advisory, also published 2026-09-22 with the same CVE, is rated **Moderate, CVSS 4.0 5.3** (`AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N`): "Satori does not properly escape certain values before including them in generated SVG output. This can allow crafted values to be interpreted as SVG markup. The impact depends on how the generated SVG is consumed." Affected `>= 0.0.27 < 0.33.5`, patched `0.33.5`; "No complete workaround exists besides upgrading. Applications that cannot immediately upgrade should not render attacker-controlled content with Satori." Finders: RaghavMaheshwari124 and rafabd1.

**Why one CVE has two severities.** Satori's bug is markup injection into an SVG string — harmless if the SVG is served as an image to a browser, critical if it is handed to a native rasteriser with its own parsing bugs. Next.js's Node.js `ImageResponse` does the latter (the Edge implementation takes a different path and is not affected). Vercel's wording — "due to vulnerabilities in other upstream dependencies" — does not name the rasteriser, and neither advisory does; this write-up does not guess. The practical reading: **the severity that applies to you is the consumer's (9.5), not the library's (5.3)**, and any other framework that pipes Satori output into a native SVG renderer on the server should be assumed to sit at the higher number until its maintainers say otherwise.

**Why this matters for vibe coders.** A dynamic OG-image route is one of the most common things an AI assistant scaffolds for a Next.js app — `app/api/og/route.tsx` reading `title` and `description` from the query string — and it is by construction an unauthenticated endpoint that renders user input. This is the third Next.js critical in four weeks (AVIF/libheif and the Windows path traversal on 08-25, now this), all in the image path, and the second one caused by a dependency Next.js merely bundles. Version-pinning Next.js and never touching `satori` directly gives no protection: the fix is in the framework release.

**Update 2026-09-25 — Next.js pre-announced a *scheduled* security release for 2026-09-30: nine vulnerabilities (one critical, two high, five medium, one low), to ship as 16.3.7 and 15.5.27.** On 2026-09-23 the Next.js team (Josh Story, Karim Rahal, Sebastian Silbermann) posted advance notice of a **September 30** release addressing "nine vulnerabilities in Next.js: one **critical**, two **high**, five **medium**, and one **low**," with "**16.3.7** and **15.5.27**" published "alongside the full advisories, including impact, affected versions, and upgrade instructions." No affected ranges or CVE ids are given yet; the guidance is "upgrading to a patched version once the release is available." This is distinct from the out-of-band Satori fix above (16.3.6, 09-22). Per this corpus's own rule, a pre-announced count is a **floor** — re-fetch the release post on 09-30 and grep every id, because Next.js has shipped more than the announced number before (the August critical became two after a second `sharp`/`libheif`-class bug surfaced). A future sweep should open [`nextjs.org/blog/upcoming-nextjs-security-release-september-2026`](https://nextjs.org/blog/upcoming-nextjs-security-release-september-2026)'s successor post and the `vercel/next.js` advisory tab on release day.

## Am I affected?

- **Affected if:** `next` is `>= 16.2.0` and `< 16.3.6`, **and** any route uses the Node.js `ImageResponse` from `next/og` with values derived from the request (query string, path params, headers, database content an attacker can write) inside the JSX/SVG it renders. Route segments with `export const runtime = 'edge'` use the Edge implementation and are not affected.
- **Also affected if:** you use `satori` (or `@vercel/og`, or an OG-image integration built on Satori) `< 0.33.5` directly and rasterise its output server-side with user-controlled content — apply the consumer's severity, not Satori's.
- **Not affected if:** Next.js 15.x (the RCE does not apply; 15.5.26 is hardening), Next.js < 16.2.0, or no `ImageResponse` route renders attacker-controlled values.

```bash
# Versions
npm ls next satori @vercel/og 2>/dev/null | grep -E 'next@|satori@|@vercel/og@'

# Every ImageResponse call site, and whether it reads request input
grep -rn "ImageResponse" --include=*.ts --include=*.tsx --include=*.js --include=*.jsx . \
  | grep -v node_modules
grep -rln "ImageResponse" --include=*.tsx --include=*.ts . | grep -v node_modules \
  | xargs grep -ln "searchParams\|params\.\|headers()" 2>/dev/null

# Is the route on the Node.js runtime? (no 'edge' export = Node.js = affected path)
grep -rn "runtime *= *['\"]edge['\"]" --include=*.ts --include=*.tsx . | grep -v node_modules
```

## If you are affected

1. **Upgrade now:** `npm install next@16.3.6` (16.3 line) or `npm install next@15.5.26` (15.5 line, hardening). Redeploy; on Vercel a redeploy is required for the new dependency to take effect.
2. If you cannot upgrade today, apply Vercel's workaround: do not pass attacker-controlled values into SVG content, attributes or styles rendered by the Node.js `ImageResponse` — hard-code the OG image, or move the route to the Edge runtime, or gate it behind an allow-list of known titles.
3. If you call `satori` directly: `npm install satori@0.33.5`, and until then stop rendering attacker-controlled content with it.
4. An OG route is unauthenticated by design, so if it was live on an affected version treat the server as reachable: review request logs for the OG route with unusual `<`, `>`, `&` or entity-encoded payloads in query parameters, and if anything looks deliberate follow [if-your-webapp-was-compromised.md](../playbooks/if-your-webapp-was-compromised.md) and rotate the secrets the process could read ([rotating-cloud-credentials.md](../playbooks/rotating-cloud-credentials.md)).

## Prevention

- **Treat image generation as untrusted input processing.** OG-image, thumbnail and chart routes take request data and hand it to native parsers (SVG rasterisers, libheif, libvips); run them on the Edge runtime or in an isolated service with no secrets, and keep the framework on the latest patch line. [prevention/supply-chain-attack-surface.md](../prevention/supply-chain-attack-surface.md).
- **Watch the framework's advisory tab, not only the changelog.** Next.js now pre-announces security releases; the pre-announcement names the advisory id before it is public — subscribe to `vercel/next.js` security advisories and to the Security Release Program blog.
- **Assume "critical upstream issue" means a dependency you never installed by name.** Twice in a month the Next.js critical lived in a bundled library (libheif via sharp, then Satori). `npm audit` will flag the framework version; what it cannot tell you is whether your code exercises the path — the grep above does. [auditing-a-vibe-coded-repo.md](../playbooks/auditing-a-vibe-coded-repo.md).
- Vercel-hosted apps still need the redeploy; hosting does not patch a bundled dependency for you.

## Sources
- [vercel/next.js — GHSA-vcvr-r3jv-pc5j: Remote Code Execution in next/og ImageResponse](https://github.com/vercel/next.js/security/advisories/GHSA-vcvr-r3jv-pc5j) — vendor advisory, published 2026-09-22: CVE-2026-94545, Critical CVSS 4.0 9.5 and vector, affected `>= 16.2.0 < 16.3.6`, patched 16.3.6, the impact text, the example route, the Edge/no-attacker-input exclusion, the workaround, finder rafabd1. Fetched 2026-09-22.
- [Next.js — Next.js Security Update for a Critical Upstream Issue](https://nextjs.org/blog/nextjs-security-update-september-22-2026) — 2026-09-22 (Josh Story, Karim Rahal, Sebastian Silbermann): 16.3.6 / 15.5.26, "upgrade upstream dependencies, including Satori," 15.x not affected by the RCE, the related Satori advisory id, "improper escaping in SVG output generated by Satori could lead to remote code execution due to vulnerabilities in other upstream dependencies." Fetched 2026-09-22.
- [Next.js — Upcoming Next.js Security Update for a Critical Upstream Issue](https://nextjs.org/blog/upcoming-nextjs-security-release-september-22-2026) — the same-day pre-announcement naming GHSA-vcvr-r3jv-pc5j and the two versions before publication. Fetched 2026-09-22.
- [vercel/satori — GHSA-wx4j-mvgx-mqwp: Improper escaping in Satori-generated SVG](https://github.com/vercel/satori/security/advisories/GHSA-wx4j-mvgx-mqwp) — upstream advisory, published 2026-09-22 under the same CVE-2026-94545: Moderate CVSS 4.0 5.3 and vector, affected `>= 0.0.27 < 0.33.5`, patched 0.33.5, "the impact depends on how the generated SVG is consumed," no workaround besides upgrading, finders RaghavMaheshwari124 and rafabd1. Fetched 2026-09-22.
- [vercel/satori — releases](https://github.com/vercel/satori/releases) — 0.33.5 (2026-09-22) "Harden SVG serialization (#814)"; preceding 0.33.4 dated 2026-08-24. Fetched 2026-09-22.
- [vercel/next.js — release v16.3.6](https://github.com/vercel/next.js/releases/tag/v16.3.6) — "This release contains a security fix for GHSA-vcvr-r3jv-pc5j," 22 Sep. Fetched 2026-09-22.
- npm registry `time` fields (`npm view next time`, `npm view satori time`, 2026-09-22): `satori@0.33.5` 15:57 UTC, `next@16.3.6` 16:19 UTC, `next@15.5.26` 17:03 UTC; `latest` → 16.3.6, `backport` → 15.5.26.
- NVD API (`services.nvd.nist.gov`, 2026-09-22): no record for CVE-2026-94545 at the time of writing — the CVSS figures above are the vendors', not NVD's.
- Related in this corpus: [Next.js July + August 2026 releases](2026-07-nextjs-july-security-release.md) (the AVIF/libheif and Windows criticals of 2026-08-25, and the Astro recurrence) and [Hacktron / OpenAI forum](2026-09-hacktron-openai-forum-sso-codex-account-takeover.md) (the same image-pipeline class in Discourse).
- **2026-09-25 update source** — [Next.js — Upcoming Next.js September Security Release](https://nextjs.org/blog/upcoming-nextjs-security-release-september-2026) — 2026-09-23 (Josh Story, Karim Rahal, Sebastian Silbermann): the September 30 date, the 9-vulnerability breakdown (1 critical / 2 high / 5 medium / 1 low), and the planned 16.3.7 / 15.5.27 releases. Fetched 2026-09-25; no affected ranges or CVE ids published yet.
