oRPC: Prototype Pollution in `@orpc/client` via `StandardRPCJsonSerializer` Deserialization
Description
oRPC is an tool that helps build APIs that are end-to-end type-safe and adhere to OpenAPI standards. Prior to version 1.13.6, a prototype pollution vulnerability exists in the RPC JSON deserializer of the @orpc/client package. The vulnerability allows unauthenticated, remote attackers to inject arbitrary properties into the global Object.prototype. Because this pollution persists for the lifetime of the Node.js process and affects all objects, it can lead to severe security breaches, including authentication bypass, denial of service, and potentially Remote Code Execution. This issue has been patched in version 1.13.6.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Prototype pollution in oRPC's RPC JSON deserializer allows unauthenticated remote attackers to inject properties into Object.prototype, leading to severe security impacts.
Vulnerability
Details
The vulnerability resides in the deserialize() method of the StandardRPCJsonSerializer in the @orpc/client package. When processing attacker-controlled path segments from the meta and maps arrays, the method fails to validate or sanitize dangerous JavaScript object keys such as __proto__ and constructor. This allows an attacker to pollute the global Object.prototype by injecting arbitrary properties during deserialization [1][2].
Exploitation
An unauthenticated, remote attacker can exploit this by sending a crafted RPC request containing malicious path segments in the meta or maps arrays. No authentication or special network position is required; the attack surface is any exposed RPC endpoint using the vulnerable deserializer [1][2].
Impact
Because the prototype pollution persists for the lifetime of the Node.js process and affects all objects, it can lead to severe security breaches. Potential impacts include authentication bypass, denial of service, and potentially remote code execution, depending on how the polluted properties are used by the application [1][2].
Mitigation
The issue has been patched in version 1.13.6 of the @orpc/client package. The fix adds validation that rejects path segments like __proto__ and constructor, preventing prototype pollution during deserialization [4]. Users are strongly advised to upgrade to the patched version immediately.
AI Insight generated on May 18, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@orpc/clientnpm | < 1.13.6 | 1.13.6 |
Affected products
2Patches
12 files changed · +36 −0
packages/client/src/adapters/standard/rpc-json-serializer.test.ts+28 −0 modified@@ -157,4 +157,32 @@ describe('standardRPCJsonSerializer: custom serializers', () => { }) }).toThrow('Custom serializer type must be unique.') }) + + it.each(['nonExist', '__proto__', 'constructor'])('should throw when accessing non-existent path during deserialization: %s', (segment) => { + const serializer = new StandardRPCJsonSerializer() + + expect( + () => serializer.deserialize({ a: 1 }, [[1, segment]]), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + + expect( + () => serializer.deserialize({ a: 1 }, [[1, 'a', segment]]), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + + expect( + () => serializer.deserialize({ a: 1 }, [[1, segment, 'role']]), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + + expect( + () => serializer.deserialize({ a: 1 }, [], [[segment]], () => new Blob([])), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + + expect( + () => serializer.deserialize({ a: 1 }, [], [['a', segment]], () => new Blob([])), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + + expect( + () => serializer.deserialize({ a: 1 }, [], [[segment, 'role']], () => new Blob([])), + ).toThrow(`Security error: accessing non-existent path during deserialization. Path segment: ${segment}`) + }) })
packages/client/src/adapters/standard/rpc-json-serializer.ts+8 −0 modified@@ -145,6 +145,10 @@ export class StandardRPCJsonSerializer { segments.forEach((segment) => { currentRef = currentRef[preSegment] preSegment = segment + + if (!Object.hasOwn(currentRef, preSegment)) { + throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`) + } }) currentRef[preSegment] = getBlob(i) @@ -160,6 +164,10 @@ export class StandardRPCJsonSerializer { for (let i = 1; i < item.length; i++) { currentRef = currentRef[preSegment] preSegment = item[i]! + + if (!Object.hasOwn(currentRef, preSegment)) { + throw new Error(`Security error: accessing non-existent path during deserialization. Path segment: ${preSegment}`) + } } for (const custom of this.customSerializers) {
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4- github.com/advisories/GHSA-m272-9rp6-32mcghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-28794ghsaADVISORY
- github.com/middleapi/orpc/commit/1dba06fc6f938c2486de303c2fa096bc1c8418b5ghsax_refsource_MISCWEB
- github.com/middleapi/orpc/security/advisories/GHSA-m272-9rp6-32mcghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.