diff --git a/index.js b/index.js index 60186e3..7efb49e 100644 --- a/index.js +++ b/index.js @@ -119,6 +119,21 @@ function escapeFunctionBody(str) { return str; } +// Keep in sync with the options read in `serialize()` below. +var OPTION_NAMES = ['space', 'isJSON', 'unsafe', 'ignoreFunction']; + +// Copy only the options set on the object itself, so a value inherited from a +// polluted `Object.prototype` (e.g. `unsafe`) can't turn off escaping. +function ownOptions(options) { + var result = Object.create(null); + for (var i = 0; i < OPTION_NAMES.length; i++) { + if (Object.prototype.hasOwnProperty.call(options, OPTION_NAMES[i])) { + result[OPTION_NAMES[i]] = options[OPTION_NAMES[i]]; + } + } + return result; +} + function generateUID() { var bytes = crypto.getRandomValues(new Uint8Array(UID_LENGTH)); var result = ''; @@ -136,6 +151,8 @@ module.exports = function serialize(obj, options) { options = {space: options}; } + options = ownOptions(options); + var functions = []; var regexps = []; var dates = []; diff --git a/test/unit/serialize.js b/test/unit/serialize.js index 1b10700..63a626f 100644 --- a/test/unit/serialize.js +++ b/test/unit/serialize.js @@ -928,6 +928,33 @@ describe('serialize( obj )', function () { '{"num":123,"str":"str"}' ); }); + + it('should ignore options inherited from `Object.prototype`', function () { + var value = { + html: '', + fn: function () { return ''; }, + map: new Map([['html', '']]) + }; + var expected = serialize(value); + var expectedWithSpace = serialize(value, 2); + + try { + Object.prototype.unsafe = true; + Object.prototype.isJSON = true; + Object.prototype.ignoreFunction = true; + Object.prototype.space = 2; + + strictEqual(serialize(value), expected); + strictEqual(serialize(value, {}), expected); + strictEqual(serialize(value, true), expected); + strictEqual(serialize(value, 2), expectedWithSpace); + } finally { + delete Object.prototype.unsafe; + delete Object.prototype.isJSON; + delete Object.prototype.ignoreFunction; + delete Object.prototype.space; + } + }); }); describe('ignoring functions without changing the input', function () {