[AUTO-CHERRYPICK] reaper: address CVE-2024-4068 - branch main (#9298)

Co-authored-by: Archana Choudhary <36061892+arc9693@users.noreply.github.com>
This commit is contained in:
CBL-Mariner-Bot 2024-06-04 22:35:47 -07:00 коммит произвёл GitHub
Родитель d03e5fd81f
Коммит 5f33b4845c
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
6 изменённых файлов: 14 добавлений и 899 удалений

Просмотреть файл

@ -1,185 +0,0 @@
Fixes CVE-2018-11694: https://nvd.nist.gov/vuln/detail/CVE-2018-11694,
which is a vulnerability in libsass module version 3.5.5
[Even though NVD lists CPE upto including 3.5.4, 3.5.5 also contains the
vulnerable code.]
This patch adpats fixes in libsass sources for the mentioned CVE:
Patch: https://github.com/sass/libsass/pull/2760
Patch: https://github.com/sass/libsass/pull/2762
Issue: https://github.com/sass/libsass/issues/2663
From 2214ae16d9d9ec4c102c56a53ff5fb8d25217dd4 Mon Sep 17 00:00:00 2001
From: <redacted>
Date: Fri, 4 Aug 2023 15:04:06 +0530
Subject: [PATCH] Disallow parent selectors in selector-append.
Fix crash in selector-append('.x~~', 'a')
---
.../node-sass/src/libsass/src/functions.cpp | 26 +++++++++++--------
.../node-sass/src/libsass/src/parser.cpp | 14 +++++-----
.../node-sass/src/libsass/src/parser.hpp | 13 +++++-----
3 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/node_modules/node-sass/src/libsass/src/functions.cpp b/node_modules/node-sass/src/libsass/src/functions.cpp
index c9999fc3..4227d4de 100644
--- a/node_modules/node-sass/src/libsass/src/functions.cpp
+++ b/node_modules/node-sass/src/libsass/src/functions.cpp
@@ -240,13 +240,13 @@ namespace Sass {
std::stringstream msg;
msg << argname << ": null is not a valid selector: it must be a string,\n";
msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'";
- error(msg.str(), pstate, traces);
+ error(msg.str(), exp->pstate(), traces);
}
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
str->quote_mark(0);
}
std::string exp_src = exp->to_string(ctx.c_options);
- return Parser::parse_selector(exp_src.c_str(), ctx, traces);
+ return Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src);
}
template <>
@@ -255,13 +255,13 @@ namespace Sass {
if (exp->concrete_type() == Expression::NULL_VAL) {
std::stringstream msg;
msg << argname << ": null is not a string for `" << function_name(sig) << "'";
- error(msg.str(), pstate, traces);
+ error(msg.str(), exp->pstate(), traces);
}
if (String_Constant_Ptr str = Cast<String_Constant>(exp)) {
str->quote_mark(0);
}
std::string exp_src = exp->to_string(ctx.c_options);
- Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces);
+ Selector_List_Obj sel_list = Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src);
if (sel_list->length() == 0) return NULL;
Complex_Selector_Obj first = sel_list->first();
if (!first->tail()) return first->head();
@@ -1970,7 +1970,7 @@ namespace Sass {
str->quote_mark(0);
}
std::string exp_src = exp->to_string(ctx.c_options);
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
+ Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces, exp->pstate(), pstate.src);
parsedSelectors.push_back(sel);
}
@@ -2023,7 +2023,9 @@ namespace Sass {
str->quote_mark(0);
}
std::string exp_src = exp->to_string();
- Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces);
+ Selector_List_Obj sel = Parser::parse_selector(exp_src.c_str(), ctx, traces,
+ exp->pstate(), pstate.src,
+ /*allow_parent=*/false);
parsedSelectors.push_back(sel);
}
@@ -2077,11 +2079,13 @@ namespace Sass {
// TODO: Add check for namespace stuff
- // append any selectors in childSeq's head
- parentSeqClone->innermost()->head()->concat(base->head());
-
- // Set parentSeqClone new tail
- parentSeqClone->innermost()->tail( base->tail() );
+ Complex_Selector_Ptr lastComponent = parentSeqClone->mutable_last();
+ if (lastComponent->head() == nullptr) {
+ std::string msg = "Parent \"" + parentSeqClone->to_string() + "\" is incompatible with \"" + base->to_string() + "\"";
+ error(msg, pstate, traces);
+ }
+ lastComponent->head()->concat(base->head());
+ lastComponent->tail(base->tail());
newElements.push_back(parentSeqClone);
}
diff --git a/node_modules/node-sass/src/libsass/src/parser.cpp b/node_modules/node-sass/src/libsass/src/parser.cpp
index 28fe0224..8d916269 100644
--- a/node_modules/node-sass/src/libsass/src/parser.cpp
+++ b/node_modules/node-sass/src/libsass/src/parser.cpp
@@ -30,11 +30,11 @@ namespace Sass {
using namespace Constants;
using namespace Prelexer;
- Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
+ Parser Parser::from_c_str(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
pstate.offset.column = 0;
pstate.offset.line = 0;
- Parser p(ctx, pstate, traces);
+ Parser p(ctx, pstate, traces, allow_parent);
p.source = source ? source : beg;
p.position = beg ? beg : p.source;
p.end = p.position + strlen(p.position);
@@ -44,11 +44,11 @@ namespace Sass {
return p;
}
- Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
+ Parser Parser::from_c_str(const char* beg, const char* end, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
pstate.offset.column = 0;
pstate.offset.line = 0;
- Parser p(ctx, pstate, traces);
+ Parser p(ctx, pstate, traces, allow_parent);
p.source = source ? source : beg;
p.position = beg ? beg : p.source;
p.end = end ? end : p.position + strlen(p.position);
@@ -66,10 +66,9 @@ namespace Sass {
pstate.offset.line = 0;
}
- Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source)
+ Selector_List_Obj Parser::parse_selector(const char* beg, Context& ctx, Backtraces traces, ParserState pstate, const char* source, bool allow_parent)
{
- Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source);
- // ToDo: ruby sass errors on parent references
+ Parser p = Parser::from_c_str(beg, ctx, traces, pstate, source, allow_parent);
// ToDo: remap the source-map entries somehow
return p.parse_selector_list(false);
}
@@ -818,6 +817,7 @@ namespace Sass {
// parse parent selector
else if (lex< exactly<'&'> >(false))
{
+ if (!allow_parent) error("Parent selectors aren't allowed here.");
// this produces a linefeed!?
seq->has_parent_reference(true);
seq->append(SASS_MEMORY_NEW(Parent_Selector, pstate));
diff --git a/node_modules/node-sass/src/libsass/src/parser.hpp b/node_modules/node-sass/src/libsass/src/parser.hpp
index d2a6ddc1..2371dfca 100644
--- a/node_modules/node-sass/src/libsass/src/parser.hpp
+++ b/node_modules/node-sass/src/libsass/src/parser.hpp
@@ -48,23 +48,24 @@ namespace Sass {
Backtraces traces;
size_t indentation;
size_t nestings;
+ bool allow_parent;
Token lexed;
- Parser(Context& ctx, const ParserState& pstate, Backtraces traces)
+ Parser(Context& ctx, const ParserState& pstate, Backtraces traces, bool allow_parent = true)
: ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(),
source(0), position(0), end(0), before_token(pstate), after_token(pstate),
- pstate(pstate), traces(traces), indentation(0), nestings(0)
+ pstate(pstate), traces(traces), indentation(0), nestings(0), allow_parent(allow_parent)
{
stack.push_back(Scope::Root);
}
// static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
- static Parser from_c_str(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
- static Parser from_c_str(const char* beg, const char* end, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
- static Parser from_token(Token t, Context& ctx, Backtraces, ParserState pstate = ParserState("[TOKEN]"), const char* source = 0);
+ static Parser from_c_str(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
+ static Parser from_c_str(const char* beg, const char* end, Context& ctx, Backtraces, ParserState pstate = ParserState("[CSTRING]"), const char* source = nullptr, bool allow_parent = true);
+ static Parser from_token(Token t, Context& ctx, Backtraces, ParserState pstate = ParserState("[TOKEN]"), const char* source = nullptr);
// special static parsers to convert strings into certain selectors
- static Selector_List_Obj parse_selector(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[SELECTOR]"), const char* source = 0);
+ static Selector_List_Obj parse_selector(const char* src, Context& ctx, Backtraces, ParserState pstate = ParserState("[SELECTOR]"), const char* source = nullptr, bool allow_parent = true);
#ifdef __clang__

Просмотреть файл

@ -1,39 +0,0 @@
diff --git a/node_modules/loader-utils/lib/parseQuery.js b/node_modules/loader-utils/lib/parseQuery.js
index 12b3efc6..3dd7cb9b 100644
--- a/node_modules/loader-utils/lib/parseQuery.js
+++ b/node_modules/loader-utils/lib/parseQuery.js
@@ -26,7 +26,7 @@ function parseQuery(query) {
}
const queryArgs = query.split(/[,&]/g);
- const result = {};
+ const result = Object.create(null);
queryArgs.forEach((arg) => {
const idx = arg.indexOf('=');
diff --git a/node_modules/style-loader/node_modules/loader-utils/lib/parseQuery.js b/node_modules/style-loader/node_modules/loader-utils/lib/parseQuery.js
index fdca007d..4a201a2e 100644
--- a/node_modules/style-loader/node_modules/loader-utils/lib/parseQuery.js
+++ b/node_modules/style-loader/node_modules/loader-utils/lib/parseQuery.js
@@ -26,7 +26,7 @@ function parseQuery(query) {
}
const queryArgs = query.split(/[,&]/g);
- const result = {};
+ const result = Object.create(null);
queryArgs.forEach((arg) => {
const idx = arg.indexOf('=');
diff --git a/node_modules/url-loader/node_modules/loader-utils/lib/parseQuery.js b/node_modules/url-loader/node_modules/loader-utils/lib/parseQuery.js
index fdca007d..4a201a2e 100644
--- a/node_modules/url-loader/node_modules/loader-utils/lib/parseQuery.js
+++ b/node_modules/url-loader/node_modules/loader-utils/lib/parseQuery.js
@@ -26,7 +26,7 @@ function parseQuery(query) {
}
const queryArgs = query.split(/[,&]/g);
- const result = {};
+ const result = Object.create(null);
queryArgs.forEach((arg) => {
const idx = arg.indexOf('=');

Просмотреть файл

@ -1,451 +0,0 @@
diff --git a/node_modules/follow-redirects/index.js b/node_modules/follow-redirects/index.js
index 212f00a..3232a72 100644
--- a/node_modules/follow-redirects/index.js
+++ b/node_modules/follow-redirects/index.js
@@ -6,6 +6,29 @@ var Writable = require("stream").Writable;
var assert = require("assert");
var debug = require("./debug");
+// Whether to use the native URL object or the legacy url module
+var useNativeURL = false;
+try {
+ assert(new URL());
+}
+catch (error) {
+ useNativeURL = error.code === "ERR_INVALID_URL";
+}
+
+// URL fields to preserve in copy operations
+var preservedUrlFields = [
+ "auth",
+ "host",
+ "hostname",
+ "href",
+ "path",
+ "pathname",
+ "port",
+ "protocol",
+ "query",
+ "search",
+];
+
// Create handlers that pass events from native requests
var events = ["abort", "aborted", "connect", "error", "socket", "timeout"];
var eventHandlers = Object.create(null);
@@ -16,13 +39,19 @@ events.forEach(function (event) {
});
// Error types with codes
+var InvalidUrlError = createErrorType(
+ "ERR_INVALID_URL",
+ "Invalid URL",
+ TypeError
+);
var RedirectionError = createErrorType(
"ERR_FR_REDIRECTION_FAILURE",
"Redirected request failed"
);
var TooManyRedirectsError = createErrorType(
"ERR_FR_TOO_MANY_REDIRECTS",
- "Maximum number of redirects exceeded"
+ "Maximum number of redirects exceeded",
+ RedirectionError
);
var MaxBodyLengthExceededError = createErrorType(
"ERR_FR_MAX_BODY_LENGTH_EXCEEDED",
@@ -33,6 +62,9 @@ var WriteAfterEndError = createErrorType(
"write after end"
);
+// istanbul ignore next
+var destroy = Writable.prototype.destroy || noop;
+
// An HTTP(S) request that can be redirected
function RedirectableRequest(options, responseCallback) {
// Initialize the request
@@ -54,7 +86,13 @@ function RedirectableRequest(options, responseCallback) {
// React to responses of native requests
var self = this;
this._onNativeResponse = function (response) {
- self._processResponse(response);
+ try {
+ self._processResponse(response);
+ }
+ catch (cause) {
+ self.emit("error", cause instanceof RedirectionError ?
+ cause : new RedirectionError({ cause: cause }));
+ }
};
// Perform the first request
@@ -63,10 +101,17 @@ function RedirectableRequest(options, responseCallback) {
RedirectableRequest.prototype = Object.create(Writable.prototype);
RedirectableRequest.prototype.abort = function () {
- abortRequest(this._currentRequest);
+ destroyRequest(this._currentRequest);
+ this._currentRequest.abort();
this.emit("abort");
};
+RedirectableRequest.prototype.destroy = function (error) {
+ destroyRequest(this._currentRequest, error);
+ destroy.call(this, error);
+ return this;
+};
+
// Writes buffered data to the current native request
RedirectableRequest.prototype.write = function (data, encoding, callback) {
// Writing is not allowed if end has been called
@@ -75,10 +120,10 @@ RedirectableRequest.prototype.write = function (data, encoding, callback) {
}
// Validate input and shift parameters if necessary
- if (!(typeof data === "string" || typeof data === "object" && ("length" in data))) {
+ if (!isString(data) && !isBuffer(data)) {
throw new TypeError("data should be a string, Buffer or Uint8Array");
}
- if (typeof encoding === "function") {
+ if (isFunction(encoding)) {
callback = encoding;
encoding = null;
}
@@ -107,11 +152,11 @@ RedirectableRequest.prototype.write = function (data, encoding, callback) {
// Ends the current native request
RedirectableRequest.prototype.end = function (data, encoding, callback) {
// Shift parameters if necessary
- if (typeof data === "function") {
+ if (isFunction(data)) {
callback = data;
data = encoding = null;
}
- else if (typeof encoding === "function") {
+ else if (isFunction(encoding)) {
callback = encoding;
encoding = null;
}
@@ -179,6 +224,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
self.removeListener("abort", clearTimer);
self.removeListener("error", clearTimer);
self.removeListener("response", clearTimer);
+ self.removeListener("close", clearTimer);
if (callback) {
self.removeListener("timeout", callback);
}
@@ -205,6 +251,7 @@ RedirectableRequest.prototype.setTimeout = function (msecs, callback) {
this.on("abort", clearTimer);
this.on("error", clearTimer);
this.on("response", clearTimer);
+ this.on("close", clearTimer);
return this;
};
@@ -263,8 +310,7 @@ RedirectableRequest.prototype._performRequest = function () {
var protocol = this._options.protocol;
var nativeProtocol = this._options.nativeProtocols[protocol];
if (!nativeProtocol) {
- this.emit("error", new TypeError("Unsupported protocol " + protocol));
- return;
+ throw new TypeError("Unsupported protocol " + protocol);
}
// If specified, use the agent corresponding to the protocol
@@ -288,7 +334,7 @@ RedirectableRequest.prototype._performRequest = function () {
url.format(this._options) :
// When making a request to a proxy, […]
// a client MUST send the target URI in absolute-form […].
- this._currentUrl = this._options.path;
+ this._options.path;
// End a redirected request
// (The first request must be ended explicitly with RedirectableRequest#end)
@@ -356,15 +402,14 @@ RedirectableRequest.prototype._processResponse = function (response) {
}
// The response is a redirect, so abort the current request
- abortRequest(this._currentRequest);
+ destroyRequest(this._currentRequest);
// Discard the remainder of the response to avoid waiting for data
response.destroy();
// RFC7231§6.4: A client SHOULD detect and intervene
// in cyclical redirections (i.e., "infinite" redirection loops).
if (++this._redirectCount > this._options.maxRedirects) {
- this.emit("error", new TooManyRedirectsError());
- return;
+ throw new TooManyRedirectsError();
}
// Store the request headers if applicable
@@ -398,38 +443,28 @@ RedirectableRequest.prototype._processResponse = function (response) {
var currentHostHeader = removeMatchingHeaders(/^host$/i, this._options.headers);
// If the redirect is relative, carry over the host of the last request
- var currentUrlParts = url.parse(this._currentUrl);
+ var currentUrlParts = parseUrl(this._currentUrl);
var currentHost = currentHostHeader || currentUrlParts.host;
var currentUrl = /^\w+:/.test(location) ? this._currentUrl :
url.format(Object.assign(currentUrlParts, { host: currentHost }));
- // Determine the URL of the redirection
- var redirectUrl;
- try {
- redirectUrl = url.resolve(currentUrl, location);
- }
- catch (cause) {
- this.emit("error", new RedirectionError(cause));
- return;
- }
-
// Create the redirected request
- debug("redirecting to", redirectUrl);
+ var redirectUrl = resolveUrl(location, currentUrl);
+ debug("redirecting to", redirectUrl.href);
this._isRedirect = true;
- var redirectUrlParts = url.parse(redirectUrl);
- Object.assign(this._options, redirectUrlParts);
+ spreadUrlObject(redirectUrl, this._options);
// Drop confidential headers when redirecting to a less secure protocol
// or to a different domain that is not a superdomain
- if (redirectUrlParts.protocol !== currentUrlParts.protocol &&
- redirectUrlParts.protocol !== "https:" ||
- redirectUrlParts.host !== currentHost &&
- !isSubdomain(redirectUrlParts.host, currentHost)) {
+ if (redirectUrl.protocol !== currentUrlParts.protocol &&
+ redirectUrl.protocol !== "https:" ||
+ redirectUrl.host !== currentHost &&
+ !isSubdomain(redirectUrl.host, currentHost)) {
removeMatchingHeaders(/^(?:authorization|cookie)$/i, this._options.headers);
}
// Evaluate the beforeRedirect callback
- if (typeof beforeRedirect === "function") {
+ if (isFunction(beforeRedirect)) {
var responseDetails = {
headers: response.headers,
statusCode: statusCode,
@@ -439,23 +474,12 @@ RedirectableRequest.prototype._processResponse = function (response) {
method: method,
headers: requestHeaders,
};
- try {
- beforeRedirect(this._options, responseDetails, requestDetails);
- }
- catch (err) {
- this.emit("error", err);
- return;
- }
+ beforeRedirect(this._options, responseDetails, requestDetails);
this._sanitizeOptions(this._options);
}
// Perform the redirected request
- try {
- this._performRequest();
- }
- catch (cause) {
- this.emit("error", new RedirectionError(cause));
- }
+ this._performRequest();
};
// Wraps the key/value object of protocols with redirect functionality
@@ -475,26 +499,19 @@ function wrap(protocols) {
// Executes a request, following redirects
function request(input, options, callback) {
- // Parse parameters
- if (typeof input === "string") {
- var urlStr = input;
- try {
- input = urlToOptions(new URL(urlStr));
- }
- catch (err) {
- /* istanbul ignore next */
- input = url.parse(urlStr);
- }
+ // Parse parameters, ensuring that input is an object
+ if (isURL(input)) {
+ input = spreadUrlObject(input);
}
- else if (URL && (input instanceof URL)) {
- input = urlToOptions(input);
+ else if (isString(input)) {
+ input = spreadUrlObject(parseUrl(input));
}
else {
callback = options;
- options = input;
+ options = validateUrl(input);
input = { protocol: protocol };
}
- if (typeof options === "function") {
+ if (isFunction(options)) {
callback = options;
options = null;
}
@@ -505,6 +522,9 @@ function wrap(protocols) {
maxBodyLength: exports.maxBodyLength,
}, input, options);
options.nativeProtocols = nativeProtocols;
+ if (!isString(options.host) && !isString(options.hostname)) {
+ options.hostname = "::1";
+ }
assert.equal(options.protocol, protocol, "protocol mismatch");
debug("options", options);
@@ -527,27 +547,57 @@ function wrap(protocols) {
return exports;
}
-/* istanbul ignore next */
function noop() { /* empty */ }
-// from https://github.com/nodejs/node/blob/master/lib/internal/url.js
-function urlToOptions(urlObject) {
- var options = {
- protocol: urlObject.protocol,
- hostname: urlObject.hostname.startsWith("[") ?
- /* istanbul ignore next */
- urlObject.hostname.slice(1, -1) :
- urlObject.hostname,
- hash: urlObject.hash,
- search: urlObject.search,
- pathname: urlObject.pathname,
- path: urlObject.pathname + urlObject.search,
- href: urlObject.href,
- };
- if (urlObject.port !== "") {
- options.port = Number(urlObject.port);
+function parseUrl(input) {
+ var parsed;
+ /* istanbul ignore else */
+ if (useNativeURL) {
+ parsed = new URL(input);
}
- return options;
+ else {
+ // Ensure the URL is valid and absolute
+ parsed = validateUrl(url.parse(input));
+ if (!isString(parsed.protocol)) {
+ throw new InvalidUrlError({ input });
+ }
+ }
+ return parsed;
+}
+
+function resolveUrl(relative, base) {
+ /* istanbul ignore next */
+ return useNativeURL ? new URL(relative, base) : parseUrl(url.resolve(base, relative));
+}
+
+function validateUrl(input) {
+ if (/^\[/.test(input.hostname) && !/^\[[:0-9a-f]+\]$/i.test(input.hostname)) {
+ throw new InvalidUrlError({ input: input.href || input });
+ }
+ if (/^\[/.test(input.host) && !/^\[[:0-9a-f]+\](:\d+)?$/i.test(input.host)) {
+ throw new InvalidUrlError({ input: input.href || input });
+ }
+ return input;
+}
+
+function spreadUrlObject(urlObject, target) {
+ var spread = target || {};
+ for (var key of preservedUrlFields) {
+ spread[key] = urlObject[key];
+ }
+
+ // Fix IPv6 hostname
+ if (spread.hostname.startsWith("[")) {
+ spread.hostname = spread.hostname.slice(1, -1);
+ }
+ // Ensure port is a number
+ if (spread.port !== "") {
+ spread.port = Number(spread.port);
+ }
+ // Concatenate path
+ spread.path = spread.search ? spread.pathname + spread.search : spread.pathname;
+
+ return spread;
}
function removeMatchingHeaders(regex, headers) {
@@ -562,37 +612,60 @@ function removeMatchingHeaders(regex, headers) {
undefined : String(lastValue).trim();
}
-function createErrorType(code, defaultMessage) {
- function CustomError(cause) {
+function createErrorType(code, message, baseClass) {
+ // Create constructor
+ function CustomError(properties) {
Error.captureStackTrace(this, this.constructor);
- if (!cause) {
- this.message = defaultMessage;
- }
- else {
- this.message = defaultMessage + ": " + cause.message;
- this.cause = cause;
- }
- }
- CustomError.prototype = new Error();
- CustomError.prototype.constructor = CustomError;
- CustomError.prototype.name = "Error [" + code + "]";
- CustomError.prototype.code = code;
+ Object.assign(this, properties || {});
+ this.code = code;
+ this.message = this.cause ? message + ": " + this.cause.message : message;
+ }
+
+ // Attach constructor and set default properties
+ CustomError.prototype = new (baseClass || Error)();
+ Object.defineProperties(CustomError.prototype, {
+ constructor: {
+ value: CustomError,
+ enumerable: false,
+ },
+ name: {
+ value: "Error [" + code + "]",
+ enumerable: false,
+ },
+ });
return CustomError;
}
-function abortRequest(request) {
+function destroyRequest(request, error) {
for (var event of events) {
request.removeListener(event, eventHandlers[event]);
}
request.on("error", noop);
- request.abort();
+ request.destroy(error);
}
function isSubdomain(subdomain, domain) {
- const dot = subdomain.length - domain.length - 1;
+ assert(isString(subdomain) && isString(domain));
+ var dot = subdomain.length - domain.length - 1;
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
}
+function isString(value) {
+ return typeof value === "string" || value instanceof String;
+}
+
+function isFunction(value) {
+ return typeof value === "function";
+}
+
+function isBuffer(value) {
+ return typeof value === "object" && ("length" in value);
+}
+
+function isURL(value) {
+ return URL && value instanceof URL;
+}
+
// Exports
module.exports = wrap({ http: http, https: https });
module.exports.wrap = wrap;

Просмотреть файл

@ -1,211 +0,0 @@
Fixes CVE-2023-28155: https://nvd.nist.gov/vuln/detail/CVE-2023-28155, which is a vulnerability
in the the request module that is used by this package.
Note that request is deprecated (see https://github.com/request/request for details), so this
has not and will never be fixed in the request module itself. However, there is a pull request
that fixes it.
Adapted by tobiasb@microsoft.com from a pull request for a patch to request:
https://github.com/request/request/pull/3444/files
From d42332182512e56ba68446f49c3e3711e04301a2 Mon Sep 17 00:00:00 2001
From: <redacted>
Date: Sun, 12 Mar 2023 19:47:24 +0100
Subject: [PATCH 1/5] Added option "allowInsecureRedirect"
---
PATCH NOTE -- ORIGINAL:
lib/redirect.js | 6 +++++-
PATCH NOTE -- UPDATE:
node_modules/request/lib/redirect.js | 6 +++++-
PATCH NOTE: These tests are not included in the module we use, so they are not included in this patch.
tests/test-httpModule.js | 3 ++-
tests/test-redirect.js | 15 ++++++++++++++-
PATCH NOTE -- ORIGINAL:
3 files changed, 21 insertions(+), 3 deletions(-)
PATCH NOTE -- UPDATED:
1 file changed, 5 insertions(+), 1 deletion(-)
# PATCH NOTE -- ORIGINAL:
#diff --git a/lib/redirect.js b/lib/redirect.js
# PATCH NOTE -- UPDATED with path used within the source tarball:
diff --git a/node_modules/request/lib/redirect.js b/node_modules/request/lib/redirect.js
index b9150e77c..770c7f41b 100644
# PATCH NOTE -- ORIGINAL:
# --- a/lib/redirect.js
# +++ b/lib/redirect.js
# PATCH NOTE -- UPDATED with path used within the source tarball:
--- a/node_modules/request/lib/redirect.js
+++ b/node_modules/request/lib/redirect.js
@@ -14,6 +14,7 @@ function Redirect (request) {
this.redirects = []
this.redirectsFollowed = 0
this.removeRefererHeader = false
+ this.allowInsecureRedirect = false
}
Redirect.prototype.onRequest = function (options) {
@@ -40,6 +41,9 @@ Redirect.prototype.onRequest = function (options) {
if (options.followOriginalHttpMethod !== undefined) {
self.followOriginalHttpMethod = options.followOriginalHttpMethod
}
+ if (options.allowInsecureRedirect !== undefined) {
+ self.allowInsecureRedirect = options.allowInsecureRedirect;
+ }
}
Redirect.prototype.redirectTo = function (response) {
@@ -108,7 +112,7 @@ Redirect.prototype.onResponse = function (response) {
request.uri = url.parse(redirectTo)
// handle the case where we change protocol from https to http or vice versa
- if (request.uri.protocol !== uriPrev.protocol) {
+ if (request.uri.protocol !== uriPrev.protocol && self.allowInsecureRedirect) {
delete request.agent
}
# PATCH NOTE: The rest of the diffs are not applied because they are tests and not
# included in the source tarball.
# diff --git a/tests/test-httpModule.js b/tests/test-httpModule.js
# index 4d4e236bf..a59c427b1 100644
# --- a/tests/test-httpModule.js
# +++ b/tests/test-httpModule.js
# @@ -70,7 +70,8 @@ function runTests (name, httpModules) {
# tape(name, function (t) {
# var toHttps = 'http://localhost:' + plainServer.port + '/to_https'
# var toPlain = 'https://localhost:' + httpsServer.port + '/to_plain'
# - var options = { httpModules: httpModules, strictSSL: false }
# + var options = { httpModules: httpModules, strictSSL: false, allowInsecureRedirect: true }
# + var optionsSecure = { httpModules: httpModules, strictSSL: false }
# var modulesTest = httpModules || {}
# clearFauxRequests()
# diff --git a/tests/test-redirect.js b/tests/test-redirect.js
# index b7b5ca676..48b4982e4 100644
# --- a/tests/test-redirect.js
# +++ b/tests/test-redirect.js
# @@ -345,7 +345,8 @@ tape('http to https redirect', function (t) {
# hits = {}
# request.get({
# uri: require('url').parse(s.url + '/ssl'),
# - rejectUnauthorized: false
# + rejectUnauthorized: false,
# + allowInsecureRedirect: true
# }, function (err, res, body) {
# t.equal(err, null)
# t.equal(res.statusCode, 200)
# @@ -354,6 +355,18 @@ tape('http to https redirect', function (t) {
# })
# })
# +tape('http to https redirect should fail without the explicit "allowInsecureRedirect" option', function (t) {
# + hits = {}
# + request.get({
# + uri: require('url').parse(s.url + '/ssl'),
# + rejectUnauthorized: false
# + }, function (err, res, body) {
# + t.notEqual(err, null)
# + t.equal(err.code, "ERR_INVALID_PROTOCOL","Failed to cross-protocol redirect")
# + t.end()
# + })
# +})
# +
# tape('should have referer header by default when following redirect', function (t) {
# request.post({
# uri: s.url + '/temp',
# From 9d69d750f39cc5ab6f3b011e17472bc28b14dc22 Mon Sep 17 00:00:00 2001
# From: Szymon Drosdzol <szymon@doyensec.com>
# Date: Sun, 12 Mar 2023 19:50:09 +0100
# Subject: [PATCH 2/5] Documented allowInsecureRedirect in Readme
# ---
# README.md | 1 +
# 1 file changed, 1 insertion(+)
# diff --git a/README.md b/README.md
# index 42290d5ce..dd432a768 100644
# --- a/README.md
# +++ b/README.md
# @@ -809,6 +809,7 @@ The first argument can be either a `url` or an `options` object. The only requir
# - `followOriginalHttpMethod` - by default we redirect to HTTP method GET. you can enable this property to redirect to the original HTTP method (default: `false`)
# - `maxRedirects` - the maximum number of redirects to follow (default: `10`)
# - `removeRefererHeader` - removes the referer header when a redirect happens (default: `false`). **Note:** if true, referer header set in the initial request is preserved during redirect chain.
# +- `allowInsecureRedirect` - allows cross-protocol redirects (HTTP to HTTPS and vice versa). **Warning:** may lead to bypassing anti SSRF filters
# ---
# From 8a15249d182e54a261b1539846f76d913a6904f4 Mon Sep 17 00:00:00 2001
# From: SzymonDrosdzol <84710686+SzymonDrosdzol@users.noreply.github.com>
# Date: Fri, 17 Mar 2023 10:09:46 +0100
# Subject: [PATCH 3/5] Removed semicolon
# Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
# ---
# lib/redirect.js | 2 +-
# 1 file changed, 1 insertion(+), 1 deletion(-)
# diff --git a/lib/redirect.js b/lib/redirect.js
# index 770c7f41b..2864f9f2a 100644
# --- a/lib/redirect.js
# +++ b/lib/redirect.js
# @@ -42,7 +42,7 @@ Redirect.prototype.onRequest = function (options) {
# self.followOriginalHttpMethod = options.followOriginalHttpMethod
# }
# if (options.allowInsecureRedirect !== undefined) {
# - self.allowInsecureRedirect = options.allowInsecureRedirect;
# + self.allowInsecureRedirect = options.allowInsecureRedirect
# }
# }
# From 8535868fc88f24ed652d3f290bfd553a2cdbb811 Mon Sep 17 00:00:00 2001
# From: SzymonDrosdzol <84710686+SzymonDrosdzol@users.noreply.github.com>
# Date: Fri, 17 Mar 2023 10:12:09 +0100
# Subject: [PATCH 4/5] Code style fix
# Co-authored-by: Kevin van Rijn <6368561+kevinvanrijn@users.noreply.github.com>
# ---
# tests/test-redirect.js | 2 +-
# 1 file changed, 1 insertion(+), 1 deletion(-)
# diff --git a/tests/test-redirect.js b/tests/test-redirect.js
# index 48b4982e4..3e1957604 100644
# --- a/tests/test-redirect.js
# +++ b/tests/test-redirect.js
# @@ -362,7 +362,7 @@ tape('http to https redirect should fail without the explicit "allowInsecureRedi
# rejectUnauthorized: false
# }, function (err, res, body) {
# t.notEqual(err, null)
# - t.equal(err.code, "ERR_INVALID_PROTOCOL","Failed to cross-protocol redirect")
# + t.equal(err.code, 'ERR_INVALID_PROTOCOL', 'Failed to cross-protocol redirect')
# t.end()
# })
# })
# From 43647c4bd6e451f350267d5236463b4248dbc8df Mon Sep 17 00:00:00 2001
# From: SzymonDrosdzol <84710686+SzymonDrosdzol@users.noreply.github.com>
# Date: Fri, 17 Mar 2023 10:22:33 +0100
# Subject: [PATCH 5/5] Removed leftover declaration
# ---
# tests/test-httpModule.js | 1 -
# 1 file changed, 1 deletion(-)
# diff --git a/tests/test-httpModule.js b/tests/test-httpModule.js
# index a59c427b1..f12382fe6 100644
# --- a/tests/test-httpModule.js
# +++ b/tests/test-httpModule.js
# @@ -71,7 +71,6 @@ function runTests (name, httpModules) {
# var toHttps = 'http://localhost:' + plainServer.port + '/to_https'
# var toPlain = 'https://localhost:' + httpsServer.port + '/to_plain'
# var options = { httpModules: httpModules, strictSSL: false, allowInsecureRedirect: true }
# - var optionsSecure = { httpModules: httpModules, strictSSL: false }
# var modulesTest = httpModules || {}
# clearFauxRequests()

Просмотреть файл

@ -2,11 +2,11 @@
"Signatures": {
"cassandra-reaper-3.1.1.tar.gz": "6efe52195ad4a3c3b7a6f928bafa60d3df011709d9bc918e717033bf86d724d8",
"reaper-bower-cache-3.1.1.tar.gz": "a8532fe1d28f6d2c99a5e0d08b17b85465617931d49c7d27450ed328e59c0b08",
"reaper-bower-components-3.1.1.tar.gz": "213f956916bbfaa02eb880bd9e17d0ab41985987e7b95a925fde5f7c2e8bd44f",
"reaper-bower-components-3.1.1-1.tar.gz": "51f5b03b3f56966f5fbfe28a13e0a74003cf33372ff4ba13fd82c6fe79092033",
"reaper-local-lib-node-modules-3.1.1.tar.gz": "8daf9a8726a85ca31b024a5bab60a357fe927f670908955cdd9b106bf9c6bd60",
"reaper-local-n-3.1.1-1.tar.gz": "e60ecf1c982c8cd44b35da02aec6de5b1f8f0df562f290f9bb905d03f9eefa68",
"reaper-m2-cache-3.1.1.tar.gz": "14103df496c6bfd1bf2690b45e6082e3411872f7332f03a68cf5d8e28fc6b27f",
"reaper-npm-cache-3.1.1.tar.gz": "1fd8fd9438ef682cccceaaf49d0e65ec50eb7145c20f27253a3521c731e79585",
"reaper-srcui-node-modules-3.1.1.tar.gz": "182d346f73d29544cabec090877f1a63ead6914371cd3db11aac5e5f4ec3c5dc"
"reaper-srcui-node-modules-3.1.1-1.tar.gz": "edd67243e97838657e09513f639a8e7c81fbb813353a19eba3949f79fb9e3e9e"
}
}

Просмотреть файл

@ -1,10 +1,11 @@
%global debug_package %{nil}
%define local_n_release 1
%define local_srcui_release 1
%define srcdir cassandra-%{name}-%{version}
%define bower_components reaper-bower-components-%{version}.tar.gz
%define srcui_node_modules reaper-srcui-node-modules-%{version}.tar.gz
%define bower_components reaper-bower-components-%{version}-%{local_srcui_release}.tar.gz
%define srcui_node_modules reaper-srcui-node-modules-%{version}-%{local_srcui_release}.tar.gz
%define bower_cache reaper-bower-cache-%{version}.tar.gz
%define maven_cache reaper-m2-cache-%{version}.tar.gz
%define npm_cache reaper-npm-cache-%{version}.tar.gz
@ -14,7 +15,7 @@
Summary: Reaper for cassandra is a tool for running Apache Cassandra repairs against single or multi-site clusters.
Name: reaper
Version: 3.1.1
Release: 8%{?dist}
Release: 9%{?dist}
License: ASL 2.0
Vendor: Microsoft Corporation
Distribution: Mariner
@ -38,10 +39,6 @@ Source5: %{npm_cache}
Source6: %{local_lib_node_modules}
# v14.18.0 node binary under /usr/local
Source7: %{local_n}
Patch0: CVE-2022-37601.patch
Patch1: CVE-2023-28155.patch
Patch2: CVE-2018-11694.patch
Patch3: CVE-2023-26159.patch
BuildRequires: git
BuildRequires: javapackages-tools
BuildRequires: maven
@ -111,10 +108,6 @@ tar xf %{SOURCE1}
echo "Installing npm_modules"
tar fx %{SOURCE2}
patch -p1 --input %{PATCH0}
patch -p1 --input %{PATCH1}
patch -p1 --input %{PATCH2}
patch -p1 --input %{PATCH3}
popd
# Building using maven in offline mode.
@ -185,6 +178,14 @@ fi
%{_unitdir}/cassandra-%{name}.service
%changelog
* Thu May 23 2024 Archana Choudhary <archana1@microsoft.com> - 3.1.1-9
- Repackage and update src/ui node modules and bower components to 3.1.1-1
- Address CVE-2024-4068 by upgrading the version of the npm module "braces" to 3.0.3
- Remove patch for CVE-2023-28155 as request npm module upgraded to 2.88.2
- Remove patch for CVE-2018-11694 as node-sass npm module upgraded to 4.14.1
- Remove patch for CVE-2022-37601 as loader-utils npm module upgraded to 1.4.2
- Remove patch for CVE-2023-26159 as follow-redirects npm module upgraded to 1.15.6
* Thu Jan 11 2024 Henry Li <lihl@microsoft.com> - 3.1.1-8
- Apply patch to resolve CVE-2023-26159