CVE-2026-103918 Overview
oRPC is a TypeScript framework for building end-to-end type-safe APIs that comply with OpenAPI standards. A prototype pollution vulnerability [CWE-915] affects the @orpc/zod package in versions prior to 1.14.10. The ZodSmartCoercionPlugin and experimental_ZodSmartCoercionPlugin collect object and record properties into plain objects and resolve shape keys through the prototype chain. A remote client reaching a procedure with an object or record input can supply __proto__ to replace the prototype of the returned request object. Attacker-controlled inherited values then reach application lookups during request processing.
Critical Impact
Remote unauthenticated attackers can inject properties into per-request objects through the prototype chain, influencing downstream application lookups and triggering unhandled TypeError exceptions during Zod validation.
Affected Products
- @orpc/zod package versions prior to 1.14.10
- Applications using ZodSmartCoercionPlugin
- Applications using experimental_ZodSmartCoercionPlugin
Discovery Timeline
- 2026-10-02 - CVE-2026-103918 published to NVD
- 2026-10-06 - Last updated in NVD database
Technical Details for CVE-2026-103918
Vulnerability Analysis
The flaw lives in the smart coercion logic within packages/zod/src/coercer.ts and packages/zod/src/zod4/coercer.ts. The coercer builds request representations using plain JavaScript objects, which inherit from Object.prototype. When processing incoming request payloads, the plugin reads shape keys through standard property access, allowing lookups to traverse the prototype chain.
For record schemas, submitting a __proto__ key replaces the prototype of the per-request object. This allows an attacker to set inherited properties that later reach application code performing property reads on the parsed object. For object schemas, specifying keys such as constructor, toString, or __proto__ causes the coercer to resolve inherited members as Zod schemas, producing an unhandled TypeError before validation completes.
The advisory confirms the issue does not modify the global Object.prototype, unrelated objects, other requests, or other users. The availability impact is scoped to the crafted request rather than persistent process-wide state.
Root Cause
The root cause is improperly controlled modification of object prototype attributes [CWE-915]. The coercer used plain {} objects whose prototype chain remained writable through __proto__, and resolved shape keys with prototype-chain lookups rather than own-property checks.
Attack Vector
Any remote client able to invoke a procedure accepting an object or record input can send a JSON payload containing a __proto__ key. No authentication or user interaction is required when the procedure is publicly reachable. The malicious key reshapes the parsed request object, after which application code reading unexpected properties receives attacker-controlled values.
// Patch excerpt - packages/zod/src/coercer.ts
ZodTypeAny,
ZodUnion,
} from 'zod/v3'
-import { guard, isObject } from '@orpc/shared'
+import { guard, isObject, NullProtoObj } from '@orpc/shared'
import { ZodFirstPartyTypeKind } from 'zod/v3'
import { getCustomZodDef } from './schemas/base'
// Patch excerpt - packages/zod/src/zod4/coercer.ts
$ZodType,
$ZodUnion,
} from 'zod/v4/core'
-import { guard, isObject } from '@orpc/shared'
+import { guard, isObject, NullProtoObj } from '@orpc/shared'
Source: GitHub Commit 26314df. The fix replaces plain object construction with NullProtoObj, a null-prototype object that cannot be polluted through __proto__.
Stop Remote Code Execution Before It Runs
Singularity™ Endpoint detects and blocks exploit attempts at machine speed, including zero-days and novel attack techniques.
Stop Exploit AttemptsDetection Methods for CVE-2026-103918
Indicators of Compromise
- HTTP request bodies to oRPC procedures containing a __proto__ key in JSON payloads
- HTTP request bodies containing suspicious keys such as constructor, prototype, or toString targeting object or record inputs
- Unhandled TypeError exceptions originating from @orpc/zod coercer code paths in application logs
- Spikes in 500-level responses correlated with payloads directed at oRPC endpoints
Detection Strategies
- Inspect inbound JSON payloads at the application gateway or WAF for reserved property names in object positions and alert on matches to oRPC routes.
- Correlate server-side exceptions referencing @orpc/zod coercer frames with the request bodies that produced them to identify exploitation attempts.
- Run a software composition analysis scan against package-lock.json and pnpm-lock.yaml to flag any @orpc/zod version below 1.14.10.
Monitoring Recommendations
- Enable structured logging of request paths and exception stack traces for all oRPC procedures to support retroactive hunting.
- Monitor error rate dashboards for oRPC endpoints and alert on sustained increases in TypeError occurrences before validation.
- Add continuous dependency monitoring to detect downgrade or reintroduction of vulnerable @orpc/zod releases in future builds.
How to Mitigate CVE-2026-103918
Immediate Actions Required
- Upgrade @orpc/zod to version 1.14.10 or later across all services that expose procedures over HTTP.
- Audit every procedure definition that accepts object or record schemas and inventory callers that are reachable without authentication.
- Review application code paths that read dynamic properties from parsed request objects for safe property access patterns.
Patch Information
The fix is published in oRPC version 1.14.10. The patch introduces NullProtoObj from @orpc/shared and replaces plain object construction in both the Zod v3 and Zod v4 coercers so request objects no longer inherit from Object.prototype. See the GitHub Security Advisory GHSA-gcgf-fh7c-8gf2, Pull Request #1727, and the v1.14.10 release notes.
Workarounds
- Deploy a WAF or proxy rule that rejects JSON request bodies containing __proto__, constructor, or prototype as object keys for affected routes.
- Replace use of ZodSmartCoercionPlugin and experimental_ZodSmartCoercionPlugin with stricter schemas that do not rely on smart coercion until the upgrade can be deployed.
- Access request properties using Object.hasOwn() or Reflect.has() with own-property checks instead of relying on prototype-chain lookups.
# Upgrade the vulnerable package
npm install @orpc/zod@1.14.10
# Verify installed version
npm ls @orpc/zod
# Audit the lockfile for lingering vulnerable copies
npm audit --production
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

