Skip to content
You are reading the v2 docs, currently in beta.V1 docs
oRPC
Esc
navigateopen⌘Jpreview
On this page

Prototype Pollution Protection Plugin

Use PrototypePollutionProtectionHandlerPlugin to reject request input carrying __proto__ or constructor.prototype keys before it reaches your procedures.

How It Works

Prototype pollution happens when attacker-controlled keys such as __proto__ end up assigned onto Object.prototype, changing the behavior of every object in the process. oRPC’s own decoding never assigns through the prototype chain, so the risk appears later, when your code passes the decoded input to something that merges, clones, or path-sets it, such as a vulnerable merge or set utility.

The plugin closes that gap by inspecting the decoded input of every matched request and rejecting it with a 400 when either appears:

  • an own __proto__ key on an object
  • an own constructor key holding a prototype key, the same rule secure-json-parse enforces for Fastify

The walk covers everything the built-in codecs can decode: plain objects, arrays, and Map/Set keys and values, at any depth. An AsyncIteratorObject input is checked value by value as it arrives, and a polluting value fails that iteration with the same error. A lone constructor or prototype key stays allowed, since either alone cannot pollute and both are common in real data. Because the check runs on the decoded input, it applies to any handler and content type: JSON and query data in RPCHandler, plus form data and bracket notation in OpenAPIHandler.

Setup

import { class PrototypePollutionProtectionHandlerPlugin<T extends Context>
Rejects requests whose decoded input contains prototype-polluting keys: an own `__proto__` key, or an own `constructor` key holding a `prototype` key. oRPC's own decoding never assigns through the prototype chain, so this plugin exists to stop such keys from reaching application code that merges, clones, or path-sets input with a library vulnerable to prototype pollution. An `AsyncIteratorObject` input is checked value by value as it arrives, and a polluting value fails that iteration instead.
@see{@link https://orpc.dev/docs/plugins/prototype-pollution-protection Prototype Pollution Protection Plugin}
PrototypePollutionProtectionHandlerPlugin
} from '@orpc/server/plugins'
const
const handler: RPCHandler<{
    headers?: IncomingHttpHeaders;
} & object>
handler
= new
new RPCHandler<{
    headers?: IncomingHttpHeaders;
} & object>(router: Router<{
    headers?: IncomingHttpHeaders;
} & object>, options?: NoInfer<RPCHandlerOptions<{
    headers?: IncomingHttpHeaders;
} & object>>): RPCHandler<{
    headers?: IncomingHttpHeaders;
} & object>
Serves an oRPC router over the RPC protocol using the Fetch API (Request/Response), supported by modern runtimes like Deno, Bun, Cloudflare Workers, and browsers.
@see{@link https://orpc.dev/docs/adapters/fetch-api Fetch API Adapter}
RPCHandler
(
const router: {
    planet: {
        list: ImplementedProcedure<{
            headers?: IncomingHttpHeaders;
        } & object, object, ZodObject<{
            limit: ZodOptional<ZodNumber>;
            cursor: ZodDefault<ZodNumber>;
        }, $strip>, ZodArray<ZodObject<{
            id: ZodNumber;
            name: ZodString;
            description: ZodOptional<ZodString>;
        }, $strip>>, object>;
        find: ImplementedProcedure<{
            headers?: IncomingHttpHeaders;
        } & object, object, ZodObject<{
            id: ZodNumber;
        }, $strip>, ZodObject<...>, object>;
        create: ImplementedProcedure<...>;
    };
}
router
, {
FetchHandlerOptions<{ headers?: IncomingHttpHeaders; } & object>.plugins?: FetchHandlerPlugin<{
    headers?: IncomingHttpHeaders;
} & object>[] | undefined
plugins
: [
new
new PrototypePollutionProtectionHandlerPlugin<{
    headers?: IncomingHttpHeaders;
} & object>(): PrototypePollutionProtectionHandlerPlugin<{
    headers?: IncomingHttpHeaders;
} & object>
Rejects requests whose decoded input contains prototype-polluting keys: an own `__proto__` key, or an own `constructor` key holding a `prototype` key. oRPC's own decoding never assigns through the prototype chain, so this plugin exists to stop such keys from reaching application code that merges, clones, or path-sets input with a library vulnerable to prototype pollution. An `AsyncIteratorObject` input is checked value by value as it arrives, and a polluting value fails that iteration instead.
@see{@link https://orpc.dev/docs/plugins/prototype-pollution-protection Prototype Pollution Protection Plugin}
PrototypePollutionProtectionHandlerPlugin
(),
], })

Learn More

Learn more about the attack this plugin prevents on MDN and in the OWASP Prototype Pollution Prevention Cheat Sheet. For implementation details, see the source code.

Last updated on August 27, 2026

Was this page helpful?