Cafiyn Pulse
← Startup Signals
6 min readUpdated 2026-09-25Issue 4

A 9.5 in next/og. Whether it reaches you depends on one line in your OG route.

The advisory rates it 9.5, but it only fires if your OG image route puts attacker-controlled text into SVG. Here is how to find out which side of that line you are on.

ByKarthik KumarCafiyn Innovations
At a glance
Advisory
GHSA-vcvr-r3jv-pc5j, CVE-2026-94545
Severity
Critical, CVSS 9.5
Affected
Next.js 16.2.0 up to but not including 16.3.6
Not affected
Next.js 15.x, and the Edge ImageResponse implementation
Fixed in
Next.js 16.3.6, released 22 September 2026
Upstream
Satori escaping bug, fixed in 0.33.5

What shipped, and when

On 22 September Vercel published an advance notice and then an out-of-band security release the same day. Two versions went out: 16.3.6 on the Active LTS line and 15.5.26 on Maintenance LTS. The advisory GHSA-vcvr-r3jv-pc5j is titled Remote Code Execution in next/og ImageResponse, carries CVE-2026-94545, and is rated critical at CVSS 9.5.

The affected range is narrow and specific: 16.2.0 up to but not including 16.3.6. The 15.5.26 release exists but the blog post is explicit that it contains related hardening only, and that Next.js 15.x is not affected by the remote code execution issue. If you are on 15.x you should still take the patch, but you are not in an emergency.

The precondition that decides everything

A CVSS 9.5 on a framework as widely deployed as Next.js reads like a drop-everything event. The advisory is more careful than the score suggests. It states that applications using the Edge ImageResponse implementation, or applications that do not pass attacker-controlled values into SVG content, attributes or styles, are not affected.

That is one sentence carrying two exemptions. The first is about runtime: if your OG route runs on the Edge runtime, this particular path does not reach you. The second is about data flow: the flaw needs untrusted text to arrive inside the SVG that Satori renders. An OG image that draws a fixed logo and a fixed tagline has nowhere for that text to enter.

The common shape that does qualify is the dynamic OG card. A route that reads a title from the URL, or a username from a database, or a search term from a query parameter, and paints it into the image, is passing exactly the kind of value the advisory names. That pattern is popular precisely because it is useful, which is why the range of genuinely exposed applications is wider than the exemptions might suggest.

Where the bug actually lives

The entry point is upstream. Satori, the library that turns JSX into SVG and which next/og uses under the hood, had an improper escaping bug: certain values were not escaped before being included in generated SVG output. That advisory, GHSA-wx4j-mvgx-mqwp, is rated moderate at CVSS 5.3 and is fixed in Satori 0.33.5.

An escaping bug on its own is not remote code execution. What raises it is the combination: Vercel describes the escaping flaw as something that could lead to remote code execution due to vulnerabilities in other upstream dependencies, and says the fix upgrades those dependencies. So the critical rating belongs to the composition, not to Satori alone. Do not carry the 9.5 across to the Satori advisory when you write this up internally.

The practical consequence is that if you use Satori or @vercel/og directly, outside Next.js, you have your own upgrade to do and no Next.js release will do it for you.

How to check in ten minutes

The check is mechanical. Find the routes, then trace what enters them.

  • Find every OG route: search your app, src and pages directories for next/og and for ImageResponse
  • For each one, note whether it declares the Edge runtime or runs on Node. Only the Node implementation is affected
  • Trace every value rendered inside the image back to its origin. A query parameter, a route segment, a database field that users can write to, and a CMS field all count as attacker-controlled
  • Check styles too, not just text. The advisory names SVG content, attributes and styles, so a colour or a font family taken from a parameter is in scope
  • If you use satori or @vercel/og directly, bump satori to 0.33.5 independently of any Next.js upgrade

The step most teams skip

Upgrading and deploying production does not finish the job. Preview deployments, branch deployments and any long-lived staging environment keep serving whatever build they were created from. A preview URL from three weeks ago still runs the vulnerable code until it is redeployed or deleted, and preview URLs are frequently public and frequently indexed.

The same applies to anything pinned by a lockfile in a repository you did not think about this week: internal tools, marketing sites, documentation builds. The framework upgrade is per-application, not per-organisation.

What to do

  1. 1Upgrade to Next.js 16.3.6 if you are on 16.2.0 or later. Take 15.5.26 on the 15.5 line as hardening, not as an emergency.
  2. 2List your OG image routes and check each one for attacker-controlled values entering SVG content, attributes or styles.
  3. 3Bump satori to 0.33.5 if you use satori or @vercel/og outside Next.js.
  4. 4Redeploy or delete preview and branch deployments, which keep serving the old build.
  5. 5Check every repository you own, not just the main product, for a pinned vulnerable version.

Common questions

Which Next.js versions are affected by CVE-2026-94545?

The advisory gives the affected range as 16.2.0 up to but not including 16.3.6. Next.js 15.x is not affected by the remote code execution issue, although 15.5.26 includes related hardening.

Is the Edge runtime affected?

No. Both the advisory and the Next.js release post say applications using the Edge ImageResponse implementation are not affected. The flaw is in the Node.js implementation.

What makes an application exposed?

Passing attacker-controlled values into SVG content, attributes or styles during image generation. Applications that render only fixed content in their OG images are not affected, per the advisory.

Do I need to upgrade Satori separately?

Only if you use satori or @vercel/og directly rather than through Next.js. The Satori advisory GHSA-wx4j-mvgx-mqwp is fixed in 0.33.5 and is rated moderate at CVSS 5.3, not critical.

Why is the Satori advisory only rated 5.3 when the Next.js one is 9.5?

The Satori bug is improper escaping in generated SVG. Vercel describes remote code execution as arising from that flaw combined with vulnerabilities in other upstream dependencies, which the fix also upgrades. The critical rating belongs to the combination.

Sources

Read against the primary documentation rather than secondary coverage. Where a figure comes from a provider's own docs, it is quoted as published on 2026-09-25.

Related

More from Signals

OpenAI and Anthropic both cut prices on 22 September. One of them costs you a refactor.
Two frontier price cuts in one day is a good week for anyone paying a token bill. The migration cost is not evenly distributed, and one of the two prices comes with an expiry hedge.
A package install reads your home directory. This week two of them did it on purpose.
The implant did nothing clever. It read the files your shell reads, in the place your credentials live, and sent them somewhere else. That is the whole attack, and it works.
GitHub is switching off SHA-1 SSH keys. Find out now whether yours is one of them.
The keys at risk are the old ones, on the machines nobody logs into, in the pipelines that have run untouched for three years. Those are also the ones that will fail loudest.
Every third-party script tag is a standing grant to run code on your visitors.
A marketing form, a chat widget, an analytics snippet. Each one is permission for someone else's server to execute whatever it sends, on every page it sits on, forever.
1.8 million Android apps were scanned for hardcoded keys. Here is how to check yours.
Finding secrets in shipped apps is now a cheap, automated pipeline. Anything compiled into an APK, an IPA or a JavaScript bundle should be treated as already published.
OpenAI's Agents API will hold your agent state. What breaks if you ever need to leave.
Two major providers moved into the agent state layer in the same week. A managed harness is a real shortcut, as long as you keep a copy of what it holds.
Meta's Muse agent can now check out at your store. What merchants should change.
Agent purchases are arriving through wallets and single-use cards, not through merchants adopting a new protocol. Many merchants will receive them without choosing to.
What Brevo's SSO incident teaches about multi-tenant SAML and hijacked sending accounts.
One incident, two lessons: why email authentication did not help, and the tenant-scoping mistake anyone shipping SSO can make.
Cloudflare now sorts bots into Search, Training and Agent. What it means for your site and your agent.
The same change lands on two audiences. Site owners can now accidentally block search; agent builders will find more doors closed.
OpenAI has published seven shutdown dates. Here is the calendar.
Seven dates between 23 October and 26 February. Every one announced months ahead, in public. The failure mode is never the notice.
Nvidia bought Hugging Face. Your open-weight fallback is now a vendor relationship.
The commitments say nothing breaks. The structural change is that "we can always self-host" is now a dependency on one vendor rather than on a neutral commons.
The Videos API goes away on 24 September and OpenAI names nothing to move to.
Every other deprecation on OpenAI's page offers a migration target. This one does not, which makes it a different kind of problem.
Whisper shuts down on 26 February. The risk is not the deadline.
Five months is a generous window. Whisper is also typically wired into a background job that fails into a queue rather than into a user's face.
The Assistants API is gone. Your app may not have told you yet.
It shut down on 26 August 2026. The replacement is not a drop-in, and the most common migration mistake changes your model's behaviour without throwing an error.
One Copilot code review costs 13 requests. Here is the rest of the maths.
Copilot now bills on usage rather than seats. The headline change is simple. The multipliers underneath it are where teams get surprised.
Row-level security is on by default now. That is not the same as being protected.
Lovable fixed the default. The gap that actually leaks data was never the default, it was the policy, and no platform can write that for you.
Your model comparison is measuring the wrong number.
Every price list is per token. Your bill is per finished piece of work. Those two numbers can rank models in opposite orders.
An agent with production log access is a new identity. Treat it like one.
Always-on agents that read production logs are arriving fast. The access-control question they raise is old and well understood, which is the good news.

Open the tool.

Ten production categories, three minutes, and a ranked list of what to fix first.

Check your own stack