New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add __proto__ to objects and arrays #296
Conversation
Nope, I'm still confused. The test is asserting that you can overwrite proto from JSON5.parse(). How is this PR fixing the prototype pollution problem instead of marking it as a feature? |
@jdmarshall The confusion is understandable. The bug was reported in #199 without the realization that it was also a vulnerability at the time, and #200 was written to address that bug but not merged because it was a borderline breaking change. Once the vulnerability aspect was realized, the fix in #200 was recreated in this PR and merged, but it did not contain any information about the vulnerability as to avoid potential zero-day exploits. If you read the discussions in #199 and #200, you'll see that the issue was never to prevent JSON5 from representing an object with a property named Normally in JavaScript, the const data = {foo: 1}
data.__proto__ = {bar: 2} // data's prototype is now {bar:2}
data.foo // returns 1
data.bar // returns 2 because bar is found up data's prototype chain
Object.keys(data) // returns ['foo'] because bar only exists on data's prototype So you can see how setting In JavaScript, you can also set an object's prototype while constructing the object like this: const data = {
foo: 1,
__proto__: { bar: 2 }
}
data.foo // returns 1
data.bar // returns 2 because bar is found up data's prototype chain
Object.keys(data) // returns ['foo'] because bar only exists on data's prototype However this does not work in JSON: const json = `{
"foo": 1,
"__proto__": { "bar": 2 }
}`
const data = JSON.parse(json)
data.foo // returns 1
data.bar // returns undefined because bar is neither found on data nor up its prototype chain
Object.keys(data) // returns ['foo', '__proto__'] because __proto__ is just a regular property
data.__proto__ // returns {bar: 2} but it does not represent data's prototype
Object.getPrototypeOf(data) // returns {} (the default) because data's prototype
// was not set via the __proto__ property The bug was that JSON5 was behaving like JavaScript when it should have been behaving like JSON. By making JSON5 use Now it might seem like setting |
^ This is such a fantastic explanation, @jordanbtucker. Thank you for taking the time to write it! ❤️ |
So does this prevent |
No, it does not prevent using |
Closes #199