diff --git a/CHANGELOG.md b/CHANGELOG.md index be9e98d5..1a4882ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +### Unreleased [[code][c-unreleased], [diff][d-unreleased]] + +[c-unreleased]: https://github.com/json5/json5/tree/v1 +[d-unreleased]: https://github.com/json5/json5/compare/v1.0.2...v1 + +### v1.0.2 [[code][c1.0.2], [diff][d1.0.2]] + +[c1.0.2]: https://github.com/json5/json5/tree/v1.0.2 +[d1.0.2]: https://github.com/json5/json5/compare/v1.0.1...v1.0.2 + +- Fix: Properties with the name `__proto__` are added to objects and arrays. + ([#199]) This also fixes a prototype pollution vulnerability reported by + Jonathan Gregson! ([#295]). This has been backported to v1. ([#298]) + + ### v1.0.1 [[code][c1.0.1], [diff][d1.0.1]] [c1.0.1]: https://github.com/json5/json5/tree/v1.0.1 @@ -272,3 +287,6 @@ parser for the regular JSON format. [#108]: https://github.com/json5/json5/pull/108 [#134]: https://github.com/json5/json5/pull/134 [#154]: https://github.com/json5/json5/issues/154 +[#199]: https://github.com/json5/json5/issues/199 +[#295]: https://github.com/json5/json5/issues/295 +[#298]: https://github.com/json5/json5/pull/298 diff --git a/package-lock.json b/package-lock.json index 1e99c2ef..1154b0da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "json5", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index b51b7624..87f84a03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "json5", - "version": "1.0.1", + "version": "1.0.2", "description": "JSON for humans.", "main": "lib/index.js", "bin": "lib/cli.js", diff --git a/src/parse.js b/src/parse.js index 675d4c32..2d62b29c 100644 --- a/src/parse.js +++ b/src/parse.js @@ -42,12 +42,34 @@ export default function parse (text, reviver) { function internalize (holder, name, reviver) { const value = holder[name] if (value != null && typeof value === 'object') { - for (const key in value) { - const replacement = internalize(value, key, reviver) - if (replacement === undefined) { - delete value[key] - } else { - value[key] = replacement + if (Array.isArray(value)) { + for (let i = 0; i < value.length; i++) { + const key = String(i) + const replacement = internalize(value, key, reviver) + if (replacement === undefined) { + delete value[key] + } else { + Object.defineProperty(value, key, { + value: replacement, + writable: true, + enumerable: true, + configurable: true, + }) + } + } + } else { + for (const key in value) { + const replacement = internalize(value, key, reviver) + if (replacement === undefined) { + delete value[key] + } else { + Object.defineProperty(value, key, { + value: replacement, + writable: true, + enumerable: true, + configurable: true, + }) + } } } } @@ -973,7 +995,12 @@ function push () { if (Array.isArray(parent)) { parent.push(value) } else { - parent[key] = value + Object.defineProperty(parent, key, { + value, + writable: true, + enumerable: true, + configurable: true, + }) } } diff --git a/test/parse.js b/test/parse.js index 9d4f4e02..7229f038 100644 --- a/test/parse.js +++ b/test/parse.js @@ -33,6 +33,11 @@ describe('JSON5', () => { assert.deepStrictEqual(JSON5.parse('{\\u0061\\u0062:1,\\u0024\\u005F:2,\\u005F\\u0024:3}'), {ab: 1, $_: 2, _$: 3}) }) + it('preserves __proto__ property names', () => { + // eslint-disable-next-line no-proto + assert.strictEqual(JSON5.parse('{"__proto__":1}').__proto__, 1) + }) + it('parses multiple properties', () => { assert.deepStrictEqual(JSON5.parse('{abc:1,def:2}'), {abc: 1, def: 2}) })