You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
2.0 KiB

4 years ago
'use strict';
const internals = {
suspectRx: /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*\:/
};
exports.parse = function (text, reviver, options) {
// Normalize arguments
if (!options) {
if (reviver &&
typeof reviver === 'object') {
options = reviver;
reviver = undefined;
}
else {
options = {};
}
}
// Parse normally, allowing exceptions
const obj = JSON.parse(text, reviver);
// options.protoAction: 'error' (default) / 'remove' / 'ignore'
if (options.protoAction === 'ignore') {
return obj;
}
// Ignore null and non-objects
if (!obj ||
typeof obj !== 'object') {
return obj;
}
// Check original string for potential exploit
if (!text.match(internals.suspectRx)) {
return obj;
}
// Scan result for proto keys
exports.scan(obj, options);
return obj;
};
exports.scan = function (obj, options) {
options = options || {};
let next = [obj];
while (next.length) {
const nodes = next;
next = [];
for (const node of nodes) {
if (Object.prototype.hasOwnProperty.call(node, '__proto__')) { // Avoid calling node.hasOwnProperty directly
if (options.protoAction !== 'remove') {
throw new SyntaxError('Object contains forbidden prototype property');
}
delete node.__proto__;
}
for (const key in node) {
const value = node[key];
if (value &&
typeof value === 'object') {
next.push(node[key]);
}
}
}
}
};
exports.safeParse = function (text, reviver) {
try {
return exports.parse(text, reviver);
}
catch (ignoreError) {
return null;
}
};