Last active
August 6, 2018 16:00
-
-
Save mikesamuel/d7396bf3396bc793d585b1dd40bfbfd0 to your computer and use it in GitHub Desktop.
Monkeypatching JSON to distinguish parsed objects from user-code created objects
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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