VYPR
Critical severityNVD Advisory· Published Mar 6, 2026· Updated Mar 9, 2026

oRPC: Prototype Pollution in `@orpc/client` via `StandardRPCJsonSerializer` Deserialization

CVE-2026-28794

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.

PackageAffected versionsPatched versions
@orpc/clientnpm
< 1.13.61.13.6

Affected products

2

Patches

1
1dba06fc6f93

Merge commit from fork

https://github.com/middleapi/orpcunnoqMar 2, 2026via ghsa
2 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

News mentions

0

No linked articles in our index yet.