Skip to content

Commit 7dc60a0

Browse files
committed
fix(dashboard): keep a "__proto__" key when cleaning chat messages
Review caught that the NUL-stripping copy assigned keys onto a plain object, so a tool result key named "__proto__" (or one that became it after cleaning) set the prototype instead of being stored. The copy now defines own properties, with a regression test.
1 parent 0df4a93 commit 7dc60a0

2 files changed

Lines changed: 17 additions & 5 deletions

File tree

‎packages/core/src/modules/assistant/src/persistence.test.ts‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,13 @@ test('stripNullCharacters keeps a clean value as is', () => {
2424
const value = { text: 'clean', list: [1, 'two', { three: 3 }] };
2525
expect(stripNullCharacters(value)).toEqual(value);
2626
});
27+
28+
test('stripNullCharacters keeps a __proto__ key as a plain entry', () => {
29+
const value: unknown = JSON.parse(
30+
'{"__proto__": {"polluted": true}, "__pr\\u0000oto__": 1}'
31+
);
32+
const cleaned = stripNullCharacters(value) as Record<string, unknown>;
33+
expect(Object.getPrototypeOf(cleaned)).toBe(Object.prototype);
34+
expect(Object.hasOwn(cleaned, '__proto__')).toBe(true);
35+
expect(JSON.stringify(cleaned)).toBe('{"__proto__":1}');
36+
});

‎packages/core/src/modules/assistant/src/persistence.ts‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@ export function stripNullCharacters<T>(value: T): T {
1212
return value.map(stripNullCharacters) as T;
1313
}
1414
if (value !== null && typeof value === 'object') {
15-
const cleaned: Record<string, unknown> = {};
16-
for (const [key, entry] of Object.entries(value)) {
17-
cleaned[stripNullCharacters(key)] = stripNullCharacters(entry);
18-
}
19-
return cleaned as T;
15+
// fromEntries defines own properties, so a "__proto__" key survives.
16+
return Object.fromEntries(
17+
Object.entries(value).map(([key, entry]) => [
18+
stripNullCharacters(key),
19+
stripNullCharacters(entry),
20+
])
21+
) as T;
2022
}
2123
return value;
2224
}

0 commit comments

Comments
 (0)