From: Colin Casey Date: Mon, 5 Jun 2023 12:13:22 -0300 Subject: Prevent prototype pollution in cookie memstore (#283) All occurrences of new object creation in `memstore.js` have been changed from `{}` (i.e.; `Object.create(Object.prototype)` to `Object.create(null)` so that we are using object instances that do not have a prototype property that can be polluted. Origin: https://github.com/salesforce/tough-cookie/commit/12d474791bb856004e858fdb1c47b7608d09cf6e Bug: https://security.snyk.io/vuln/SNYK-JS-TOUGHCOOKIE-5672873 Bug: https://github.com/salesforce/tough-cookie/issues/282 Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-26136 --- lib/memstore.js | 6 +++--- test/cookie_jar_test.js | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/memstore.js b/lib/memstore.js index 89ceb69..3486a6f 100644 --- a/lib/memstore.js +++ b/lib/memstore.js @@ -36,7 +36,7 @@ var util = require('util'); function MemoryCookieStore() { Store.call(this); - this.idx = {}; + this.idx = Object.create(null); } util.inherits(MemoryCookieStore, Store); exports.MemoryCookieStore = MemoryCookieStore; @@ -109,10 +109,10 @@ MemoryCookieStore.prototype.findCookies = function(domain, path, cb) { MemoryCookieStore.prototype.putCookie = function(cookie, cb) { if (!this.idx[cookie.domain]) { - this.idx[cookie.domain] = {}; + this.idx[cookie.domain] = Object.create(null); } if (!this.idx[cookie.domain][cookie.path]) { - this.idx[cookie.domain][cookie.path] = {}; + this.idx[cookie.domain][cookie.path] = Object.create(null); } this.idx[cookie.domain][cookie.path][cookie.key] = cookie; cb(null); diff --git a/test/cookie_jar_test.js b/test/cookie_jar_test.js index 9d0691d..26ad159 100644 --- a/test/cookie_jar_test.js +++ b/test/cookie_jar_test.js @@ -480,4 +480,29 @@ vows } } }) + .addBatch({ + "Issue #282 - Prototype pollution": { + "when setting a cookie with the domain __proto__": { + topic: function() { + const jar = new tough.CookieJar(undefined, { + rejectPublicSuffixes: false + }); + // try to pollute the prototype + jar.setCookieSync( + "Slonser=polluted; Domain=__proto__; Path=/notauth", + "https://__proto__/admin" + ); + jar.setCookieSync( + "Auth=Lol; Domain=google.com; Path=/notauth", + "https://google.com/" + ); + this.callback(); + }, + "results in a cookie that is not affected by the attempted prototype pollution": function() { + const pollutedObject = {}; + assert(pollutedObject["/notauth"] === undefined); + } + } + } + }) .export(module);