From 0fd0455fe8338903448421b968d8073d656fec65 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Jul 2022 17:10:23 +0200 Subject: [PATCH 1/3] fix(NODE-4381): handle `__proto__` well in EJSON Similar fix and similar test as f34cabc31e66, just for EJSON serialization instead of BSON deserialization. --- src/extended_json.ts | 12 +++++++++++- test/node/extended_json_tests.js | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/extended_json.ts b/src/extended_json.ts index b7bb1b03..90269623 100644 --- a/src/extended_json.ts +++ b/src/extended_json.ts @@ -285,7 +285,17 @@ function serializeDocument(doc: any, options: EJSONSerializeOptions) { for (const name in doc) { options.seenObjects.push({ propertyName: name, obj: null }); try { - _doc[name] = serializeValue(doc[name], options); + const value = serializeValue(doc[name], options); + if (name === '__proto__') { + Object.defineProperty(_doc, name, { + value, + writable: true, + enumerable: true, + configurable: true + }); + } else { + _doc[name] = value; + } } finally { options.seenObjects.pop(); } diff --git a/test/node/extended_json_tests.js b/test/node/extended_json_tests.js index f3e6cea8..b3f6ff63 100644 --- a/test/node/extended_json_tests.js +++ b/test/node/extended_json_tests.js @@ -509,6 +509,16 @@ describe('Extended JSON', function () { // expect(() => EJSON.serialize(badMap)).to.throw(); // uncomment when EJSON supports ES6 Map }); + it('should correctly deserialize objects containing __proto__ keys', function (done) { + const original = { ['__proto__']: { a: 42 } }; + const serialized = EJSON.stringify(original); + expect(serialized).to.equal('{"__proto__":{"a":42}}'); + const deserialized = EJSON.parse(serialized); + expect(Object.getOwnPropertyDescriptor(deserialized, '__proto__').enumerable).to.equal(true); + expect(deserialized.__proto__.a).to.equal(42); + done(); + }); + context('circular references', () => { it('should throw a helpful error message for input with circular references', function () { const obj = { From c1e397472d85f2cc5271aca1c4409e6fbca35c43 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Jul 2022 18:04:10 +0200 Subject: [PATCH 2/3] fixup: review feedback --- test/node/bson_test.js | 7 ++++++- test/node/extended_json_tests.js | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/test/node/bson_test.js b/test/node/bson_test.js index 484d9c07..ac178000 100644 --- a/test/node/bson_test.js +++ b/test/node/bson_test.js @@ -1776,7 +1776,12 @@ describe('BSON', function () { assertBuffersEqual(done, serialized_data, serialized_data2, 0); var doc1 = BSON.deserialize(serialized_data); - expect(Object.getOwnPropertyDescriptor(doc1, '__proto__').enumerable).to.equal(true); + expect(doc1).to.have.deep.ownPropertyDescriptor('__proto__', { + configurable: true, + enumerable: true, + writable: true, + value: { a: 42 } + }); expect(doc1.__proto__.a).to.equal(42); done(); }); diff --git a/test/node/extended_json_tests.js b/test/node/extended_json_tests.js index b3f6ff63..30d6a0ca 100644 --- a/test/node/extended_json_tests.js +++ b/test/node/extended_json_tests.js @@ -514,7 +514,12 @@ describe('Extended JSON', function () { const serialized = EJSON.stringify(original); expect(serialized).to.equal('{"__proto__":{"a":42}}'); const deserialized = EJSON.parse(serialized); - expect(Object.getOwnPropertyDescriptor(deserialized, '__proto__').enumerable).to.equal(true); + expect(deserialized).to.have.deep.ownPropertyDescriptor('__proto__', { + configurable: true, + enumerable: true, + writable: true, + value: { a: 42 } + }); expect(deserialized.__proto__.a).to.equal(42); done(); }); From 707a941fad30f1e0f4d67134c53d428110386c98 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 5 Jul 2022 21:36:26 +0200 Subject: [PATCH 3/3] fixup: review comment --- test/node/extended_json_tests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/node/extended_json_tests.js b/test/node/extended_json_tests.js index 30d6a0ca..e8f97457 100644 --- a/test/node/extended_json_tests.js +++ b/test/node/extended_json_tests.js @@ -509,7 +509,7 @@ describe('Extended JSON', function () { // expect(() => EJSON.serialize(badMap)).to.throw(); // uncomment when EJSON supports ES6 Map }); - it('should correctly deserialize objects containing __proto__ keys', function (done) { + it('should correctly deserialize objects containing __proto__ keys', function () { const original = { ['__proto__']: { a: 42 } }; const serialized = EJSON.stringify(original); expect(serialized).to.equal('{"__proto__":{"a":42}}'); @@ -521,7 +521,6 @@ describe('Extended JSON', function () { value: { a: 42 } }); expect(deserialized.__proto__.a).to.equal(42); - done(); }); context('circular references', () => {