From 1729e7544b356c188d95d9f1b501ee77d53f9693 Mon Sep 17 00:00:00 2001 From: CBL-Mariner-Bot <75509084+CBL-Mariner-Bot@users.noreply.github.com> Date: Wed, 23 Oct 2024 14:47:18 -0400 Subject: [PATCH] [AUTO-CHERRYPICK] Patch Reaper for multiple CVEs - branch main (#10735) Co-authored-by: Rohit Rawat Co-authored-by: jslobodzian Co-authored-by: Riken Maharjan --- SPECS/reaper/CVE-2024-43799.patch | 27 +++++ SPECS/reaper/CVE-2024-43800.patch | 26 ++++ SPECS/reaper/CVE-2024-45296.patch | 190 ++++++++++++++++++++++++++++++ SPECS/reaper/CVE-2024-47764.patch | 116 ++++++++++++++++++ SPECS/reaper/CVE-2024-48949.patch | 23 ++++ SPECS/reaper/reaper.spec | 19 ++- 6 files changed, 398 insertions(+), 3 deletions(-) create mode 100644 SPECS/reaper/CVE-2024-43799.patch create mode 100644 SPECS/reaper/CVE-2024-43800.patch create mode 100644 SPECS/reaper/CVE-2024-45296.patch create mode 100644 SPECS/reaper/CVE-2024-47764.patch create mode 100644 SPECS/reaper/CVE-2024-48949.patch diff --git a/SPECS/reaper/CVE-2024-43799.patch b/SPECS/reaper/CVE-2024-43799.patch new file mode 100644 index 00000000000..f264afd7713 --- /dev/null +++ b/SPECS/reaper/CVE-2024-43799.patch @@ -0,0 +1,27 @@ +From 6309d1f68103ef27c565cf58ab03f9ed32ff631c Mon Sep 17 00:00:00 2001 +From: Rohit Rawat +Date: Thu, 10 Oct 2024 13:44:09 +0000 +Subject: [PATCH] CVE-2024-43799 + +from: https://github.com/pillarjs/send/commit/ae4f2989491b392ae2ef3b0015a019770ae65d35 +--- + send/index.js | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/ui/node_modules/send/index.js b/src/ui/node_modules/send/index.js +index 89afd7e5..768f8ca6 100644 +--- a/src/ui/node_modules/send/index.js ++++ b/src/ui/node_modules/send/index.js +@@ -482,8 +482,7 @@ SendStream.prototype.redirect = function redirect (path) { + } + + var loc = encodeUrl(collapseLeadingSlashes(this.path + '/')) +- var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + +- escapeHtml(loc) + '') ++ var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + escapeHtml(loc)) + + // redirect + res.statusCode = 301 +-- +2.39.4 + diff --git a/SPECS/reaper/CVE-2024-43800.patch b/SPECS/reaper/CVE-2024-43800.patch new file mode 100644 index 00000000000..3a8cd6b2690 --- /dev/null +++ b/SPECS/reaper/CVE-2024-43800.patch @@ -0,0 +1,26 @@ +From cb67c9a152a1e2d8ffb3a74c504d4c9a845bf4dc Mon Sep 17 00:00:00 2001 +From: Rohit Rawat +Date: Mon, 14 Oct 2024 07:18:16 +0000 +Subject: [PATCH] serve-static don't pass untrusted user input + +--- + serve-static/index.js | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/ui/node_modules/serve-static/index.js b/src/ui/node_modules/serve-static/index.js +index b7d3984c..3f3e64e9 100644 +--- a/src/ui/node_modules/serve-static/index.js ++++ b/src/ui/node_modules/serve-static/index.js +@@ -195,8 +195,7 @@ function createRedirectDirectoryListener () { + + // reformat the URL + var loc = encodeUrl(url.format(originalUrl)) +- var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + +- escapeHtml(loc) + '') ++ var doc = createHtmlDocument('Redirecting', 'Redirecting to ' + escapeHtml(loc)) + + // send redirect response + res.statusCode = 301 +-- +2.39.4 + diff --git a/SPECS/reaper/CVE-2024-45296.patch b/SPECS/reaper/CVE-2024-45296.patch new file mode 100644 index 00000000000..8528fbe296b --- /dev/null +++ b/SPECS/reaper/CVE-2024-45296.patch @@ -0,0 +1,190 @@ +From 6f1351c1c631d01ced7d2461c5eeee4552865306 Mon Sep 17 00:00:00 2001 +From: Rohit Rawat +Date: Thu, 10 Oct 2024 12:14:51 +0000 +Subject: [PATCH] Upgrade path-to-regexp from 0.1.7 to 0.1.11 + +CVE-2024-45296 was fixed in https://github.com/pillarjs/path-to-regexp/pull/320 +which was released in version 0.1.11 +--- + path-to-regexp/index.js | 103 ++++++++++++++++++++++++---------------- + 1 file changed, 62 insertions(+), 41 deletions(-) + +diff --git a/src/ui/node_modules/path-to-regexp/index.js b/src/ui/node_modules/path-to-regexp/index.js +index 500d1dad..39b7caac 100644 +--- a/src/ui/node_modules/path-to-regexp/index.js ++++ b/src/ui/node_modules/path-to-regexp/index.js +@@ -1,13 +1,13 @@ + /** +- * Expose `pathtoRegexp`. ++ * Expose `pathToRegexp`. + */ + +-module.exports = pathtoRegexp; ++module.exports = pathToRegexp; + + /** + * Match matching groups in a regular expression. + */ +-var MATCHING_GROUP_REGEXP = /\((?!\?)/g; ++var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g; + + /** + * Normalize the given path string, +@@ -25,22 +25,27 @@ var MATCHING_GROUP_REGEXP = /\((?!\?)/g; + * @api private + */ + +-function pathtoRegexp(path, keys, options) { ++function pathToRegexp(path, keys, options) { + options = options || {}; + keys = keys || []; + var strict = options.strict; + var end = options.end !== false; + var flags = options.sensitive ? '' : 'i'; ++ var lookahead = options.lookahead !== false; + var extraOffset = 0; + var keysOffset = keys.length; + var i = 0; + var name = 0; ++ var pos = 0; ++ var backtrack = ''; + var m; + + if (path instanceof RegExp) { + while (m = MATCHING_GROUP_REGEXP.exec(path.source)) { ++ if (m[0][0] === '\\') continue; ++ + keys.push({ +- name: name++, ++ name: m[1] || name++, + optional: false, + offset: m.index + }); +@@ -54,20 +59,51 @@ function pathtoRegexp(path, keys, options) { + // the same keys and options instance into every generation to get + // consistent matching groups before we join the sources together. + path = path.map(function (value) { +- return pathtoRegexp(value, keys, options).source; ++ return pathToRegexp(value, keys, options).source; + }); + +- return new RegExp('(?:' + path.join('|') + ')', flags); ++ return new RegExp(path.join('|'), flags); ++ } ++ ++ if (typeof path !== 'string') { ++ throw new TypeError('path must be a string, array of strings, or regular expression'); + } + +- path = ('^' + path + (strict ? '' : path[path.length - 1] === '/' ? '?' : '/?')) +- .replace(/\/\(/g, '/(?:') +- .replace(/([\/\.])/g, '\\$1') +- .replace(/(\\\/)?(\\\.)?:(\w+)(\(.*?\))?(\*)?(\?)?/g, function (match, slash, format, key, capture, star, optional, offset) { ++ path = path.replace( ++ /\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g, ++ function (match, slash, format, key, capture, star, optional, offset) { ++ pos = offset + match.length; ++ ++ if (match[0] === '\\') { ++ backtrack += match; ++ return match; ++ } ++ ++ if (match === '.') { ++ backtrack += '\\.'; ++ extraOffset += 1; ++ return '\\.'; ++ } ++ ++ backtrack = slash || format ? '' : path.slice(pos, offset); ++ ++ if (match === '*') { ++ extraOffset += 3; ++ return '(.*)'; ++ } ++ ++ if (match === '/(') { ++ backtrack += '/'; ++ extraOffset += 2; ++ return '/(?:'; ++ } ++ + slash = slash || ''; +- format = format || ''; +- capture = capture || '([^\\/' + format + ']+?)'; ++ format = format ? '\\.' : ''; + optional = optional || ''; ++ capture = capture ? ++ capture.replace(/\\.|\*/, function (m) { return m === '*' ? '(.*)' : m; }) : ++ (backtrack ? '((?:(?!/|' + backtrack + ').)+?)' : '([^/' + format + ']+?)'); + + keys.push({ + name: key, +@@ -75,41 +111,20 @@ function pathtoRegexp(path, keys, options) { + offset: offset + extraOffset + }); + +- var result = '' +- + (optional ? '' : slash) +- + '(?:' +- + format + (optional ? slash : '') + capture +- + (star ? '((?:[\\/' + format + '].+?)?)' : '') ++ var result = '(?:' ++ + format + slash + capture ++ + (star ? '((?:[/' + format + '].+?)?)' : '') + + ')' + + optional; + + extraOffset += result.length - match.length; + + return result; +- }) +- .replace(/\*/g, function (star, index) { +- var len = keys.length +- +- while (len-- > keysOffset && keys[len].offset > index) { +- keys[len].offset += 3; // Replacement length minus asterisk length. +- } +- +- return '(.*)'; + }); + + // This is a workaround for handling unnamed matching groups. + while (m = MATCHING_GROUP_REGEXP.exec(path)) { +- var escapeCount = 0; +- var index = m.index; +- +- while (path.charAt(--index) === '\\') { +- escapeCount++; +- } +- +- // It's possible to escape the bracket. +- if (escapeCount % 2 === 1) { +- continue; +- } ++ if (m[0][0] === '\\') continue; + + if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) { + keys.splice(keysOffset + i, 0, { +@@ -122,8 +137,14 @@ function pathtoRegexp(path, keys, options) { + i++; + } + ++ path += strict ? '' : path[path.length - 1] === '/' ? '?' : '/?'; ++ + // If the path is non-ending, match until the end or a slash. +- path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?=\\/|$)')); ++ if (end) { ++ path += '$'; ++ } else if (path[path.length - 1] !== '/') { ++ path += lookahead ? '(?=/|$)' : '(?:/|$)'; ++ } + +- return new RegExp(path, flags); +-}; ++ return new RegExp('^' + path, flags); ++}; +\ No newline at end of file +-- +2.39.4 + diff --git a/SPECS/reaper/CVE-2024-47764.patch b/SPECS/reaper/CVE-2024-47764.patch new file mode 100644 index 00000000000..6c5880950c8 --- /dev/null +++ b/SPECS/reaper/CVE-2024-47764.patch @@ -0,0 +1,116 @@ +From 9ca5ddf291fcd82a34925e1584bb7356a554fbe3 Mon Sep 17 00:00:00 2001 +From: Rohit Rawat +Date: Mon, 14 Oct 2024 09:44:29 +0000 +Subject: [PATCH] narrow the validation cookies to match RFC6265 + +--- + cookie/index.js | 64 ++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 55 insertions(+), 9 deletions(-) + +diff --git a/src/ui/node_modules/cookie/index.js b/src/ui/node_modules/cookie/index.js +index 03d4c386..5e8c805d 100644 +--- a/src/ui/node_modules/cookie/index.js ++++ b/src/ui/node_modules/cookie/index.js +@@ -23,14 +23,60 @@ exports.serialize = serialize; + var __toString = Object.prototype.toString + + /** +- * RegExp to match field-content in RFC 7230 sec 3.2 ++ * RegExp to match cookie-name in RFC 6265 sec 4.1.1 ++ * This refers out to the obsoleted definition of token in RFC 2616 sec 2.2 ++ * which has been replaced by the token definition in RFC 7230 appendix B. + * +- * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ] +- * field-vchar = VCHAR / obs-text +- * obs-text = %x80-FF ++ * cookie-name = token ++ * token = 1*tchar ++ * tchar = "!" / "#" / "$" / "%" / "&" / "'" / ++ * "*" / "+" / "-" / "." / "^" / "_" / ++ * "`" / "|" / "~" / DIGIT / ALPHA + */ + +-var fieldContentRegExp = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/; ++var cookieNameRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/; ++ ++/** ++ * RegExp to match cookie-value in RFC 6265 sec 4.1.1 ++ * ++ * cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE ) ++ * cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E ++ * ; US-ASCII characters excluding CTLs, ++ * ; whitespace DQUOTE, comma, semicolon, ++ * ; and backslash ++ */ ++ ++var cookieValueRegExp = /^("?)[\u0021\u0023-\u002B\u002D-\u003A\u003C-\u005B\u005D-\u007E]*\1$/; ++ ++/** ++ * RegExp to match domain-value in RFC 6265 sec 4.1.1 ++ * ++ * domain-value = ++ * ; defined in [RFC1034], Section 3.5, as ++ * ; enhanced by [RFC1123], Section 2.1 ++ * =