diff --git a/autogpt_platform/frontend/next.config.mjs b/autogpt_platform/frontend/next.config.mjs index d4df72a643a9..d4595990a222 100644 --- a/autogpt_platform/frontend/next.config.mjs +++ b/autogpt_platform/frontend/next.config.mjs @@ -34,7 +34,8 @@ const nextConfig = { }, ], }, - output: "standalone", + // Vercel has its own deployment mechanism and doesn't need standalone mode + ...(process.env.VERCEL ? {} : { output: "standalone" }), transpilePackages: ["geist"], }; diff --git a/autogpt_platform/frontend/package.json b/autogpt_platform/frontend/package.json index 29a28059a666..efdbc0e81d76 100644 --- a/autogpt_platform/frontend/package.json +++ b/autogpt_platform/frontend/package.json @@ -146,7 +146,7 @@ "postcss": "8.5.6", "prettier": "3.6.2", "prettier-plugin-tailwindcss": "0.7.1", - "require-in-the-middle": "7.5.2", + "require-in-the-middle": "8.0.1", "storybook": "9.1.5", "tailwindcss": "3.4.17", "typescript": "5.9.3" diff --git a/autogpt_platform/frontend/pnpm-lock.yaml b/autogpt_platform/frontend/pnpm-lock.yaml index 406fcb212f98..679cef1bd959 100644 --- a/autogpt_platform/frontend/pnpm-lock.yaml +++ b/autogpt_platform/frontend/pnpm-lock.yaml @@ -358,8 +358,8 @@ importers: specifier: 0.7.1 version: 0.7.1(prettier@3.6.2) require-in-the-middle: - specifier: 7.5.2 - version: 7.5.2 + specifier: 8.0.1 + version: 8.0.1 storybook: specifier: 9.1.5 version: 9.1.5(@testing-library/dom@10.4.1)(msw@2.11.6(@types/node@24.10.0)(typescript@5.9.3))(prettier@3.6.2) @@ -6733,10 +6733,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-in-the-middle@7.5.2: - resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} - engines: {node: '>=8.6.0'} - require-in-the-middle@8.0.1: resolution: {integrity: sha512-QT7FVMXfWOYFbeRBF6nu+I6tr2Tf3u0q8RIEjNob/heKY/nh7drD/k7eeMFmSQgnTtCzLDcCu/XEnpW2wk4xCQ==} engines: {node: '>=9.3.0 || >=8.10.0 <9.0.0'} @@ -12531,8 +12527,8 @@ snapshots: '@typescript-eslint/parser': 8.43.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) @@ -12551,7 +12547,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 @@ -12562,22 +12558,22 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.11.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.43.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -12588,7 +12584,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.43.0(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -15135,14 +15131,6 @@ snapshots: require-from-string@2.0.2: {} - require-in-the-middle@7.5.2: - dependencies: - debug: 4.4.3 - module-details-from-path: 1.0.4 - resolve: 1.22.10 - transitivePeerDependencies: - - supports-color - require-in-the-middle@8.0.1: dependencies: debug: 4.4.3 diff --git a/autogpt_platform/frontend/src/lib/utils.ts b/autogpt_platform/frontend/src/lib/utils.ts index b05375bb839c..b7be324f3f00 100644 --- a/autogpt_platform/frontend/src/lib/utils.ts +++ b/autogpt_platform/frontend/src/lib/utils.ts @@ -2,12 +2,12 @@ import { type ClassValue, clsx } from "clsx"; import { isEmpty as _isEmpty } from "lodash"; import { twMerge } from "tailwind-merge"; +import { NodeDimension } from "@/app/(platform)/build/components/legacy-builder/Flow/Flow"; import { BlockIOObjectSubSchema, BlockIORootSchema, Category, } from "@/lib/autogpt-server-api/types"; -import { NodeDimension } from "@/app/(platform)/build/components/legacy-builder/Flow/Flow"; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); @@ -153,24 +153,29 @@ export function setNestedProperty(obj: any, path: string, value: any) { throw new Error("Path must be a non-empty string"); } - const keys = path.split(/[\/.]/); + // Split by both / and . to handle mixed separators, then filter empty strings + const keys = path.split(/[\/.]/).filter((key) => key.length > 0); + if (keys.length === 0) { + throw new Error("Path must be a non-empty string"); + } + + // Validate keys for prototype pollution protection for (const key of keys) { - if ( - !key || - key === "__proto__" || - key === "constructor" || - key === "prototype" - ) { + if (key === "__proto__" || key === "constructor" || key === "prototype") { throw new Error(`Invalid property name: ${key}`); } } + // Securely traverse and set nested properties + // Use Object.prototype.hasOwnProperty.call() to safely check properties let current = obj; for (let i = 0; i < keys.length - 1; i++) { const key = keys[i]; - if (!current.hasOwnProperty(key)) { + + // Use hasOwnProperty check to avoid prototype chain access + if (!Object.prototype.hasOwnProperty.call(current, key)) { current[key] = {}; } else if (typeof current[key] !== "object" || current[key] === null) { current[key] = {}; @@ -178,7 +183,10 @@ export function setNestedProperty(obj: any, path: string, value: any) { current = current[key]; } - current[keys[keys.length - 1]] = value; + // Set the final value using bracket notation with validated key + // Since we've validated all keys, this is safe from prototype pollution + const finalKey = keys[keys.length - 1]; + current[finalKey] = value; } export function pruneEmptyValues(