Skip to content

Commit 0f04d4d

Browse files
Merge commit from fork
* fix: Properly handle `__proto__` * throw instead * another
1 parent fcf4e88 commit 0f04d4d

File tree

5 files changed

+52
-5
lines changed

5 files changed

+52
-5
lines changed

.changeset/clean-owls-drum.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"devalue": patch
3+
---
4+
5+
fix: Properly handle `__proto__`

src/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ export function unflatten(parsed, revivers) {
217217
const object = {};
218218
hydrated[index] = object;
219219

220-
for (const key in value) {
220+
for (const key of Object.keys(value)) {
221221
if (key === '__proto__') {
222222
throw new Error('Cannot parse an object with a `__proto__` property');
223223
}

src/stringify.js

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,16 @@ export function stringify(value, reducers) {
217217

218218
if (Object.getPrototypeOf(thing) === null) {
219219
str = '["null"';
220-
for (const key in thing) {
220+
for (const key of Object.keys(thing)) {
221+
if (key === '__proto__') {
222+
throw new DevalueError(
223+
`Cannot stringify objects with __proto__ keys`,
224+
keys,
225+
thing,
226+
value
227+
);
228+
}
229+
221230
keys.push(stringify_key(key));
222231
str += `,${stringify_string(key)},${flatten(thing[key])}`;
223232
keys.pop();
@@ -226,7 +235,16 @@ export function stringify(value, reducers) {
226235
} else {
227236
str = '{';
228237
let started = false;
229-
for (const key in thing) {
238+
for (const key of Object.keys(thing)) {
239+
if (key === '__proto__') {
240+
throw new DevalueError(
241+
`Cannot stringify objects with __proto__ keys`,
242+
keys,
243+
thing,
244+
value
245+
);
246+
}
247+
230248
if (started) str += ',';
231249
started = true;
232250
keys.push(stringify_key(key));

src/uneval.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,16 @@ export function uneval(value, replacer) {
131131
);
132132
}
133133

134-
for (const key in thing) {
134+
for (const key of Object.keys(thing)) {
135+
if (key === '__proto__') {
136+
throw new DevalueError(
137+
`Cannot stringify objects with __proto__ keys`,
138+
keys,
139+
thing,
140+
value
141+
);
142+
}
143+
135144
keys.push(stringify_key(key));
136145
walk(thing[key]);
137146
keys.pop();

test/test.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ const fixtures = {
548548
})(),
549549
js: '{x:1}',
550550
json: '[{"x":1},1]'
551-
}
551+
},
552552
],
553553

554554
custom: ((instance) => [
@@ -852,6 +852,21 @@ for (const fn of [uneval, stringify]) {
852852
assert.throws(() => fn({ [Symbol()]: null }));
853853
});
854854

855+
uvu.test(`${fn.name} throws for __proto__ keys`, () => {
856+
const inner = JSON.parse('{"__proto__":1}');
857+
const root = { foo: inner };
858+
try {
859+
fn(root);
860+
assert.unreachable('should have thrown');
861+
} catch (e) {
862+
assert.equal(e.name, 'DevalueError');
863+
assert.equal(e.message, 'Cannot stringify objects with __proto__ keys');
864+
assert.equal(e.path, '.foo');
865+
assert.equal(e.value, inner);
866+
assert.equal(e.root, root);
867+
}
868+
});
869+
855870
uvu.test(`${fn.name} populates error.keys and error.path`, () => {
856871
try {
857872
fn({

0 commit comments

Comments
 (0)