Skip to content

Commit ec6f593

Browse files
authored
fix(frontend): code scanning vulnerability (#11459)
## Changes ๐Ÿ—๏ธ Addresses this code scanning alert [security/code-scanning/156](https://github.com/Significant-Gravitas/AutoGPT/security/code-scanning/156) ## Checklist ๐Ÿ“‹ ### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] No prototype pollution
1 parent e6ed834 commit ec6f593

File tree

1 file changed

+18
-10
lines changed
  • autogpt_platform/frontend/src/lib

1 file changed

+18
-10
lines changed

โ€Žautogpt_platform/frontend/src/lib/utils.tsโ€Ž

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import { type ClassValue, clsx } from "clsx";
22
import { isEmpty as _isEmpty } from "lodash";
33
import { twMerge } from "tailwind-merge";
44

5+
import { NodeDimension } from "@/app/(platform)/build/components/legacy-builder/Flow/Flow";
56
import {
67
BlockIOObjectSubSchema,
78
BlockIORootSchema,
89
Category,
910
} from "@/lib/autogpt-server-api/types";
10-
import { NodeDimension } from "@/app/(platform)/build/components/legacy-builder/Flow/Flow";
1111

1212
export function cn(...inputs: ClassValue[]) {
1313
return twMerge(clsx(inputs));
@@ -153,32 +153,40 @@ export function setNestedProperty(obj: any, path: string, value: any) {
153153
throw new Error("Path must be a non-empty string");
154154
}
155155

156-
const keys = path.split(/[\/.]/);
156+
// Split by both / and . to handle mixed separators, then filter empty strings
157+
const keys = path.split(/[\/.]/).filter((key) => key.length > 0);
157158

159+
if (keys.length === 0) {
160+
throw new Error("Path must be a non-empty string");
161+
}
162+
163+
// Validate keys for prototype pollution protection
158164
for (const key of keys) {
159-
if (
160-
!key ||
161-
key === "__proto__" ||
162-
key === "constructor" ||
163-
key === "prototype"
164-
) {
165+
if (key === "__proto__" || key === "constructor" || key === "prototype") {
165166
throw new Error(`Invalid property name: ${key}`);
166167
}
167168
}
168169

170+
// Securely traverse and set nested properties
171+
// Use Object.prototype.hasOwnProperty.call() to safely check properties
169172
let current = obj;
170173

171174
for (let i = 0; i < keys.length - 1; i++) {
172175
const key = keys[i];
173-
if (!current.hasOwnProperty(key)) {
176+
177+
// Use hasOwnProperty check to avoid prototype chain access
178+
if (!Object.prototype.hasOwnProperty.call(current, key)) {
174179
current[key] = {};
175180
} else if (typeof current[key] !== "object" || current[key] === null) {
176181
current[key] = {};
177182
}
178183
current = current[key];
179184
}
180185

181-
current[keys[keys.length - 1]] = value;
186+
// Set the final value using bracket notation with validated key
187+
// Since we've validated all keys, this is safe from prototype pollution
188+
const finalKey = keys[keys.length - 1];
189+
current[finalKey] = value;
182190
}
183191

184192
export function pruneEmptyValues(

0 commit comments

Comments
ย (0)