CVE-2025-68130
Description
tRPC allows users to build and consume fully typesafe APIs without schemas or code generation. Starting in version 10.27.0 and prior to versions 10.45.3 and 11.8.0, a A prototype pollution vulnerability exists in @trpc/server's formDataToObject function, which is used by the Next.js App Router adapter. An attacker can pollute Object.prototype by submitting specially crafted FormData field names, potentially leading to authorization bypass, denial of service, or other security impacts. Note that this vulnerability is only present when using experimental_caller / experimental_nextAppDirCaller. Versions 10.45.3 and 11.8.0 fix the issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
@trpc/servernpm | >= 10.27.0, < 10.45.3 | 10.45.3 |
@trpc/servernpm | >= 11.0.0, < 11.8.0 | 11.8.0 |
Affected products
1Patches
11 file changed · +18 −3
packages/server/src/unstable-core-do-not-import/http/formDataToObject.ts+18 −3 modified@@ -2,6 +2,10 @@ const isNumberString = (str: string) => /^\d+$/.test(str); +// Prototype pollution guard +const isUnsafeKey = (key: string) => + key === '__proto__' || key === 'constructor' || key === 'prototype'; + function set( obj: Record<string, any>, path: readonly string[], @@ -12,8 +16,13 @@ function set( const key = newPath.shift()!; const nextKey = newPath[0]!; - if (!obj[key]) { - obj[key] = isNumberString(nextKey) ? [] : {}; + // Skip unsafe keys to prevent prototype pollution + if (isUnsafeKey(key)) { + return; + } + + if (!Object.hasOwn(obj, key)) { + obj[key] = isNumberString(nextKey) ? [] : Object.create(null); } else if (Array.isArray(obj[key]) && !isNumberString(nextKey)) { obj[key] = Object.fromEntries(Object.entries(obj[key])); } @@ -23,6 +32,12 @@ function set( return; } const p = path[0]!; + + // Skip unsafe keys to prevent prototype pollution + if (isUnsafeKey(p)) { + return; + } + if (obj[p] === undefined) { obj[p] = value; } else if (Array.isArray(obj[p])) { @@ -33,7 +48,7 @@ function set( } export function formDataToObject(formData: FormData) { - const obj: Record<string, unknown> = {}; + const obj: Record<string, unknown> = Object.create(null); for (const [key, value] of formData.entries()) { const parts = key.split(/[\.\[\]]/).filter(Boolean);
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.