Skip to content

Instantly share code, notes, and snippets.

@mikesamuel
Last active August 6, 2018 16:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikesamuel/d7396bf3396bc793d585b1dd40bfbfd0 to your computer and use it in GitHub Desktop.
Save mikesamuel/d7396bf3396bc793d585b1dd40bfbfd0 to your computer and use it in GitHub Desktop.
Monkeypatching JSON to distinguish parsed objects from user-code created objects
/**
* A symbol that should only be added to objects whose
* properties come from an external string, or which include
* uncherry-picked properties from such an object.
*/
const PARSER_OUTPUT_SYMBOL = Symbol('parserOutput');
function markingReviver(_, value) {
"use strict";
if (value && typeof value === 'object') {
// HACK: This might fail if optReviver freezes values.
// Could use a WeakSet instead but then tainting won't follow
// mass assignments like Object.assign.
value[PARSER_OUTPUT_SYMBOL] = true;
// This affect arrays. That seems fine.
}
return value;
}
// Monkeypatch JSON.parse to add a symbol to structured values
const jsonParseTrusted = JSON.parse;
JSON.parse = function (jsonString, optReviver) {
const reviver = typeof optReviver === 'function'
? ((key, value) => markingReviver(key, optReviver(key, value)))
: markingReviver;
return jsonParseTrusted(jsonString, reviver);
};
// TODO: Other common JavaScript object parsing vectors.
// * XHR response with type application/json?
// * JSON injected into a <script> body by a server-side template.
/**
* True if x was parsed from external strings or was mass assigned (Object.assign)
* own properties from such an object.
*
* CAVEAT: If x might come from a different Realm, which has its own
* monkeypatched JSON, then this would have to change to recognize other
* properties.
*/
function isParsedObject(x) {
return x && typeof x === 'object'
&& Object.hasOwnProperty.call(x, PARSER_OUTPUT_SYMBOL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment