Detect seroval fromJSON Prototype/Type Confusion Insecure Deserialization (CVE-2026-59940) in Microsoft Sentinel
Detects exploitation attempts and post-exploitation indicators of CVE-2026-59940, a critical (CVSS 9.8) insecure deserialization vulnerability in the npm 'seroval' library (<= 1.5.2). seroval.fromJSON() suffers from a Promise resolver type confusion (CWE-843) that allows an attacker who controls serialized input to trigger invocation of attacker-controlled methods/objects during deserialization (CWE-502), leading to arbitrary code execution in Node.js server processes or browser contexts that deserialize untrusted seroval payloads (e.g., via solid-js/start, tRPC-like RSC transports, or other frameworks using seroval for server-to-client data hydration). Detection focuses on anomalous Node.js child process spawning, unexpected outbound network connections, and web application error/crash signatures correlated with requests carrying serialized seroval payloads (identifiable by characteristic JSON structures such as tagged arrays with $R, $Map, $Set, or Promise resolver markers) targeting endpoints that perform server-side rendering or RPC deserialization.
MITRE ATT&CK
- Tactic
- Initial Access Execution Persistence
KQL Detection Query
let SuspiciousParents = dynamic(["node.exe","node"]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (SuspiciousParents)
| where FileName in~ ("cmd.exe","powershell.exe","bash","sh","wget","curl","python3","perl","nc","ncat","/bin/sh","/bin/bash")
| where InitiatingProcessCommandLine has_any ("seroval","fromJSON","$R","$Map","$Set","__proto__")
or ProcessCommandLine has_any ("seroval","fromJSON")
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName
| order by Timestamp desc Detects Node.js server processes (potentially running applications that use seroval for deserialization) spawning shell interpreters or download utilities shortly after processing requests, consistent with exploitation of CVE-2026-59940's Promise resolver type confusion leading to RCE.
Data Sources
Required Tables
False Positives & Tuning
- Legitimate Node.js build tooling or CI/CD pipelines invoking shell commands from parent Node processes
- Developer debugging sessions that spawn subprocesses from Node.js REPLs
- Application health-check scripts that legitimately shell out from a Node.js server
Other platforms for CVE-2026-59940
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulate seroval malicious payload deserialization (lab)
Expected signal: Node.js process event invoking require('child_process') or similar module resolution shortly after processing the crafted JSON payload; process creation event if the PoC spawns a shell.
- Test 2Spawn shell child process from Node.js parent to simulate post-exploitation
Expected signal: Process creation event showing node as parent and /bin/sh or /bin/bash as child, with command line containing 'id'.
- Test 3Spawn PowerShell child process from Node.js parent (Windows)
Expected signal: Windows Event ID 4688 / Sysmon Event ID 1 showing node.exe as parent process and powershell.exe as child process with benign test command line.
Response Playbook
Triage
- Identify all applications in the environment that depend on the 'seroval' npm package (directly or transitively via frameworks like SolidStart, Vinxi, or custom RSC/SSR transports) and determine installed versions via `npm ls seroval` or lockfile analysis (package-lock.json, pnpm-lock.yaml, yarn.lock).
- Review web application logs and WAF logs for requests to server-rendering, hydration, or RPC endpoints containing serialized payloads with seroval markers (e.g., `$R`, `$Map`, `$Set`, `$Promise`, `__proto__`) especially from unauthenticated or low-trust sources.
- Correlate any matches from the KQL/SPL/EQL detections above with process execution timelines to determine whether a Node.js server process spawned unexpected child processes or made unexpected outbound connections shortly after receiving a suspicious payload.
- Check for signs of successful exploitation such as new scheduled tasks, cron jobs, modified startup scripts, unexpected outbound C2-style connections, or newly created files/binaries owned by the Node.js service account.
Containment
- Immediately upgrade the 'seroval' package to version 1.5.3 or later across all affected applications and redeploy; if immediate upgrade is not possible, restrict deserialization to trusted-origin payloads only and disable/gate any endpoint that calls seroval.fromJSON() on untrusted input.
- Isolate affected hosts/containers from the network (or apply egress restrictions) if evidence of post-exploitation activity (unexpected child processes, outbound connections) is confirmed, and rotate any credentials or secrets accessible to the compromised Node.js process.
Evidence Collection
- Preserve Node.js application logs, process execution telemetry (EDR/Sysmon), and network connection logs covering the suspected exploitation window for forensic analysis and timeline reconstruction.
- Capture the raw HTTP request/response bodies (including serialized seroval payloads) that triggered the detection for offline replay/analysis in an isolated lab environment against the vulnerable version to confirm exploitability.
Escalation Criteria
- !Escalate to incident response if a Node.js process is confirmed to have spawned a shell, downloaded external payloads, or established outbound connections to unfamiliar/known-malicious infrastructure following a seroval deserialization event.
- !Escalate if the affected application handles sensitive data (PII, credentials, financial data) or runs with elevated privileges, given the CVSS 9.8 rating and potential for full remote code execution.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Node.js process execution logs and EDR telemetry showing anomalous child processes spawned from the Node.js server process - >
Application-layer request logs / WAF logs containing serialized seroval payloads with resolver/prototype markers ($R, $Map, $Set, __proto__) - >
npm lockfile (package-lock.json / pnpm-lock.yaml) and node_modules/seroval/package.json showing the installed vulnerable version
Tuning Guidance
Baseline normal Node.js child-process spawning behavior for each application (CI/CD runners, monitoring agents, and legitimate shell-outs commonly trigger parent-child Node->shell relationships). Scope detections to production SSR/RPC-facing hosts rather than developer workstations or build servers to reduce noise, and prioritize alerts where the suspicious child process or network connection occurs within seconds of an inbound HTTP request containing seroval markers. Suppress alerts from known CI/CD service accounts and package-manager postinstall processes after validating them as benign.
Hunting Queries
Hunts for Node.js processes establishing an unusually high number of outbound connections to public IPs, which may indicate post-exploitation C2 beaconing following successful seroval deserialization abuse.
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ ("node.exe","node")
| where RemoteIPType == "Public"
| summarize ConnCount=count(), RemoteIPs=make_set(RemoteIP) by DeviceName, InitiatingProcessCommandLine
| where ConnCount > 20 index=* sourcetype=node_app_logs OR sourcetype=network
| search parent_process="node*"
| stats count dc(dest_ip) as unique_dests by host, process
| where count > 20 Atomic Red Team Tests
In an isolated lab Node.js environment running seroval <= 1.5.2, send a crafted serialized payload exploiting the Promise resolver type confusion to trigger invocation of an attacker-controlled function, simulating CVE-2026-59940 exploitation.
Command
node -e "const { fromJSON } = require('seroval'); const payload = JSON.parse(process.argv[1]); fromJSON(payload);" '{"t":21,"i":0,"s":{"t":1,"i":1,"a":["child_process"],"m":"require"}}' Cleanup
No persistent changes made; restart the lab Node.js process/container to reset in-memory state. Expected Telemetry
Node.js process event invoking require('child_process') or similar module resolution shortly after processing the crafted JSON payload; process creation event if the PoC spawns a shell.
Expected Detection
EDR/Sysmon-based process-lineage detections (KQL/EQL/QRadar/CrowdStrike rules above) should trigger if the simulated payload results in a child process spawn from the Node.js process.
Simulates the post-exploitation behavior of CVE-2026-59940 by having a Node.js process directly spawn a shell child process, mimicking what an attacker-controlled deserialized function call would achieve.
Command
node -e "require('child_process').execSync('id > /tmp/seroval_poc_test.txt')" Cleanup
rm -f /tmp/seroval_poc_test.txt Expected Telemetry
Process creation event showing node as parent and /bin/sh or /bin/bash as child, with command line containing 'id'.
Expected Detection
SPL/KQL/EQL parent-child process detections above should alert on node spawning a shell interpreter.
Simulates Windows-based post-exploitation behavior of CVE-2026-59940 where a compromised Node.js process invokes PowerShell, consistent with attacker-controlled method invocation during seroval deserialization.
Command
node -e "require('child_process').execSync('powershell.exe -Command Write-Output seroval_poc_test')" Cleanup
No persistent artifacts created; no cleanup required beyond closing the spawned process. Expected Telemetry
Windows Event ID 4688 / Sysmon Event ID 1 showing node.exe as parent process and powershell.exe as child process with benign test command line.
Expected Detection
KQL DeviceProcessEvents detection above should trigger on the node.exe -> powershell.exe parent-child relationship.