From 2f239a005511c06c2f385b6e3c53292aad612f31 Mon Sep 17 00:00:00 2001 From: Tom Harrison Date: Fri, 14 Jan 2022 13:13:07 -0500 Subject: [PATCH 1/4] Fix as proposed by Johns Hopkins researchers --- index.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.js b/index.js index 115a37c..43f274b 100644 --- a/index.js +++ b/index.js @@ -61,6 +61,8 @@ exports.parse = function(str){ var parts = pairs[i].split('='); var key = decode(parts[0]); var m; + // Sanitize keys to uppercase to mitigate client-side prototype pollution + key && ["__proto__", "constructor", "prototype"].includes(key.toLowerCase()) ? key.toUpperCase() : key if (m = pattern.exec(key)) { obj[m[1]] = obj[m[1]] || []; From af6fadd1b79c3d0f9a4c4eb46849c3869d3ba7e2 Mon Sep 17 00:00:00 2001 From: Tom Harrison Date: Fri, 14 Jan 2022 13:49:15 -0500 Subject: [PATCH 2/4] actually modify the key value --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 43f274b..b2ca65f 100644 --- a/index.js +++ b/index.js @@ -62,7 +62,9 @@ exports.parse = function(str){ var key = decode(parts[0]); var m; // Sanitize keys to uppercase to mitigate client-side prototype pollution - key && ["__proto__", "constructor", "prototype"].includes(key.toLowerCase()) ? key.toUpperCase() : key + if (key && ["__proto__", "constructor", "prototype"].includes(key.toLowerCase())) { + key = key.toUpperCase() + } if (m = pattern.exec(key)) { obj[m[1]] = obj[m[1]] || []; From 5553a569463fc44fb93c2cbb0afa7a1cb2d92e69 Mon Sep 17 00:00:00 2001 From: David Lumley Date: Fri, 14 Jan 2022 13:03:24 -0800 Subject: [PATCH 3/4] use indexOf instead of includes for better compatibility (#2) --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index b2ca65f..06ceee0 100644 --- a/index.js +++ b/index.js @@ -62,7 +62,7 @@ exports.parse = function(str){ var key = decode(parts[0]); var m; // Sanitize keys to uppercase to mitigate client-side prototype pollution - if (key && ["__proto__", "constructor", "prototype"].includes(key.toLowerCase())) { + if (key && ["__proto__", "constructor", "prototype"].indexOf(key.toLowerCase()) > -1) { key = key.toUpperCase() } From 8e875c2241d98286899394b08276c2cfcd7a05cd Mon Sep 17 00:00:00 2001 From: David Lumley Date: Fri, 14 Jan 2022 17:20:20 -0800 Subject: [PATCH 4/4] ensure when we assign to `obj` that we use the sanitized key (#3) --- index.js | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 06ceee0..b051efd 100644 --- a/index.js +++ b/index.js @@ -40,6 +40,22 @@ var decode = function(str) { } } +/** + * Ensure any potential prototype pollution can be sanitized. + * + * @param {String} str + * @return {String} + * @api public + */ + +var sanitizeObjKey = function(str) { + if (str && ["__proto__", "constructor", "prototype"].indexOf(str.toLowerCase()) > -1) { + return str.toUpperCase() + } + + return str; +} + /** * Parse the given query `str`. * @@ -59,20 +75,17 @@ exports.parse = function(str){ var pairs = str.split('&'); for (var i = 0; i < pairs.length; i++) { var parts = pairs[i].split('='); - var key = decode(parts[0]); + var key = sanitizeObjKey(decode(parts[0])); var m; - // Sanitize keys to uppercase to mitigate client-side prototype pollution - if (key && ["__proto__", "constructor", "prototype"].indexOf(key.toLowerCase()) > -1) { - key = key.toUpperCase() - } if (m = pattern.exec(key)) { - obj[m[1]] = obj[m[1]] || []; - obj[m[1]][m[2]] = decode(parts[1]); + var objectKey = sanitizeObjKey(m[1]) + obj[objectKey] = obj[objectKey] || []; + obj[objectKey][m[2]] = decode(parts[1]); continue; } - obj[parts[0]] = null == parts[1] + obj[key] = null == parts[1] ? '' : decode(parts[1]); }