Skip to content

Commit

Permalink
feat(json-expression): 🎸 prevent protoptype chain mutation in "o.set"
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Jun 17, 2024
1 parent bd05779 commit b676b55
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 10 deletions.
12 changes: 12 additions & 0 deletions src/json-expression/__tests__/jsonExpressionUnitTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2021,6 +2021,18 @@ export const jsonExpressionUnitTests = (
name: 'Mac'
});
});

test('cannot set __proto__ prop', () => {
const expression: Expr = ['o.set', {a: 'b'},
'__proto__', ['$', '/name'],
];
expect(() => check(expression, {
a: 'b',
'__proto__': 'Mac',
}, {
name: 'Mac',
})).toThrow(new Error('PROTO_KEY'));
});
});
});

Expand Down
5 changes: 3 additions & 2 deletions src/json-expression/operators/object.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const objectOperators: types.OperatorDefinition<any>[] = [
let doc = util.asObj(ctx.eval(expr[i++], ctx)) as Record<string, unknown>;
while (i < length) {
const prop = util.str(expr[i++]) as string;
if (prop === '__proto__') throw new Error('PROTO_KEY');
const value = ctx.eval(expr[i++], ctx);
doc[prop] = value;
}
Expand All @@ -104,7 +105,7 @@ export const objectOperators: types.OperatorDefinition<any>[] = [
curr = new Expression(`asObj(${curr})`);
}
ctx.link(util.str, 'str');
ctx.link(util.setRaw, 'setRaw');
ctx.link(util.objSetRaw, 'objSetRaw');
while (i < length) {
let prop = ctx.operands[i++];
if (prop instanceof Literal) {
Expand All @@ -113,7 +114,7 @@ export const objectOperators: types.OperatorDefinition<any>[] = [
prop = new Expression(`str(${prop})`);
}
const value = ctx.operands[i++];
curr = new Expression(`setRaw(${curr}, ${prop}, ${value})`);
curr = new Expression(`objSetRaw(${curr}, ${prop}, ${value})`);
}
return curr;
},
Expand Down
12 changes: 4 additions & 8 deletions src/json-expression/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,10 @@ export const entries = (value: unknown): [key: string, value: unknown][] => {
return entries;
};

export const set = (obj: unknown, key: unknown, value: unknown): Record<string, unknown> => {
const obj2 = asObj(obj) as Record<string, unknown>;
obj2[str(key)] = value;
return obj2 as Record<string, unknown>;
};

export const setRaw = (obj: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> => {
obj[str(key)] = value;
export const objSetRaw = (obj: Record<string, unknown>, key: string, value: unknown): Record<string, unknown> => {
const prop = str(key);
if (prop === '__proto__') throw new Error('PROTO_KEY');
obj[prop] = value;
return obj;
};

Expand Down

0 comments on commit b676b55

Please sign in to comment.