From 1437886e7d7fe7671c4daeb3d1d1f1548bb5affe Mon Sep 17 00:00:00 2001 From: dttdrv <154076940+dttdrv@users.noreply.github.com> Date: Fri, 27 Mar 2026 12:01:55 +0000 Subject: [PATCH] fix: mitigate prototype pollution in aiRouter extraBody merging --- .jules/sentinel.md | 4 ++++ backend/src/services/aiRouter.ts | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index e0fa46b..ab5f5f0 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -2,3 +2,7 @@ **Vulnerability:** API endpoints in `backend/src/server.ts` taking user input (`projectId`, `jobId`) were directly joined with paths using `join` in `backend/src/store/localStore.ts` without proper sanitization. This allowed attackers to escape the project directory context and overwrite or read arbitrary files by sending payload containing `../` sequences. **Learning:** Even internal backend services handling project resources must securely sanitize all parameter values used for file operations to prevent path traversal outside expected boundaries. **Prevention:** Always use safe path sanitization utilities, like the implemented `safeJoin` and `toSafeRelativePath` in `backend/src/utils/path.ts`, to securely construct file paths and ensure the final path remains within the intended boundaries. +## 2025-03-05 - [Prototype Pollution in Object Merging] +**Vulnerability:** A prototype pollution vulnerability existed in `backend/src/services/aiRouter.ts` where properties from user-provided `extraBody` were iteratively copied directly into an object without sanitizing sensitive keys like `__proto__`, `constructor`, and `prototype`. +**Learning:** Copying properties directly from parsed user input over to internal state objects allows attackers to override prototype attributes, which can result in denial of service, logic bypass, or further vulnerabilities depending on where the polluted object is used. +**Prevention:** Always explicitly validate and block sensitive keys (`__proto__`, `constructor`, `prototype`) when transferring properties from user-provided input to internal objects to prevent prototype pollution. diff --git a/backend/src/services/aiRouter.ts b/backend/src/services/aiRouter.ts index cf9cb2e..403dc0f 100644 --- a/backend/src/services/aiRouter.ts +++ b/backend/src/services/aiRouter.ts @@ -68,8 +68,8 @@ function isPlainObject(value: unknown): value is Record { function mergeExtraBody(payload: JsonObject, extraBody: unknown): void { if (!isPlainObject(extraBody)) return; - // Never allow overriding required core fields. - const blocked = new Set(["model", "messages", "stream"]); + // Never allow overriding required core fields or prototype properties. + const blocked = new Set(["model", "messages", "stream", "__proto__", "constructor", "prototype"]); for (const [key, value] of Object.entries(extraBody)) { if (blocked.has(key)) continue; payload[key] = value as any;