Next.js next/og ImageResponse Remote Code Execution — CVE-2026-94545

Node.js runtime ImageResponse (Satori SVG pipeline) · Next.js 16.2.0 through 16.3.5 · fixed in 16.3.6 · disclosed 2026-09-22
Threat
CVE-2026-94545
Severity
CRITICAL 9.5
Type
Web app framework RCE (vulnerability)
Access
Unauthenticated / Network
Version
v0.1 · 2026-09-26
Author
HuntPack
Confidence
High (vendor-confirmed; no ITW exploitation reported as of source dates)
01

Executive Summary

CVE-2026-94545 is a critical (CVSS v4 9.5) remote code execution vulnerability in the Node.js runtime implementation of ImageResponse, the next/og feature Next.js applications use to generate Open Graph and social-preview images. The vulnerable path runs through Satori, Vercel's JSX/HTML-to-SVG conversion library: when an application places attacker-controlled input (a query-string value, header, or other request-derived data) into SVG content, attributes, or styles during image generation, improperly escaped output can be interpreted as active SVG markup and reach vulnerabilities in downstream rendering dependencies, ultimately yielding code execution in the context of the Node.js application process.

Affected versions are Next.js 16.2.0 through 16.3.5 when ImageResponse runs on the Node.js runtime (the default runtime). The Edge runtime implementation of ImageResponse is not affected, and Next.js 15.x is not affected by the RCE (15.5.26 ships related defense-in-depth hardening only). Vercel fixed the issue in Next.js 16.3.6, released 2026-09-22. The underlying flaw is tracked upstream in Satori itself (GHSA-wx4j-mvgx-mqwp, fixed in Satori 0.33.5) and is bundled inside the Next.js package rather than listed as an independent dependency, so a lockfile audit alone will not surface it.

As of the cited reporting dates (2026-09-23/24), no public proof-of-concept and no confirmed in-the-wild exploitation had been reported. That means this pack is built almost entirely around behavioral detection and version/configuration facts rather than atomic network or file indicators — there is no published campaign infrastructure to block. The highest-value defensive angle is not the exploit trigger itself (an HTTP request to an image-generation route, which Falcon endpoint telemetry cannot see) but what a successful exploit does afterward on the Node.js application server: spawning a shell or interpreter, reaching out to the network, writing new files into the web root, or reading credential material — all of which the Falcon sensor already instruments on any host where it is deployed.

Defender priority: patch to Next.js 16.3.6 today wherever next/og ImageResponse is in use, and in parallel enable the post-exploitation process/network/file hunts in Section 8 on every Next.js application-tier host — patching closes the door, but any host that was internet-reachable on an affected version between 2026-03-18 (16.2 release) and today should also be hunted for prior abuse, since neither vendor advisory provides a way to retroactively confirm whether a route was exploited before the patch.
02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry Forward
1 · VendorGHSA-vcvr-r3jv-pc5j (Vercel/Next.js advisory)Authoritative: affected range, patched version, CVSS v4 9.5 vector, PoC-shaped example (<title>{value}</title>), workaround text, credited researchers.Yes
1 · Vendornextjs.org security blogAuthoritative: dual-release fix (16.3.6 / 15.5.26 hardening-only), confirms Next.js 15.x not affected, links the related upstream Satori advisory.Yes
1 · VendorGHSA-wx4j-mvgx-mqwp (Vercel/Satori advisory)Root-cause advisory: Satori improperly escapes values before SVG output; fixed in Satori 0.33.5. Rated Moderate/5.3 at the library level — explains the CVSS discrepancy vs. the Critical/9.5 Next.js-level score (see analyst note, Section 18).Yes
2 · PressThe Hacker NewsIndependent confirmation, no ITW exploitation/PoC as of 2026-09-23, notes GitHub Advisory Database / CVE record were not yet published at write-up time, and that Satori is bundled (not a visible lockfile dependency).Partial — corroboration only, no new atomic facts
2 · Vendor-adjacent researchSOC PrimeReiterates vendor facts; adds concrete behavioral-hunt guidance (unusual image-endpoint requests, anomalous Node.js child processes, unexpected outbound connections, suspicious file creation) that directly informed Section 8's hunt angle.Partial — behavioral guidance carried forward; commercial-platform pitches discarded
2 · PressDaily CyberSecurity / securityonline.infoCorroborates affected/patched versions and CVSS 9.5; adds the concrete attacker mental model (query parameter into an SVG <title>-style tag).Partial — corroboration only

Web-hunter decisions

  • No source published atomic network/file IOCs (C2 domains, IPs, hashes) — consistent with "disclosed, patched, not yet exploited in the wild." The pack does not invent any; see Section 10.
  • All five secondary sources agree on the version range, fix version, and Node-vs-Edge distinction; this pack treats those facts as high confidence.
  • Source-injection check: every fetched page was reviewed for text addressed to an AI assistant, requests to fetch further URLs, claims of administrator/user authority, or instructions to skip validation steps. None was found in any of the six saved snapshots. SOC Prime's page contained ordinary commercial calls-to-action for its own platform ("Prime Detect", "Uncoder AI", "Contact Sales") and securityonline.info carried an unrelated ad sidebar for two other CVEs — both are normal marketing/site furniture directed at a human reader, not a prompt-injection attempt, and neither was acted on. Full verbatim snapshots are saved alongside this file in NextJS-ImageResponse-CVE-2026-94545-Hunt-sources/ for provenance.
03

Hunt Brief & Attack Chain

Hunt hypotheses

  1. (High conf) A Node.js application process (parent) spawns a shell, script interpreter, or discovery/recon binary it would not normally spawn — the highest-fidelity signal that server-side code execution in the Node process was used to shell out. MITRE T1190 / T1059.
  2. (High conf) That same Node.js process spawns a network tool-transfer utility (curl, wget, certutil, bitsadmin) to stage a second-stage payload. MITRE T1105.
  3. (Medium conf) The Node.js process itself opens an unusual outbound network connection (reverse shell, staging, or C2 check-in) to a destination port outside the application's normal service ports. MITRE T1071 / T1571.
  4. (Medium conf) The Node.js process (or a spawned child) writes a new executable or script into the web root, build-output, or cache directories — a dropped web shell or persistence payload. MITRE T1505.003 / T1105.
  5. (Medium conf) The Node.js process reads credential-shaped files (.env, SSH keys, cloud credential files, .npmrc tokens) shortly after code execution, consistent with an attacker harvesting secrets reachable by the app's service account. MITRE T1552.001.
  6. (Medium conf, exposure hunt, not an attack signal) Fleet-wide identification of hosts actually running a Next.js production server process, to prioritize patch/audit effort — command-line evidence only; EDR telemetry cannot confirm the exact installed next package version, only that a Next.js server process is running.

Attack chain

StepStageTelemetryHunt Angle
1ReconReverse-proxy / access logs (not Falcon sensor)Attacker fingerprints a Next.js app exposing an OG-image or social-preview route (/opengraph-image, /twitter-image, a custom /api/og handler).
2WeaponizationNone on the wire yetAttacker crafts a value intended to be interpreted as SVG markup once embedded unescaped in generated SVG content, attributes, or styles.
3ExploitationReverse-proxy / access logs; Falcon has no visibility at this stepCoverage gap — the crafted request that triggers the flaw, and any resulting in-process code execution that never forks a new OS process, is invisible to endpoint process/file/network telemetry. See Section 15.
4Execution / post-exploitationProcessRollup2, SyntheticProcessRollup2Node.js process spawns a shell/interpreter to act on the code-execution primitive. Q1.
5DiscoveryProcessRollup2 CommandLineRecon commands (whoami, id, hostname, uname, ip) run from the shelled-out child. Q1.
6Command & Control / tool transferProcessRollup2, NetworkConnectIP4Download of a second-stage payload, or an outbound reverse-shell / staging connection. Q2, Q3.
7Credential accessFileOpenInfo, FileReadInfoReading .env, cloud credential files, or npm tokens reachable by the app's service account. Q5.
8PersistencePeFileWritten, NewExecutableWritten, ELFFileWrittenA web shell or payload dropped into a served or cache directory for repeat access. Q4.
04

Consolidated IOC Table

No atomic network or file indicators (domains, IPs, hashes) have been published for CVE-2026-94545 as of the cited sources — there is no confirmed in-the-wild exploitation and no public PoC to derive them from. This table therefore ships version/configuration facts, which are the real, sourced "indicators" available for this vulnerability, plus behavioral signals. No entry here is a fabricated atomic IOC.

TypeValueConfidenceActionContextExpiry
software-version-rangenext (npm) ≥ 16.2.0 and ≤ 16.3.5highhuntVulnerable range per vendor advisory GHSA-vcvr-r3jv-pc5j2027-03-26
software-versionnext (npm) 16.3.6highenrichPatched version — presence confirms remediation2027-03-26
software-versionnext (npm) 15.5.26highenrich15.x hardening-only release (15.x was never RCE-affected)2027-03-26
software-version-rangesatori (npm) ≥ 0.0.27 and ≤ 0.33.4highhuntRoot-cause vulnerable range per GHSA-wx4j-mvgx-mqwp; bundled inside next, not always a visible direct dependency2027-03-26
software-versionsatori (npm) 0.33.5highenrichPatched Satori version2027-03-26
code-patternRequest-derived value interpolated into SVG content/attribute/style inside an ImageResponse call on the Node.js runtimehighhuntThe exact vulnerable pattern named in the vendor advisory's own example2027-03-26
behaviorNode.js process spawning shell / interpreter / recon binariesmediumhuntGeneric post-exploitation behavior, not unique to this CVE — see FP notes on Q12026-12-26
behaviorNode.js process opening an outbound connection to a non-standard portmediumhuntGeneric reverse-shell / staging behavior — high FP without tenant baselining, see Q32026-12-26
05

Affected Surface & Telemetry Matrix

SurfaceRequired TelemetryPriorityGap Risk
Next.js app server (Node.js runtime), bare-metal / VMFalcon sensor: ProcessRollup2, NetworkConnectIP4, file-write eventsCriticalLow — full endpoint visibility once patched/hunted
Next.js app server, containerized (Docker / Kubernetes)Falcon Cloud Workload Protection sensor emits the identical ProcessRollup2/NetworkConnectIP4/file-write schema used in Section 8's queries; no container-specific field was added to any query below because none is verified in this pipeline's Falcon data-model reference (see callout in Section 8) — ⚠ validate in tenant if you want to additionally scope by container/pod identity fields.CriticalMedium — coverage depends on sensor deployment inside the container/pod, which is commonly skipped
Reverse proxy / CDN / WAF in front of the app (access + request logs)Non-Falcon: web server or edge-proxy access logs, ideally ingested to Falcon Next-Gen SIEMHighHigh — this is the only telemetry that can see the actual exploit trigger (Section 3, step 3); most environments do not retain or ingest this today
CI/CD and build agents (produce the Next.js build)Falcon sensor process telemetry; source-control / package-registry audit logsMediumMedium — legitimate next build activity is a major source of false positives for Q1/Q4; must be excluded or scoped out (see TUNING notes)
Hosting/serverless platform (e.g., Vercel-managed deployments)Platform build logs / dependency manifest; no endpoint sensor visibility on a fully managed serverless functionMediumHigh — neither vendor advisory states whether platform-hosted apps are automatically protected; verify with your hosting provider rather than assuming
06

ATT&CK Mapping

TacticTechniqueNameObserved / Expected Behavior
Initial Access (TA0001)T1190Exploit Public-Facing ApplicationCrafted request to an ImageResponse-backed OG-image route on the Node.js runtime.
Execution (TA0002)T1059.004 / T1059.003 / T1059.006Command and Scripting Interpreter (Unix Shell / Windows Cmd / Python)Node.js process spawns a shell or scripting interpreter post-exploitation. Q1.
Discovery (TA0007)T1082, T1033System Information Discovery; System Owner/User Discoverywhoami/id/hostname/uname run from the spawned shell. Q1.
Command and Control (TA0011)T1105Ingress Tool TransferNode.js process spawns curl/wget/certutil to fetch a second stage. Q2.
Command and Control (TA0011)T1071, T1571Application Layer Protocol; Non-Standard PortNode.js process opens an outbound connection to a non-standard destination port. Q3.
Persistence (TA0003)T1505.003Server Software Component: Web ShellNew executable/script written into the web root or cache directory by the Node.js process. Q4.
Credential Access (TA0006)T1552.001Unsecured Credentials: Credentials In FilesNode.js process reads .env/SSH-key/cloud-credential/npm-token files. Q5.
Execution (TA0002) — gapT1620 (partial fit)Reflective Code Loading (closest documented technique)Purely in-process JavaScript-level code execution that never forks a new OS process — not reliably mapped to a single technique and not covered by any query in Section 8. See Section 15.
07

Native Audit-Log Hunts

These checks do not depend on the Falcon sensor and cover the parts of the attack chain (recon and the exploit trigger itself) that endpoint telemetry cannot see.

1 · Reverse-proxy / access-log grep for the exploit trigger

Search web-server or edge-proxy access logs for requests to known OG-image routes carrying HTML/SVG-shaped or URL-encoded payloads:

grep -EI "GET /(api/og|opengraph-image|twitter-image|og-image)[^ ]*(%3C|%3E|<|>|javascript:|data:)" /var/log/REPLACE_WITH_ACCESS_LOG_PATH

2 · Application code audit for the vulnerable pattern

Find every call site and manually confirm none interpolates request-derived data into SVG content, attributes, or styles:

grep -rn "from 'next/og'" --include=*.ts --include=*.tsx --include=*.js --include=*.jsx .
grep -rn "ImageResponse(" --include=*.ts --include=*.tsx --include=*.js --include=*.jsx .
# then manually inspect each match: does searchParams / headers / body / any
# request-derived value reach the returned SVG's content, attributes, or styles?

3 · Runtime version audit (fleet-wide)

npm ls next --depth=0
node -e "console.log(require('./node_modules/next/package.json').version)"
npm view next version   # compare installed vs. latest to confirm 16.3.6+ or 15.5.26+

4 · Container / Kubernetes image inventory

kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}' | grep -i next
docker images --format '{{.Repository}}:{{.Tag}}' | grep -i next

FP note: build agents legitimately run next build/next-server constantly; scope checks 3 and 4 to identify hosts, not to alert, and cross-reference against Section 3's attack chain before treating a hit as suspicious.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.

All six queries below target Node.js application-server processes via ParentBaseFileName/FileName/ContextBaseFileName matches on node — this schema is identical whether the sensor runs on bare metal, a VM, or inside a container via Falcon Cloud Workload Protection, so no rewrite is needed to cover containerized Next.js hosts. If your tenant tags container/pod identity on these events with additional fields, they are not included below because they are not verified against this pipeline's Falcon data-model reference — ⚠ validate any container/pod identity field names in your tenant before adding them.

Q1 · Node.js process spawning a shell, interpreter, or recon binary
CONF HIGHFP MEDIUMCOST LOW

Looks for: a Node.js process directly spawning a shell, common scripting interpreter, or a basic system-recon binary — the single highest-fidelity signal that code execution in the Node process was used to shell out post-exploitation. FP: build tooling (npm install, next build), process managers (pm2), and container health-check wrapper scripts routinely spawn shells from a node parent.

// HUNT: Node.js process spawning shell/interpreter/recon binary (CVE-2026-94545 post-exploitation)
// MITRE: T1190, T1059.004, T1059.003, T1059.006
// CONF: high  FP: medium  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 on Next.js application-tier hosts
// FALSE POSITIVES: npm/yarn/pnpm lifecycle scripts, "next build", pm2 process manager restarts, container health-check wrapper scripts that shell out from a node parent
// TUNING: exclude ParentCommandLine="*npm*install*", ParentCommandLine="*next build*", ParentCommandLine="*pm2*"; scope the search to the production runtime host group and exclude CI/build agents
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^node(\.exe)?$/i
| FileName=/^(sh|bash|dash|zsh|ksh|cmd|powershell|pwsh|python[0-9.]*|perl|ruby|whoami|id|uname|hostname|ifconfig|ip|ipconfig|netstat|ss)(\.exe)?$/i
| table([aid, ComputerName, UserName, ParentBaseFileName, ParentCommandLine, FileName, CommandLine, TargetProcessId, ProcessStartTime])
Q2 · Node.js process spawning a tool-transfer utility
CONF HIGHFP MEDIUMCOST LOW

Looks for: the Node.js application process spawning a download/transfer utility to stage a second-stage payload. FP: legitimate deployment/update agents and container entrypoint scripts sometimes fetch artifacts with the same binaries.

// HUNT: Node.js process spawning ingress tool-transfer utility (CVE-2026-94545 post-exploitation)
// MITRE: T1105
// CONF: high  FP: medium  COST: low
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 on Next.js application-tier hosts
// FALSE POSITIVES: deployment/artifact-fetch agents and container entrypoint scripts that legitimately curl/wget build artifacts at startup
// TUNING: exclude CommandLine="*REPLACE_WITH_INTERNAL_ARTIFACT_REPO_HOST*" for known internal package/artifact repositories; scope to production runtime hosts and exclude deployment/CI agents
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^node(\.exe)?$/i
| FileName=/^(curl|wget|scp|ftp|tftp|certutil|bitsadmin)(\.exe)?$/i
| table([aid, ComputerName, UserName, ParentBaseFileName, ParentCommandLine, FileName, CommandLine, TargetProcessId, ProcessStartTime])
Q3 · Node.js process making an outbound connection to a non-standard port
CONF MEDIUMFP HIGHCOST MEDIUM

Looks for: the Node.js application process itself (not a spawned child) opening an outbound connection to a port outside the common application/service port set — a proxy for a reverse shell or C2 check-in when the payload runs entirely inside the Node process rather than forking a shell. FP: very high until tuned — every environment has its own legitimate set of internal service ports (databases, caches, message queues, internal APIs) that must be excluded first.

// HUNT: Node.js process outbound connection to non-standard port (CVE-2026-94545 post-exploitation)
// MITRE: T1071, T1571
// CONF: medium  FP: high  COST: medium
// REQUIRES: NetworkConnectIP4 on Next.js application-tier hosts
// FALSE POSITIVES: legitimate outbound calls to databases, caches, message queues, internal microservice APIs, and third-party SaaS integrations on non-web ports
// TUNING: baseline your environment's legitimate outbound service ports first and extend the !in() exclusion list below (databases, queues, internal APIs) before enabling this as anything beyond an audited hunt query
#event_simpleName=/NetworkConnectIP4/
| ContextBaseFileName=/^node(\.exe)?$/i
| !in(field=RemotePort, values=[80, 443, 3000, 5000, 5432, 6379, 8080, 8443, 9092, 27017])
| table([aid, ComputerName, ContextBaseFileName, LocalPort, RemoteAddressIP4, RemotePort, ProcessStartTime])
Q4 · New executable or script written by the Node.js process
CONF MEDIUMFP HIGHCOST LOW

Looks for: the Node.js process writing a new PE/ELF/script/archive file — a dropped web shell or persistence payload written into a served directory, cache, or temp path. FP: very high on build hosts, where next build writes hundreds of files into .next/cache as normal behavior.

// HUNT: New executable/script written by Node.js process (CVE-2026-94545 persistence / web shell)
// MITRE: T1505.003, T1105
// CONF: medium  FP: high  COST: low
// REQUIRES: PeFileWritten / NewExecutableWritten / ELFFileWritten / ZipFileWritten on Next.js application-tier hosts
// FALSE POSITIVES: "next build" and CI/CD pipelines write large numbers of files into .next/cache, node_modules, and dist/build output directories as routine behavior
// TUNING: exclude TargetFileName="*/.next/cache/*", TargetFileName="*/node_modules/*"; scope to production runtime hosts only and exclude build/CI agents entirely
#event_simpleName=/PeFileWritten|NewExecutableWritten|ELFFileWritten|ZipFileWritten/
| ContextBaseFileName=/^node(\.exe)?$/i
| table([aid, ComputerName, ContextBaseFileName, TargetFileName, ProcessStartTime])
Q5 · Node.js process reading credential-shaped files
CONF MEDIUMFP MEDIUMCOST LOW

Looks for: the Node.js process opening files that look like environment/credential material (.env, SSH private keys, generic credentials files, .pem certs, .npmrc tokens) — consistent with an attacker harvesting secrets reachable by the application's service account after code execution. FP: the application itself routinely reads its own .env file at startup; the interesting signal is a read outside normal startup timing or from an unexpected process ancestry.

// HUNT: Node.js process reading credential-shaped files (CVE-2026-94545 post-exploitation credential access)
// MITRE: T1552.001
// CONF: medium  FP: medium  COST: low
// REQUIRES: FileOpenInfo / FileReadInfo on Next.js application-tier hosts
// ⚠ validate in tenant: confirm FileOpenInfo/FileReadInfo populate ContextBaseFileName in your sensor version before relying on this filter
// FALSE POSITIVES: the application legitimately reads its own .env at process startup; CI/build agents read .npmrc during "npm install" on nearly every build
// TUNING: baseline normal startup-time .env reads for this app and exclude them by time-window or by known ProcessStartTime proximity; exclude build/CI hosts entirely for the .npmrc pattern
#event_simpleName=/FileOpenInfo|FileReadInfo/
| ContextBaseFileName=/^node(\.exe)?$/i
| TargetFileName=/(\.env(\.[a-z]+)?$|id_rsa$|credentials$|\.pem$|\.npmrc$)/i
| table([aid, ComputerName, ContextBaseFileName, TargetFileName, ProcessStartTime])
Q6 · Exposure hunt — hosts running a Next.js production server process
CONF MEDIUMFP LOWCOST MEDIUM

Looks for: a fleet-wide inventory of hosts running a Next.js server process, built from command-line evidence, to prioritize where the version audit in Section 7 needs to run first. This is not an attack-detection query. Limitation: command-line evidence proves a host runs Next.js; it cannot prove which exact next package version, so every hit still requires the Section 7 version-audit checks before it can be marked patched or vulnerable.

// HUNT: Fleet inventory of hosts running a Next.js server process (exposure hunt, not an attack signal)
// MITRE: N/A — exposure/inventory hunt, not an attacker TTP
// CONF: medium  FP: low  COST: medium
// REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 fleet-wide
// FALSE POSITIVES: none expected (this is inventory, not a suspicious-behavior hunt) — it will legitimately match every host that runs Next.js, patched or not
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName=/^node(\.exe)?$/i
| CommandLine="*next-server*" OR CommandLine="*next/dist/bin/next*" OR CommandLine="*node_modules/.bin/next*"
| groupBy([ComputerName, aid], function=[count(as=Hits), collect([CommandLine], limit=1)], limit=20000)
| table([ComputerName, aid, Hits, CommandLine])
09

CrowdStrike Custom IOA Recommendations

QueryIOA Candidate?PatternSuggested ExclusionsDeployment Path
Q1YesNode.js parent → shell/interpreter/recon-binary childBuild/CI parent command lines (npm install, next build, pm2)Ship in Detect mode for 14 days against a per-tenant TUNING exclusion list (Section 11); promote to a Custom IOA only after a clean baseline. Do not deploy in Prevent mode — killing every node→shell spawn will break legitimate build/ops tooling.
Q2YesNode.js parent → tool-transfer utility childKnown internal artifact-repository / deployment-agent command linesSame as Q1 — Detect mode with tenant-specific TUNING before any Custom IOA promotion.
Q3Investigate-onlyNode.js outbound to non-standard portRequires full per-tenant port baseline before it is usable as an alert at allScheduled hunt query only until baselined; not a Custom IOA candidate in this pack.
Q4Investigate-onlyNode.js writes new executable/scriptBuild/CI hosts and .next/cache/node_modules pathsScheduled hunt query, scoped to production runtime hosts only.
Q5Investigate-onlyNode.js reads credential-shaped filesApplication's own startup-time .env read; CI .npmrc readsScheduled hunt query; consider a startup-time exclusion window before any alerting.
Q6N/A — inventoryFleet Next.js server-process inventoryN/ARun ad hoc or on a weekly schedule to feed the patch-audit backlog; not an alerting query.
10

Machine-Readable IOC Appendix

No atomic network or file indicators exist for this CVE at the time this pack was built. The CSV block below intentionally ships REPLACE_WITH_… placeholders only — do not populate it with guessed values. The remaining blocks carry the real, sourced version/configuration facts and behavioral signatures instead.

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
sha256,REPLACE_WITH_SHA256_IF_A_PAYLOAD_IS_RECOVERED,detect,high,2027-03-26,CVE-2026-94545 post-exploitation payload (no public sample as of pack build date),campaign:NextJS-ImageResponse-CVE-2026-94545
domain,REPLACE_WITH_C2_DOMAIN_IF_OBSERVED,detect,high,2027-03-26,CVE-2026-94545 post-exploitation C2 (no published campaign infrastructure as of pack build date),campaign:NextJS-ImageResponse-CVE-2026-94545
ipv4,REPLACE_WITH_C2_IP_IF_OBSERVED,detect,high,2027-03-26,CVE-2026-94545 post-exploitation C2 (no published campaign infrastructure as of pack build date),campaign:NextJS-ImageResponse-CVE-2026-94545
Behavioral Signatureshunt heuristics
# Behavioral signatures for CVE-2026-94545 post-exploitation (see Section 8 for full CQL)
ParentBaseFileName == node(.exe)  AND  FileName in {sh,bash,cmd,powershell,python*,whoami,id,uname,...}
ParentBaseFileName == node(.exe)  AND  FileName in {curl,wget,certutil,bitsadmin,...}
ContextBaseFileName == node(.exe) AND  NetworkConnectIP4 to RemotePort not in {80,443,3000,5000,5432,6379,8080,8443,9092,27017}
ContextBaseFileName == node(.exe) AND  new PE/ELF/script/archive written outside .next/cache or node_modules
ContextBaseFileName == node(.exe) AND  TargetFileName matches *.env, id_rsa, credentials, *.pem, .npmrc
Vulnerable Component Fingerprintversion facts
component,affected_range,patched_version,source
next (npm),16.2.0 through 16.3.5,16.3.6,GHSA-vcvr-r3jv-pc5j
satori (npm, bundled inside next),0.0.27 through 0.33.4,0.33.5,GHSA-wx4j-mvgx-mqwp
next (npm) 15.x line,not RCE-affected,15.5.26 (hardening only),nextjs.org security blog 2026-09-22
Patch / Audit Checklistverification commands
npm ls next --depth=0
npm view next version
grep -rn "from 'next/og'" --include=*.ts --include=*.tsx --include=*.js --include=*.jsx .
grep -rn "ImageResponse(" --include=*.ts --include=*.tsx --include=*.js --include=*.jsx .
11

Detection Validation Gates

GateWhat to confirmHow
Telemetry readyProcessRollup2, SyntheticProcessRollup2, NetworkConnectIP4, and file-write events are actually flowing from the Next.js application-tier host group (including any containerized hosts)Run Q1 and Q4 with no filters beyond the event-type line against the host group for a 24-hour window; confirm non-zero baseline volume
Benign baselineLegitimate node→shell/interpreter spawns from build, deploy, and process-manager tooling are catalogued before any alertingRun Q1, Q2, and Q4 in audit-only mode for at least 7 days; record every distinct ParentCommandLine/TargetFileName pattern and fold it into the TUNING exclusions
Positive testQ1 actually fires on the behavior it claims to detectOn a non-production Next.js instance, invoke a benign child-process spawn from application code (e.g., child_process.execSync('id')) to confirm Q1 fires — never attempt to trigger the actual SVG-escaping vulnerability; this pack is defensive-only and ships no exploit content
PromotionQ1/Q2 are safe to promote from hunt query to Custom IOAAfter 7+ days of clean baseline with TUNING exclusions applied, promote to a Custom IOA in Detect mode only (Section 9); do not enable Prevent mode without a further dedicated tuning cycle against production traffic
12

Hardening — Tiered

Immediate (this week)

1. Upgrade Next.js to 16.3.6 (or 15.5.26 for the 15.x hardening line). M1051 (Update Software). Authority: vendor advisory GHSA-vcvr-r3jv-pc5j / nextjs.org security blog, 2026-09-22. Verify: npm ls next --depth=0 on every application-tier host, plus a runtime version check post-deploy (package manifests alone can lie about what's actually running).

2. Audit every ImageResponse call site for attacker-controlled SVG content, attributes, or styles. M1047 (Audit). Authority: OWASP ASVS v5, V5.3 Output Encoding and Injection Prevention. Verify: the Section 7 grep commands return zero call sites where a request-derived value reaches SVG content, attributes, or styles.

3. Apply the vendor workaround immediately on any host that cannot patch same-day. M1038 (Execution Prevention, applied at the application layer). Authority: vendor advisory workaround text (source 01). Verify: code review confirms attacker-controlled values are stripped or encoded before reaching ImageResponse's SVG output.

Near term (1–4 weeks)

4. Add a reverse-proxy/WAF rule blocking HTML/SVG-shaped payloads on OG-image routes. M1037 (Filter Network Traffic). Authority: OWASP ASVS v5 V5.3; NIST SP 800-53 SC-7 (Boundary Protection). Verify: send a benign test request containing an encoded angle-bracket payload to a non-production OG-image route and confirm the proxy blocks or flags it.

5. Run the Node.js application under a dedicated, unprivileged service account with a minimal writable filesystem scope. M1026 (Privileged Account Management). Authority: CIS Distribution Independent Linux Benchmark, service-account hardening section. Verify: ps -o user= -p REPLACE_WITH_NODE_PID is not root; confirm the account cannot write outside its designated cache/tmp paths.

6. Deny-by-default egress filtering from the application tier. M1030 (Network Segmentation). Authority: NIST SP 800-53 SC-7. Verify: from an app-tier host, confirm an outbound connection attempt to an arbitrary non-allow-listed destination is dropped.

Strategic (1–3 months)

7. Move OG/social-preview image generation to build-time static generation, or the unaffected Edge runtime, wherever product requirements allow. M1042 (Disable or Remove Feature or Program). Authority: vendor advisory (Edge runtime confirmed unaffected). ⚠ Next.js documentation marks the Edge runtime as deprecated per source 03 — treat this as a mitigation for the current vulnerable code path, not a long-term architectural target.

8. Containerize with a read-only root filesystem and a seccomp/AppArmor profile that denies exec of shells/interpreters from the Node.js process. M1038 (Execution Prevention). Authority: CIS Docker Benchmark 5.x container runtime hardening controls. Verify: attempt docker exec REPLACE_WITH_CONTAINER_ID sh -c id from inside the running container's own entrypoint and confirm it is denied by the seccomp profile (an operator's external docker exec from the host is a separate, expected admin path and is not what this control restricts).

9. Gate CI on continuous dependency/SCA scanning for Next.js and Satori version drift. M1051 (Update Software). Authority: NIST SP 800-53 SI-2 (Flaw Remediation). Verify: CI pipeline fails the build when next resolves below 16.3.6 (16.x line) or below 15.5.26 (15.x line).

13

Deployable Playbooks

Playbook A — Patch Next.js to the fixed release

Prerequisites: a maintenance window or blue/green deploy path; CI able to rebuild the application image. Reboot required: no (application redeploy required, not an OS reboot). Rollback: keep the pre-upgrade build artifact/image tagged; redeploy it if the new release regresses application behavior.

1. Confirm current version:
   npm ls next --depth=0

2. Bump the dependency (16.x line):
   npm install next@16.3.6
   # or, for the 15.x hardening-only line:
   npm install next@15.5.26

3. Rebuild and redeploy the application image/container — do not
   hot-patch node_modules on a running host; Satori is bundled
   inside next, so only a full reinstall/rebuild updates it.

4. Verify the RUNNING process, not just the manifest:
   node -e "console.log(require('./node_modules/next/package.json').version)"

5. Re-run the Section 7 code audit to confirm no residual
   attacker-controlled-value-into-SVG pattern remains, even on
   the patched version, as defense in depth.

Playbook B — seccomp profile denying shell/interpreter exec from the Node.js container

Prerequisites: container runtime supporting seccomp (Docker Engine or Kubernetes with a seccomp-capable node); a staging environment to validate the profile before production rollout. Reboot required: no (container restart required to apply a new seccomp profile, not a host reboot). Rollback: revert to the previous (or default) seccomp profile reference in the pod spec / docker run invocation and restart the container; keep the prior profile file versioned alongside this one.

{
  "defaultAction": "SCMP_ACT_ALLOW",
  "syscalls": [
    {
      "names": ["execve", "execveat"],
      "action": "SCMP_ACT_ERRNO",
      "comment": "Deny the Node.js process from exec'ing a new program at all; a patched, non-shelling-out app never needs this. Remove/relax if the app has a legitimate execve dependency."
    }
  ]
}

# Kubernetes pod spec reference (apply after validating in staging):
#   securityContext:
#     seccompProfile:
#       type: Localhost
#       localhostProfile: profiles/REPLACE_WITH_PROFILE_FILENAME.json
#
# Docker Engine reference:
#   docker run --security-opt seccomp=REPLACE_WITH_PROFILE_PATH.json REPLACE_WITH_IMAGE

Playbook C — reverse-proxy rule blocking SVG/HTML-shaped payloads on OG-image routes

Prerequisites: administrative access to the reverse proxy / WAF in front of the application; a staging route to validate the rule does not break legitimate requests. Reboot required: no (config reload only). Rollback: comment out or remove the added location/rule block and reload the proxy config; keep the previous config file versioned.

# Example nginx snippet — adjust route paths to match your app's actual
# OG-image / social-preview handlers before deploying.
location ~ ^/(api/og|opengraph-image|twitter-image) {
    if ($args ~* "(%3C|%3E|<|>|javascript:|data:)") {
        return 403;
    }
    proxy_pass http://REPLACE_WITH_UPSTREAM_APP_HOST;
}

# Test from a non-production route before enabling in production:
#   curl -s -o /dev/null -w '%{http_code}\n' \
#     'https://REPLACE_WITH_STAGING_HOST/api/og?value=%3Ctest%3E'
#   (expect 403 once the rule is live)

Playbook D — Falcon detection posture for Q1/Q2

Prerequisites: Falcon sensor deployed on all Next.js application-tier hosts; the Section 11 benign-baseline gate completed. Reboot required: no. Rollback: disable the Custom IOA rule (or revert it from Detect to a saved hunt query) if it proves too noisy after promotion; no endpoint-state change to undo since this playbook only changes Falcon console configuration, not the host.

1. Save Q1 and Q2 (Section 8) as Scheduled Searches scoped to the
   Next.js application-tier host group.
2. Run for 7+ days in audit mode; collect every distinct
   ParentCommandLine / CommandLine pattern that fires.
3. Add each confirmed-benign pattern to the TUNING exclusion list
   in the query (Section 8) before promoting.
4. Promote to a Custom IOA in Detect mode only. Do not enable
   Prevent (auto-kill) without a dedicated production tuning cycle;
   killing a false-positive build/ops process is a self-inflicted
   outage.
14

Containment Runbook

PhaseActionsOwnerEvidence to Preserve
IsolateNetwork-contain the affected host via Falcon host containment; if the host cannot be contained without an outage, restrict its inbound exposure at the load balancer/reverse proxy instead so the application tier stays up while the specific host is pulled from rotation.IR lead / SOCFalcon host-containment timestamp; load-balancer rotation-pull record
EradicateKill the malicious process tree identified via Q1–Q5; remove any dropped web shell/payload found via Q4; rotate every secret reachable by the app's service account (API keys, database credentials, cloud IAM keys, npm tokens) since Q5 indicates credential exposure is the realistic worst case.App owner + IRProcess tree snapshot, dropped-file hash/path, list of rotated secrets and rotation timestamps
RecoverRedeploy from a known-good image built on Next.js 16.3.6 (or 15.5.26); confirm the Section 7 code audit and version-audit checks pass on the new deployment before returning it to rotation; re-enable traffic gradually while watching Q1–Q5 for recurrence.App owner + SRENew image build hash/tag, passing audit-check output, post-recovery hunt-query results
15

Detection Coverage Map

TechniqueBehaviorCQLIOACoverage
T1190Crafted request reaching the vulnerable ImageResponse/Satori SVG pipelineNone (endpoint sensor has no visibility into HTTP request bodies/query strings)—GAP — visible only via reverse-proxy/access-log hunt (Section 7)
Execution — in-process, no child spawnedAttacker-controlled SVG value reaches a downstream library vulnerability and achieves code execution entirely inside the existing Node.js process, without ever forking a new OS processNoneNoneGAP — this is the honest, genuine detection gap for this CVE: process/file/network telemetry cannot see code that runs inside an already-legitimate process and touches nothing observable at the OS level. Only application-level instrumentation (APM traces, unexpected process crash/restart correlation, anomalous heap behavior) could plausibly surface this, and none of the cited sources describe such tooling for this specific flaw.
T1059.004 / .003 / .006Node.js spawns shell/interpreterQ1IOA candidate (Detect mode, Section 9)Good
T1082 / T1033Recon commands from spawned shellQ1IOA candidateGood
T1105Node.js spawns tool-transfer utilityQ2IOA candidateGood
T1071 / T1571Outbound connection to non-standard portQ3Investigate-onlyPartial — high FP until tenant-baselined; covers the case where the attacker never forks a process, but only if the payload itself opens a socket (a purely computational in-process payload is still the T1190/in-process gap above)
T1505.003 / T1105Web shell / payload dropped to diskQ4Investigate-onlyPartial — high FP on build hosts, requires scoping to production runtime hosts
T1552.001Credential-file read by Node.js processQ5Investigate-onlyPartial — needs a startup-time baseline to separate normal .env loading from abuse
Exposure / inventoryIdentifying which hosts run a vulnerable Next.js versionQ6 (command-line evidence) + Section 7 checks 3–4 (authoritative version)N/AGood — combined EDR + native audit gives high-confidence coverage

Validation gates (Section 11) apply to every Good/Partial row above: none of Q1–Q5 should be promoted to a Custom IOA, and none should be trusted operationally, until the telemetry-ready and benign-baseline gates have been run against the specific tenant deploying this pack.

16

Hunt Summary Ticket

TITLE:      Hunt for CVE-2026-94545 (Next.js next/og ImageResponse RCE) exposure and post-exploitation
SEVERITY:   Critical (CVSS v4 9.5, per vendor advisory GHSA-vcvr-r3jv-pc5j)
SCOPE:      All hosts running a Next.js application server on the Node.js runtime,
            with priority on hosts confirmed via Q6 / Section 7 checks 3-4 to be
            running next 16.2.0 through 16.3.5 with an internet-reachable
            ImageResponse-backed route (Open Graph / social-preview image
            generation).
HYPOTHESIS: An unauthenticated attacker sent a crafted request whose value was
            embedded, unescaped, into SVG content/attributes/styles rendered by
            the Node.js ImageResponse implementation, reaching a downstream
            library vulnerability and achieving code execution in the Node.js
            application process, then acted on that execution by spawning a
            shell, transferring tooling, opening an outbound connection,
            reading credentials, and/or dropping a persistence payload.
QUERIES:    Q1-Q6 (Section 8); native audit checks 1-4 (Section 7)
DO FIRST:   1. Patch to Next.js 16.3.6 / 15.5.26 fleet-wide (Playbook A).
            2. Run Q6 + Section 7 checks 3-4 to inventory exposure.
            3. Run Q1-Q5 across the application-tier host group for the
               retrospective window (16.2 released 2026-03-18 through patch
               date) since neither vendor advisory offers a way to confirm
               whether a route was exploited before patching.
FINDINGS:   [populate during the hunt — no findings at time of pack build;
            no public PoC or confirmed in-the-wild exploitation as of the
            cited source dates]
GAPS:       In-process code execution that never forks a child process is not
            observable via endpoint process/file/network telemetry (Section 15).
            The actual exploit trigger (the crafted HTTP request) requires
            reverse-proxy/access-log visibility this pack cannot assume is
            ingested (Section 7, check 1).
ACTIONS:    Patch (Immediate tier, Section 12); WAF rule on OG-image routes
            (Playbook C); credential rotation if Q5 fires (Containment
            Runbook, Section 14); promote Q1/Q2 to Custom IOA only after the
            Section 11 benign-baseline gate.
OWNER:      REPLACE_WITH_HUNT_OWNER
VERSION:    v0.1 - 2026-09-26
17

Changelog

v0.12026-09-26Initial release. Built from six vendor/press source snapshots (Section 18); no atomic IOCs published for this CVE as of build date, so the pack ships behavioral detections (Q1-Q5), an exposure/inventory hunt (Q6), and version/configuration facts instead of fabricated indicators.
18

References

TierSourceUsed ForAccess Date
1 · VendorGHSA-vcvr-r3jv-pc5j — Vercel/Next.js advisoryCVSS score/vector, affected/patched versions, vulnerable-pattern example, workaround, credits2026-09-26
1 · Vendornextjs.org — Security update, 2026-09-22Dual-release fix confirmation, Next.js 15.x non-affected status, link to root-cause Satori advisory2026-09-26
1 · VendorGHSA-wx4j-mvgx-mqwp — Vercel/Satori advisoryRoot-cause detail, Satori patched version 0.33.5, library-level CVSS score for context2026-09-26
2 · PressThe Hacker News, 2026-09-23Independent corroboration; no-ITW-exploitation status; bundled-dependency note2026-09-26
2 · Vendor-adjacent researchSOC Prime, 2026-09-24Behavioral-hunt guidance that shaped the Section 8 hunt angle2026-09-26
2 · PressDaily CyberSecurity / securityonline.info, 2026-09-23Corroboration; attacker mental-model framing2026-09-26

Full verbatim text of every source above is saved in NextJS-ImageResponse-CVE-2026-94545-Hunt-sources/ alongside this file (01 through 06). No fetched source contained text directed at an AI assistant, a request to fetch further URLs, a claim of administrator/user authority, or an instruction to skip validation — see the provenance note in Section 2.

Generated 2026-09-26 · HuntPack v0.1 · Defensive hunt/detection/hardening content only — no exploit code included.