CVE-2026-28794
JavaScript vulnerability analysis and mitigation

Overview

CVE-2026-28794 is a critical prototype pollution vulnerability in the StandardRPCJsonSerializer deserializer of the @orpc/client npm package, part of the oRPC framework — a tool for building end-to-end type-safe APIs conforming to OpenAPI standards. The vulnerability allows unauthenticated remote attackers to inject arbitrary properties into the global Object.prototype, with effects persisting for the lifetime of the Node.js process. All versions of @orpc/client up to and including 1.13.5 are affected; version 1.13.6 contains the fix. It was published on March 6, 2026, with a patch released shortly after. It carries a CVSS v3.1 base score of 9.8 (Critical) and a CVSS v4.0 base score of 9.3 (Critical) (GitHub Advisory, Feedly).

Technical details

The root cause is classified as CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes — Prototype Pollution). The vulnerability resides in the deserialize() method of StandardRPCJsonSerializer in packages/client/src/adapters/standard/rpc-json-serializer.ts. When processing attacker-controlled path segments from the meta and maps arrays, the deserializer traverses object paths using bracket notation without validating or sanitizing dangerous keys such as __proto__ and constructor. Two distinct write vectors exist: the meta vector, which writes type-constrained values (e.g., Map, Set, Date) to arbitrary object paths; and the maps vector, which allows injection of arbitrary string values by exploiting the fact that FormData.get() returns strings at runtime despite TypeScript's compile-time Blob cast. Critically, this deserialization occurs before any schema validation (e.g., Zod), so a malicious payload pollutes the prototype even if the request is subsequently rejected (GitHub Advisory, Patch Commit).

Impact

Successful exploitation causes global Object.prototype pollution that persists for the entire lifetime of the Node.js server process, affecting all objects created thereafter. This can lead to privilege escalation and authentication bypass (e.g., if the server checks a defaulted property like user.role === 'admin', all users globally evaluate as admins), denial of service by overwriting built-in methods such as toString, and potentially full Remote Code Execution if the application or its dependencies contain prototype pollution gadgets that trigger dynamic code execution. All server adapters utilizing the RPC protocol in oRPC are impacted, and no authentication or user interaction is required for exploitation (GitHub Advisory).

Exploitability

A proof-of-concept exploit is publicly available in the GitHub Security Advisory, demonstrating exploitation via a single curl command targeting a multipart form data endpoint. There is no confirmed evidence of in-the-wild exploitation at this time. The vulnerability requires no authentication, no special privileges, and no user interaction, making it trivially exploitable by any remote attacker. The EPSS score is approximately 0.765%, and the vulnerability is not currently listed in the CISA Known Exploited Vulnerabilities (KEV) catalog (GitHub Advisory, Feedly).

Exploitation steps

  1. Reconnaissance: Identify internet-facing Node.js applications using the @orpc/client package at versions ≤1.13.5. Look for exposed RPC endpoints (e.g., /rpc/) using tools like Shodan, Censys, or by inspecting JavaScript bundles for oRPC imports.
  2. Identify a target RPC endpoint: Locate any RPC endpoint that accepts multipart form data (e.g., POST /rpc/planet/create). Any endpoint using the StandardRPC protocol is vulnerable.
  3. Craft the malicious payload (maps vector): Construct a multipart POST request where the data field contains a JSON body with an empty maps array entry pointing to __proto__ and a target property name, and a separate form field provides the injected value:
    curl -X POST http://target/rpc/planet/create \
      -F 'data={"json":{},"meta":[],"maps":[["__proto__","role"]]}' \
      -F '0=admin'
  4. Prototype pollution achieved: The deserializer traverses __proto__ without validation, executing Object.prototype.role = 'admin' on the server, affecting all objects globally for the process lifetime.
  5. Exploit downstream effects: Depending on the application logic, leverage the polluted property to bypass authentication checks (e.g., if (user.role === 'admin')), trigger denial of service by overwriting built-in methods, or chain with known RCE gadgets in the application's dependencies.
  6. Persistence: The pollution persists until the Node.js process restarts; no repeated requests are needed (GitHub Advisory).

Indicators of compromise

  • Network: Unusual multipart POST requests to RPC endpoints (e.g., /rpc/) containing __proto__ or constructor strings in the data form field; requests with maps arrays referencing prototype-related keys.
  • Logs: HTTP access logs showing POST requests to RPC paths with Content-Type: multipart/form-data and JSON bodies containing "__proto__" or "constructor" in the maps field; unexpected 200 responses to such requests on unpatched servers.
  • Process Behavior: Unexpected privilege escalation in application logic (e.g., unprivileged users gaining admin access); application crashes or unhandled exceptions caused by overwritten built-in prototype methods (e.g., toString, hasOwnProperty).
  • File System: No direct file artifacts expected from prototype pollution alone; however, if RCE gadgets are triggered, watch for new files, scripts, or cron jobs created by the Node.js process user (GitHub Advisory).

Mitigation and workarounds

Upgrade the @orpc/client npm package to version 1.13.6 or later immediately. The patch adds Object.hasOwn() checks before traversing path segments during deserialization, throwing a Security error if a non-existent or dangerous path segment (including __proto__ and constructor) is accessed. No configuration-based workaround is available since the vulnerability is exploited before schema validation occurs. Organizations should also audit downstream applications for prototype pollution gadgets that could enable RCE if exploitation occurred prior to patching (Patch Commit, GitHub Advisory).

Community reactions

The vulnerability was reported by security researcher mnixry and credited in the GitHub Security Advisory. The advisory was published by the oRPC maintainer (dinwwwh) on March 2, 2026, with a patch released promptly. The issue received coverage from automated CVE tracking services including Vulners, VulDB, and INCIBE-CERT, as well as community discussion on Mastodon (infosec.exchange) and Bluesky. A PoC week roundup published on March 16, 2026 highlighted the vulnerability as a notable proof-of-concept of the week (GitHub Advisory).

Additional resources


SourceThis report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-63376HIGH8.2
  • JavaScript logoJavaScript
  • cockpit-image-builder.src
NoYesSep 03, 2026
GHSA-7q9c-hpx7-9cwmHIGH7.5
  • JavaScript logoJavaScript
  • @typespec/spector
NoYesSep 04, 2026
CVE-2026-77465HIGH7.5
  • JavaScript logoJavaScript
  • toml
NoYesSep 03, 2026
CVE-2026-71429MEDIUM6.2
  • JavaScript logoJavaScript
  • stream-json
NoYesSep 03, 2026
GHSA-6hxq-p678-4hr2LOW2
  • JavaScript logoJavaScript
  • @simplewebauthn/server
NoYesSep 04, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management