Oct 5, 2026·6 min read·2 visits
A prototype injection and denial of service vulnerability in oRPC's @orpc/zod pre-validation coercion engine enables request object prototype modification and unhandled TypeError crashes.
CVE-2026-103918 is a medium-severity vulnerability within the @orpc/zod smart coercion plugin in oRPC. Prior to version 1.14.10, the package fails to sanitize untrusted input keys when performing pre-validation type coercion, allowing prototype injection on the returned request object and Denial of Service.
The @orpc/zod package, part of the oRPC open-source framework, exposes an input-coercion mechanism designed to pre-validate and align query strings and request bodies with expected schemas before final validation. In versions prior to 1.14.10, the smart coercion implementation does not sanitize or filter untrusted object keys when performing this pre-validation mapping. This omission exposes the framework to two distinct classes of vulnerabilities depending on the keys supplied by remote clients: prototype manipulation of the resulting request object and an unhandled runtime error leading to Denial of Service.
The framework utilizes these coercion plugins to ensure type safety and compatibility with OpenAPI specifications. However, by handling untrusted input keys in standard JavaScript object literals, the system allows attackers to inject properties that alter downstream runtime behavior. The attack surface is accessible to any remote, unauthenticated caller who can submit requests to API endpoints integrated with oRPC type coercion.
While the scope is limited to the single request lifecycle, the vulnerability bypasses schema boundaries and compromises incoming data integrity. This analysis provides an exhaustive breakdown of the technical root causes, replication processes, and code adjustments necessary to secure affected deployments.
The technical root cause resides in the handling of input properties within the smart coercion modules ZodSmartCoercionPlugin and experimental_ZodSmartCoercionPlugin. The coercion process loops through untrusted input keys and maps them into a container initialized as a standard object literal. When an input payload includes the proto key, the assignment evaluates directly against the inherited prototype setter, modifying the internal prototype pointer of the returned object container instead of defining an own property.
The second aspect of the vulnerability occurs during the sub-schema lookup process. When identifying the schema mapped to a specific key, the coercer evaluates schema_.shape[k]. For input keys corresponding to native JavaScript prototype properties, such as constructor or toString, this expression resolves to the inherited prototype function rather than undefined.
The system then attempts to process these functions as Zod schema instances, which fail to meet the internal validation structural requirements. This causes an unhandled type error that immediately aborts request execution. This error crashes the current thread before the execution reaches Zod validation middleware or standard application error handlers.
To trace the vulnerability, consider the original implementation of zodCoerceInternal in packages/zod/src/coercer.ts. The container newObj is declared as a plain record mapping strings to unknown values. During the property evaluation loop, the algorithm parses untrusted keys without distinguishing between own properties of the schema and inherited properties of the prototype chain.
// Vulnerable Code Path
const newObj: Record<string, unknown> = {}
const keys = new Set([
...Object.keys(value),
...Object.keys(schema_.shape),
])
for (const k of keys) {
newObj[k] = zodCoerceInternal(
schema_.shape[k] ?? schema_._def.catchall,
value[k],
)
}The patch resolves these issues by substituting the standard object literal initialization with a null-prototype helper class NullProtoObj imported from @orpc/shared. This helper represents an object created via Object.create(null), which possesses no prototype chain or inherited setters. Consequently, any assignment to proto is constrained as a harmless own property of the newly created container.
// Patched Code Path
const newObj: Record<string, unknown> = new NullProtoObj()
const shape = schema_.shape
const keys = new Set([
...Object.keys(value),
...Object.keys(shape),
])
for (const k of keys) {
newObj[k] = zodCoerceInternal(
(Object.hasOwn(shape, k) ? shape[k] : undefined) ?? schema_._def.catchall,
value[k],
)
}Additionally, the patch replaces direct index lookups with a safe check using Object.hasOwn(shape, k). This structural constraint guarantees that the coercer only retrieves schemas defined directly on the shape definition. It prevents the system from resolving inherited prototype members like constructor or toString, eliminating the type errors that trigger application crashes.
Exploitation of the prototype manipulation vulnerability requires the presence of downstream handlers or business logic that dynamically reads properties from the returned coerced request object. An attacker constructs an HTTP request containing a JSON payload where a nested parameter includes the proto key. Upon receiving the payload, the coercer executes, and the returned object retains the custom prototype fields defined by the attacker, allowing potential privilege escalation or logic bypass.
To trigger the Denial of Service vector, an attacker targets any validated endpoint by injecting a parameter named constructor or toString into the JSON payload. As the coercer attempts to look up the sub-schema for this parameter, it evaluates the prototype function, triggering a runtime TypeError when it attempts to access the schema definition. Because this error occurs inside the pre-validation middleware, the application thread terminates the execution flow for that request, denying standard validation error responses.
No privileges are required to exploit either vector, and the complexity remains low as the payloads require only standard JSON input structures. The following diagram illustrates the flow of a malicious request through the coercion engine to either execution or system crash.
The impact of CVE-2026-103918 is classified as Medium with a CVSS score of 6.5. Although the prototype manipulation does not alter the global Object.prototype, the localized prototype modification of the returned request object allows attackers to inject properties that downstream logic may trust. If application controllers check the existence of parameters via prototype chain lookups instead of strict Object.hasOwn checks, they may rely on falsified integrity values.
The Denial of Service impact is restricted to thread-level crashes or request lifecycle termination. Because the unhandled TypeError occurs before Zod can output structured validation errors, it can cause resource exhaustion or crash-looping in environments with inadequate process monitoring or unhandled rejection capture. The lack of privileges and user interaction requirements increases the overall exposure of endpoints utilizing the vulnerable coercion packages.
The primary remediation strategy is upgrading the @orpc/zod package to version 1.14.10 or higher. This update replaces all vulnerable instances of plain object literals with null-prototype containers and enforces safe property resolution. Development teams should audit their project dependency files to ensure no nested packages refer to vulnerable versions of the framework.
# Verify the installed version of the @orpc/zod package
npm list @orpc/zodIf upgrading is not immediately possible, temporary mitigation can be achieved by intercepting incoming request bodies and query strings prior to oRPC processing. A custom middleware can scan all input structures recursively and strip keys named proto, constructor, or toString. Deploying Web Application Firewall filters to block requests containing prototype-polluting payloads can provide a robust layer of secondary defense.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@orpc/zod middleapi | < 1.14.10 | 1.14.10 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-915 / CWE-1321 |
| Attack Vector | Network |
| CVSS v3.1 Score | 6.5 (Medium) |
| EPSS Score | 0.00234 |
| Impact | Prototype Pollution / Denial of Service |
| Exploit Status | PoC available in test cases |
| KEV Status | Not listed |
The application fails to restrict keys supplied by user-provided payloads before properties are dynamically assigned, allowing unexpected input properties to be processed.
A weak path access control vulnerability in SiYuan note-taking application allowed authenticated users to bypass restricted file paths by requesting historical backups and git diffs of sensitive configurations, including plain-text authentication tokens.
An incomplete path blocklist in the file retrieval engine of the SiYuan knowledge management platform allows authenticated users to read TLS and CA private key materials directly from the configuration directory.
CVE-2026-88779 is a critical vulnerability in Citrix NetScaler ADC and Citrix NetScaler Gateway affecting systems configured as a SAML Service Provider (SP) or SAML Identity Provider (IdP). An unauthenticated remote attacker can exploit this vulnerability to trigger a buffer overflow in the authentication daemon, resulting in persistent denial of service and appliance crash loops.
A critical cross-tenant SQL injection vulnerability exists in the TSQL query compiler of Trigger.dev, allowing authenticated users to bypass tenant isolation boundaries and read arbitrary ClickHouse analytics logs and execution payloads belonging to other organizations.
A logical authorization bypass vulnerability exists in Trigger.dev versions prior to 4.5.6. This flaw allows an authenticated client with a low-trust environment API key, such as development or staging, to cancel active worker deployments in a higher-trust environment like production within the same project. The vulnerability occurs because write operations on deployments were scoped solely by project identifier instead of environment identifier.
An in-depth technical analysis of multiple critical security flaws identified in the Vibe-Trading ecosystem (vibe-trading-ai). These issues range from unauthenticated remote command injection via agent tool executions to arbitrary Python execution through dynamic module loading and unsafe Jinja2 template autoescaping, allowing full system compromise.