Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Prevent prototype pollution while parsing query strings (#2494)
* Prevent prototype pollution while parsing query strings

* Update changelog [skip ci]
  • Loading branch information
dead-claudia committed Jul 27, 2019
1 parent 48e7fd1 commit 97fa178
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/change-log.md
Expand Up @@ -17,6 +17,7 @@
### Upcoming...
- Ensure vnodes are removed correctly in the face of `onbeforeremove` resolving after new nodes are added ([#2492](https://github.com/MithrilJS/mithril.js/pull/2492) [@isiahmeadows](https://github.com/isiahmeadows))
- Fix prototype pollution vulnerability in `m.parseQueryString` ([#2494](https://github.com/MithrilJS/mithril.js/pull/2494) [@isiahmeadows](https://github.com/isiahmeadows))
-->

Expand Down
14 changes: 10 additions & 4 deletions querystring/parse.js
@@ -1,7 +1,5 @@
"use strict"

// The extra `data` parameter is for if you want to append to an existing
// parameters object.
module.exports = function(string) {
if (string === "" || string == null) return {}
if (string.charAt(0) === "?") string = string.slice(1)
Expand Down Expand Up @@ -29,9 +27,17 @@ module.exports = function(string) {
}
level = counters[key]++
}
// Disallow direct prototype pollution
else if (level === "__proto__") break
if (isValue) cursor[level] = value
else if (cursor[level] == null) cursor[level] = isNumber ? [] : {}
cursor = cursor[level]
else {
// Read own properties exclusively to disallow indirect
// prototype pollution
value = Object.getOwnPropertyDescriptor(cursor, level)
if (value != null) value = value.value
if (value == null) value = cursor[level] = isNumber ? [] : {}
}
cursor = value
}
}
return data
Expand Down
12 changes: 12 additions & 0 deletions querystring/tests/test-parseQueryString.js
Expand Up @@ -97,4 +97,16 @@ o.spec("parseQueryString", function() {
var data = parseQueryString("a=1&b=2&a=3")
o(data).deepEquals({a: "3", b: "2"})
})
o("doesn't pollute prototype directly, censors `__proto__`", function() {
var prev = Object.prototype.toString
var data = parseQueryString("a=b&__proto__%5BtoString%5D=123")
o(Object.prototype.toString).equals(prev)
o(data).deepEquals({a: "b"})
})
o("doesn't pollute prototype indirectly, retains `constructor`", function() {
var prev = Object.prototype.toString
var data = parseQueryString("constructor%5Bprototype%5D%5BtoString%5D=123")
o(Object.prototype.toString).equals(prev)
o(data).deepEquals({a: "b"})
})
})

0 comments on commit 97fa178

Please sign in to comment.