refactor(devtools): Harden props navigation

To prevent any unwanted access/changes to some props like the `prototype` or `constructor`
This commit is contained in:
Matthieu Riegler
2026-06-02 23:06:49 +02:00
committed by Pawel Kozlowski
parent 66cbfee57b
commit 752fb476eb
2 changed files with 19 additions and 0 deletions
@@ -327,6 +327,20 @@ describe('property-mutation', () => {
);
});
it('throw on mutating __proto__, constructor, or prototype properties', () => {
const obj = {foo: signal({})};
expect(() => mutateNestedProp(obj, ['foo', '__proto__'], {})).toThrowError(
/Access to property `__proto__` is blocked for security reasons./,
);
expect(() => mutateNestedProp(obj, ['foo', 'constructor'], {})).toThrowError(
/Access to property `constructor` is blocked for security reasons./,
);
expect(() => mutateNestedProp(obj, ['foo', 'prototype'], {})).toThrowError(
/Access to property `prototype` is blocked for security reasons./,
);
});
it('immutable updates objects with unrelated nested signals', () => {
const obj = {
foo: signal({
@@ -122,6 +122,11 @@ function* getNestedProps(
while (keys.length !== 0) {
const key = keys.shift()!;
// Prevent Prototype Pollution
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
throw new Error(`Access to property \`${key}\` is blocked for security reasons.`);
}
if (Array.isArray(receiver) && parseInt(key) >= receiver.length) {
throw new Error(`Cannot access index ${key} for array of length ${receiver.length}.`);
}