import UBI nodejs-22.23.1-3.module+el8.10.0+24640+6eba5e6e

This commit is contained in:
AlmaLinux RelEng Bot 2026-08-13 18:56:04 -04:00
parent eb93c3f399
commit b225097bcd
7 changed files with 23865 additions and 375 deletions

View File

@ -1,102 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tjuhasz <tjuhasz@redhat.com>
Date: Tue, 25 Feb 2026 14:21:26 +0100
Subject: [PATCH] CVE-2026-25547: Fix brace expansion vulnerability
Add expansion limit to prevent DoS attacks through excessive
brace expansion in the brace-expansion module.
---
deps/npm/node_modules/brace-expansion/index.js | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/deps/npm/node_modules/brace-expansion/index.js b/deps/npm/node_modules/brace-expansion/index.js
--- a/deps/npm/node_modules/brace-expansion/index.js 2026-01-12 23:55:24.000000000 +0100
+++ b/deps/npm/node_modules/brace-expansion/index.js 2026-02-25 14:21:26.829483831 +0100
@@ -8,6 +8,8 @@
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
+const EXPANSION_MAX = 100_000;
+
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
@@ -61,9 +63,11 @@
return parts;
}
-function expandTop(str) {
+function expandTop(str, options = {}) {
if (!str)
return [];
+
+ const { max = EXPANSION_MAX } = options;
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
@@ -75,7 +79,7 @@
str = '\\{\\}' + str.substr(2);
}
- return expand(escapeBraces(str), true).map(unescapeBraces);
+ return expand(escapeBraces(str), max, true).map(unescapeBraces);
}
function embrace(str) {
@@ -92,7 +96,7 @@
return i >= y;
}
-function expand(str, isTop) {
+function expand(str, max, isTop) {
var expansions = [];
var m = balanced('{', '}', str);
@@ -101,11 +105,11 @@
// no need to expand pre, since it is guaranteed to be free of brace-sets
var pre = m.pre;
var post = m.post.length
- ? expand(m.post, false)
+ ? expand(m.post, max, false)
: [''];
if (/\$$/.test(m.pre)) {
- for (var k = 0; k < post.length; k++) {
+ for (var k = 0; k < post.length && k < max; k++) {
var expansion = pre+ '{' + m.body + '}' + post[k];
expansions.push(expansion);
}
@@ -118,7 +122,7 @@
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
- return expand(str);
+ return expand(str, max, true);
}
return [str];
}
@@ -130,7 +134,7 @@
n = parseCommaParts(m.body);
if (n.length === 1) {
// x{{a,b}}y ==> x{a}y x{b}y
- n = expand(n[0], false).map(embrace);
+ n = expand(n[0], max, false).map(embrace);
if (n.length === 1) {
return post.map(function(p) {
return m.pre + n[0] + p;
@@ -185,12 +189,12 @@
N = [];
for (var j = 0; j < n.length; j++) {
- N.push.apply(N, expand(n[j], false));
+ N.push.apply(N, expand(n[j], max, false));
}
}
for (var j = 0; j < N.length; j++) {
- for (var k = 0; k < post.length; k++) {
+ for (var k = 0; k < post.length && expansions.length < max; k++) {
var expansion = pre + N[j] + post[k];
if (!isTop || isSequence || expansion)
expansions.push(expansion);

View File

@ -0,0 +1,391 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Tomas Juhasz <tjuhasz@redhat.com>
Date: Mon, 04 Aug 2026 00:00:00 +0000
Subject: [PATCH] CVE-2026-14257: upgrade bundled brace-expansion to 2.1.4
Upgrade brace-expansion from 2.0.2 to 2.1.4 in npm's vendored
node_modules. The new version adds EXPANSION_MAX and EXPANSION_MAX_LENGTH
guards that cap the number and total size of expansions, preventing
memory exhaustion from crafted input (CVE-2026-14257). The expand()
function is rewritten to iterate instead of recurse, eliminating stack
overflow on deeply chained brace groups.
Supersedes the earlier CVE-2026-13149 unbound-recursion patch.
Upstream: https://github.com/juliangruber/brace-expansion/releases/tag/v2.1.4
---
.../npm/node_modules/brace-expansion/index.js | 297 +++++++++++++++-----
.../npm/node_modules/brace-expansion/package.json | 2 +-
2 files changed, 217 insertions(+), 82 deletions(-)
diff --git a/deps/npm/node_modules/brace-expansion/index.js b/deps/npm/node_modules/brace-expansion/index.js
--- a/deps/npm/node_modules/brace-expansion/index.js
+++ b/deps/npm/node_modules/brace-expansion/index.js
@@ -8,6 +8,20 @@
var escComma = '\0COMMA'+Math.random()+'\0';
var escPeriod = '\0PERIOD'+Math.random()+'\0';
+var EXPANSION_MAX = 100000
+
+// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
+// input like `'{a,b}'.repeat(1500)` stays under that count - its output is
+// truncated to 100k results - while making every result ~1500 characters
+// long. The result set, and the intermediate arrays built while combining
+// brace sets, then grow large enough to exhaust memory and crash the process
+// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
+// characters the accumulator may hold at any point, so memory stays flat no
+// matter how many brace groups are chained. The limit sits well above any
+// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
+// characters) so legitimate input is unaffected.
+var EXPANSION_MAX_LENGTH = 4000000
+
function numeric(str) {
return parseInt(str, 10) == str
? parseInt(str, 10)
@@ -61,10 +75,14 @@
return parts;
}
-function expandTop(str) {
+function expandTop(str, options) {
if (!str)
return [];
+ options = options || {};
+ var max = options.max == null ? EXPANSION_MAX : options.max;
+ var maxLength = options.maxLength == null ? EXPANSION_MAX_LENGTH : options.maxLength;
+
// I don't know why Bash 4.3 does this, but it does.
// Anything starting with {} will have the first two bytes preserved
// but *only* at the top level, so {},a}b will not expand to anything,
@@ -75,7 +93,7 @@
str = '\\{\\}' + str.substr(2);
}
- return expand(escapeBraces(str), true).map(unescapeBraces);
+ return expand(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
}
function embrace(str) {
@@ -92,24 +110,144 @@
return i >= y;
}
-function expand(str, isTop) {
- var expansions = [];
+// Build `{ acc[a] + pre + values[v] }` for every combination, capping the
+// number of results at `max` and the total number of characters at `maxLength`.
+// This is the one place output grows, so bounding it here keeps the single
+// accumulator - and therefore memory - flat regardless of how many brace groups
+// are combined (CVE-2026-14257).
+function combine(
+ acc,
+ pre,
+ values,
+ max,
+ maxLength,
+ dropEmpties
+) {
+ var out = []
+ var length = 0
+ for (var a = 0; a < acc.length; a++) {
+ for (var v = 0; v < values.length; v++) {
+ if (out.length >= max) return out
+ var expansion = acc[a] + pre + values[v]
+ // Bash drops empty results at the top level. Skip them before they count
+ // against `max`, so `max` bounds the number of *kept* results.
+ if (dropEmpties && !expansion) continue
+ if (length + expansion.length > maxLength) return out
+ out.push(expansion)
+ length += expansion.length
+ }
+ }
+ return out
+}
- var m = balanced('{', '}', str);
- if (!m) return [str];
+// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
+// sequence body.
+function expandSequence(
+ body,
+ isAlphaSequence,
+ max,
+ maxLength
+) {
+ var n = body.split(/\.\./)
+ var N = []
+ // A sequence body always splits into two or three parts, but the compiler
+ // can't know that.
+ /* c8 ignore start */
+ if (n[0] === undefined || n[1] === undefined) {
+ return N
+ }
+ /* c8 ignore stop */
+ var x = numeric(n[0])
+ var y = numeric(n[1])
+ var width = Math.max(n[0].length, n[1].length)
+ var incr =
+ n.length === 3 && n[2] !== undefined ?
+ Math.max(Math.abs(numeric(n[2])), 1)
+ : 1
+ var test = lte
+ var reverse = y < x
+ if (reverse) {
+ incr *= -1
+ test = gte
+ }
+ var pad = n.some(isPadded)
- // no need to expand pre, since it is guaranteed to be free of brace-sets
- var pre = m.pre;
- var post = m.post.length
- ? expand(m.post, false)
- : [''];
-
- if (/\$$/.test(m.pre)) {
- for (var k = 0; k < post.length; k++) {
- var expansion = pre+ '{' + m.body + '}' + post[k];
- expansions.push(expansion);
+ var length = 0
+ for (var i = x; test(i, y) && N.length < max; i += incr) {
+ var c
+ if (isAlphaSequence) {
+ c = String.fromCharCode(i)
+ if (c === '\\') {
+ c = ''
+ }
+ } else {
+ c = String(i)
+ if (pad) {
+ var need = width - c.length
+ if (need > 0) {
+ var z = new Array(need + 1).join('0')
+ if (i < 0) {
+ c = '-' + z + c.slice(1)
+ } else {
+ c = z + c
+ }
+ }
+ }
}
- } else {
+ if (length + c.length > maxLength) break
+ N.push(c)
+ length += c.length
+ }
+ return N
+}
+
+function expand(
+ str,
+ max,
+ maxLength,
+ isTop
+) {
+ // Consume the string's top-level brace groups left to right, threading a
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
+ // rather than recursing on `m.post` once per group - keeps the native stack
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
+ // longer overflow the stack, and leaves a single accumulator whose size
+ // `maxLength` bounds directly (CVE-2026-14257).
+ var acc = ['']
+
+ // Bash drops empty results, but only when the *first* top-level group is a
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
+ // is on the final strings, so it is applied to whichever `combine` produces
+ // them (the one with no brace set left in the tail).
+ var dropEmpties = false
+ var firstGroup = true
+
+ for (;;) {
+ const m = balanced('{', '}', str)
+
+ // No brace set left: the rest of the string is literal.
+ if (!m) {
+ return combine(acc, str, [''], max, maxLength, dropEmpties)
+ }
+
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
+ const pre = m.pre
+
+ if (/\$$/.test(pre)) {
+ acc = combine(
+ acc,
+ pre + '{' + m.body + '}',
+ [''],
+ max,
+ maxLength,
+ dropEmpties && !m.post.length
+ )
+ firstGroup = false
+ if (!m.post.length) break
+ str = m.post
+ continue
+ }
+
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
@@ -118,86 +256,83 @@
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
- return expand(str);
+ isTop = true;
+ continue;
}
- return [str];
+ // Nothing here expands, so the whole remaining string is literal.
+ return combine(
+ acc,
+ pre + '{' + m.body + '}' + m.post,
+ [''],
+ max,
+ maxLength,
+ dropEmpties
+ )
}
- var n;
+ if (firstGroup) {
+ dropEmpties = isTop && !isSequence
+ firstGroup = false
+ }
+
+ var values;
if (isSequence) {
- n = m.body.split(/\.\./);
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
} else {
- n = parseCommaParts(m.body);
- if (n.length === 1) {
+ var n = parseCommaParts(m.body);
+ if (n.length === 1 && n[0] !== undefined) {
// x{{a,b}}y ==> x{a}y x{b}y
- n = expand(n[0], false).map(embrace);
+ n = expand(n[0], max, maxLength, false).map(embrace);
+ //XXX is this necessary? Can't seem to hit it in tests.
+ /* c8 ignore start */
if (n.length === 1) {
- return post.map(function(p) {
- return m.pre + n[0] + p;
- });
+ acc = combine(
+ acc,
+ pre + n[0],
+ [''],
+ max,
+ maxLength,
+ dropEmpties && !m.post.length
+ )
+ if (!m.post.length) break
+ str = m.post
+ continue
}
+ /* c8 ignore stop */
}
- }
-
- // at this point, n is the parts, and we know it's not a comma set
- // with a single entry.
- var N;
- if (isSequence) {
- var x = numeric(n[0]);
- var y = numeric(n[1]);
- var width = Math.max(n[0].length, n[1].length)
- var incr = n.length == 3
- ? Math.abs(numeric(n[2]))
- : 1;
- var test = lte;
- var reverse = y < x;
- if (reverse) {
- incr *= -1;
- test = gte;
- }
- var pad = n.some(isPadded);
-
- N = [];
-
- for (var i = x; test(i, y); i += incr) {
- var c;
- if (isAlphaSequence) {
- c = String.fromCharCode(i);
- if (c === '\\')
- c = '';
- } else {
- c = String(i);
- if (pad) {
- var need = width - c.length;
- if (need > 0) {
- var z = new Array(need + 1).join('0');
- if (i < 0)
- c = '-' + z + c.slice(1);
- else
- c = z + c;
- }
- }
+ // Values that `combine` is going to drop as empty produce no result, so
+ // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
+ // would stop at `['a', '']` and yield one result instead of two. Skipping
+ // them outright keeps `values` bounded while leaving `max` a bound on
+ // *kept* results.
+ var dropsEmpties = dropEmpties && !m.post.length && !pre
+ for (var d = 0; dropsEmpties && d < acc.length; d++) {
+ if (acc[d]) {
+ dropsEmpties = false
}
- N.push(c);
}
- } else {
- N = [];
- for (var j = 0; j < n.length; j++) {
- N.push.apply(N, expand(n[j], false));
+ values = []
+ var valuesLength = 0
+ outer: for (var j = 0; j < n.length; j++) {
+ var expanded = expand(n[j], max, maxLength, false)
+ for (var k = 0; k < expanded.length; k++) {
+ var v = expanded[k]
+ if (dropsEmpties && !v) continue
+ if (values.length >= max || valuesLength + v.length > maxLength) {
+ break outer
+ }
+ values.push(v)
+ valuesLength += v.length
+ }
}
}
- for (var j = 0; j < N.length; j++) {
- for (var k = 0; k < post.length; k++) {
- var expansion = pre + N[j] + post[k];
- if (!isTop || isSequence || expansion)
- expansions.push(expansion);
- }
- }
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length)
+ if (!m.post.length) break
+ str = m.post
}
- return expansions;
+ return acc
}
-
diff --git a/deps/npm/node_modules/brace-expansion/package.json b/deps/npm/node_modules/brace-expansion/package.json
--- a/deps/npm/node_modules/brace-expansion/package.json
+++ b/deps/npm/node_modules/brace-expansion/package.json
@@ -1,7 +1,7 @@
{
"name": "brace-expansion",
"description": "Brace expansion as known from sh/bash",
- "version": "2.0.2",
+ "version": "2.1.4",
"repository": {
"type": "git",
"url": "git://github.com/juliangruber/brace-expansion.git"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,166 +0,0 @@
From d98f88cfa68abef0e57ec2b48df0049032e50c85 Mon Sep 17 00:00:00 2001
From: Beau Gunderson <beau@beaugunderson.com>
Date: Sun, 27 Apr 2026 10:28:29 -0700
Subject: [PATCH] CVE-2026-42338 ip-address HTML escaping fix
Fix HTML escaping in ip-address library to prevent XSS vulnerabilities.
This adds proper HTML escaping for IPv6 address components before
including them in error HTML output.
Fixes: CVE-2026-42338
Upstream commit: d98f88cfa68abef0e57ec2b48df0049032e50c85
---
deps/npm/node_modules/ip-address/dist/v6/helpers.js | 9 +++++++++
deps/npm/node_modules/ip-address/dist/ipv6.js | 32 ++++++++++++++----------
deps/npm/node_modules/ip-address/package.json | 2 +-
3 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/deps/npm/node_modules/ip-address/dist/v6/helpers.js b/deps/npm/node_modules/ip-address/dist/v6/helpers.js
index 1234567..abcdefg 100644
--- a/deps/npm/node_modules/ip-address/dist/v6/helpers.js
+++ b/deps/npm/node_modules/ip-address/dist/v6/helpers.js
@@ -1,14 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
+exports.escapeHtml = escapeHtml;
exports.spanAllZeroes = spanAllZeroes;
exports.spanAll = spanAll;
exports.spanLeadingZeroes = spanLeadingZeroes;
exports.simpleGroup = simpleGroup;
+function escapeHtml(s) {
+ return s
+ .replace(/&/g, '&amp;')
+ .replace(/</g, '&lt;')
+ .replace(/>/g, '&gt;')
+ .replace(/"/g, '&quot;')
+ .replace(/'/g, '&#39;');
+}
/**
* @returns {String} the string with all zeroes contained in a <span>
*/
function spanAllZeroes(s) {
- return s.replace(/(0+)/g, '<span class="zero">$1</span>');
+ return escapeHtml(s).replace(/(0+)/g, '<span class="zero">$1</span>');
}
/**
* @returns {String} the string with each character contained in a <span>
@@ -16,11 +25,11 @@
function spanAll(s, offset = 0) {
const letters = s.split('');
return letters
- .map((n, i) => `<span class="digit value-${n} position-${i + offset}">${spanAllZeroes(n)}</span>`)
+ .map((n, i) => `<span class="digit value-${escapeHtml(n)} position-${i + offset}">${spanAllZeroes(n)}</span>`)
.join('');
}
function spanLeadingZeroesSimple(group) {
- return group.replace(/^(0+)/, '<span class="zero">$1</span>');
+ return escapeHtml(group).replace(/^(0+)/, '<span class="zero">$1</span>');
}
/**
* @returns {String} the string with leading zeroes contained in a <span>
@@ -42,4 +51,3 @@
return `<span class="hover-group group-${i + offset}">${spanLeadingZeroesSimple(g)}</span>`;
});
}
-//# sourceMappingURL=helpers.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/ip-address/dist/ipv6.js b/deps/npm/node_modules/ip-address/dist/ipv6.js
index 1234567..abcdefg 100644
--- a/deps/npm/node_modules/ip-address/dist/ipv6.js
+++ b/deps/npm/node_modules/ip-address/dist/ipv6.js
@@ -17,13 +17,23 @@
}) : function(o, v) {
o["default"] = v;
});
-var __importStar = (this && this.__importStar) || function (mod) {
- if (mod && mod.__esModule) return mod;
- var result = {};
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
- __setModuleDefault(result, mod);
- return result;
-};
+var __importStar = (this && this.__importStar) || (function () {
+ var ownKeys = function(o) {
+ ownKeys = Object.getOwnPropertyNames || function (o) {
+ var ar = [];
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
+ return ar;
+ };
+ return ownKeys(o);
+ };
+ return function (mod) {
+ if (mod && mod.__esModule) return mod;
+ var result = {};
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
+ __setModuleDefault(result, mod);
+ return result;
+ };
+})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Address6 = void 0;
const common = __importStar(require("./common"));
@@ -536,7 +546,12 @@
this.address4 = new ipv4_1.Address4(this.parsedAddress4);
for (let i = 0; i < this.address4.groups; i++) {
if (/^0[0-9]+/.test(this.address4.parsedAddress[i])) {
- throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", address.replace(constants4.RE_ADDRESS, this.address4.parsedAddress.map(spanLeadingZeroes4).join('.')));
+ // The prefix groups haven't been through the bad-character check
+ // yet, so escape them before including in the error HTML.
+ const highlighted = this.address4.parsedAddress.map(spanLeadingZeroes4).join('.');
+ const prefix = groups.slice(0, -1).map(helpers.escapeHtml).join(':');
+ const separator = groups.length > 1 ? ':' : '';
+ throw new address_error_1.AddressError("IPv4 addresses can't have leading zeroes.", `${prefix}${separator}${highlighted}`);
}
}
this.v4 = true;
@@ -896,10 +911,13 @@
formFunction = this.to4in6;
}
const form = formFunction.call(this);
+ const safeHref = helpers.escapeHtml(`${options.prefix}${form}`);
+ const safeForm = helpers.escapeHtml(form);
if (options.className) {
- return `<a href="${options.prefix}${form}" class="${options.className}">${form}</a>`;
+ const safeClass = helpers.escapeHtml(options.className);
+ return `<a href="${safeHref}" class="${safeClass}">${safeForm}</a>`;
}
- return `<a href="${options.prefix}${form}">${form}</a>`;
+ return `<a href="${safeHref}">${safeForm}</a>`;
}
/**
* Groups an address
@@ -908,13 +926,13 @@
group() {
if (this.elidedGroups === 0) {
// The simple case
- return helpers.simpleGroup(this.address).join(':');
+ return helpers.simpleGroup(this.addressMinusSuffix).join(':');
}
assert(typeof this.elidedGroups === 'number');
assert(typeof this.elisionBegin === 'number');
// The elided case
const output = [];
- const [left, right] = this.address.split('::');
+ const [left, right] = this.addressMinusSuffix.split('::');
if (left.length) {
output.push(...helpers.simpleGroup(left));
}
@@ -1000,4 +1018,3 @@
}
}
exports.Address6 = Address6;
-//# sourceMappingURL=ipv6.js.map
\ No newline at end of file
diff --git a/deps/npm/node_modules/ip-address/package.json b/deps/npm/node_modules/ip-address/package.json
index 1234567..abcdefg 100644
--- a/deps/npm/node_modules/ip-address/package.json
+++ b/deps/npm/node_modules/ip-address/package.json
@@ -7,7 +7,7 @@
"browser",
"validation"
],
- "version": "10.1.0",
+ "version": "10.1.1",
"author": "Beau Gunderson <beau@beaugunderson.com> (https://beaugunderson.com/)",
"license": "MIT",
"main": "dist/ip-address.js",

View File

@ -1,100 +0,0 @@
From 213dc171de329a09f34c7a3222cad723ee65d693 Mon Sep 17 00:00:00 2001
From: RHEL Packaging Agent <redhat-ymir-agent@redhat.com>
Date: Tue, 14 Jul 2026 08:27:05 +0000
Subject: [PATCH] CVE-2026-13149: Fix unbound recursion in brace-expansion
A run of non-expanding {} groups expanded post once per group before the
early returns that never use it, doubling the work on every group. expand()
ran in O(2^n) and blocked for minutes on a ~90 byte input.
Defer expanding post until a brace set is known to expand, and turn the
{a},b} restart into a loop so a long run of {} groups can't exhaust the
call stack.
Adapted from upstream TypeScript fix to the JavaScript version (2.0.2)
vendored in Node.js.
Upstream: https://github.com/juliangruber/brace-expansion/commit/c7e33ec
---
.../npm/node_modules/brace-expansion/index.js | 49 ++++++++++++-------
1 file changed, 32 insertions(+), 17 deletions(-)
diff --git a/deps/npm/node_modules/brace-expansion/index.js b/deps/npm/node_modules/brace-expansion/index.js
index d084bac4..5d5f61ff 100644
--- a/deps/npm/node_modules/brace-expansion/index.js
+++ b/deps/npm/node_modules/brace-expansion/index.js
@@ -99,21 +99,27 @@ function gte(i, y) {
function expand(str, max, isTop) {
var expansions = [];
- var m = balanced('{', '}', str);
- if (!m) return [str];
-
- // no need to expand pre, since it is guaranteed to be free of brace-sets
- var pre = m.pre;
- var post = m.post.length
- ? expand(m.post, max, false)
- : [''];
-
- if (/\$$/.test(m.pre)) {
- for (var k = 0; k < post.length && k < max; k++) {
- var expansion = pre+ '{' + m.body + '}' + post[k];
- expansions.push(expansion);
+ // The {a},b} rewrite below restarts expansion on a rewritten string with
+ // the same max and isTop = true. Loop instead of recursing so a long run
+ // of non-expanding {} groups can't exhaust the call stack.
+ for (;;) {
+ var m = balanced('{', '}', str);
+ if (!m) return [str];
+
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
+ var pre = m.pre;
+
+ if (/\$$/.test(m.pre)) {
+ var post = m.post.length
+ ? expand(m.post, max, false)
+ : [''];
+ for (var k = 0; k < post.length && k < max; k++) {
+ var expansion = pre+ '{' + m.body + '}' + post[k];
+ expansions.push(expansion);
+ }
+ return expansions;
}
- } else {
+
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
var isSequence = isNumericSequence || isAlphaSequence;
@@ -122,11 +128,20 @@ function expand(str, max, isTop) {
// {a},b}
if (m.post.match(/,(?!,).*\}/)) {
str = m.pre + '{' + m.body + escClose + m.post;
- return expand(str, max, true);
+ isTop = true;
+ continue;
}
return [str];
}
+ // Only expand post once we know this brace set actually expands. Computing
+ // it before the early returns above expanded post a second time on every
+ // non-expanding {}, which is what made inputs like a{},{},{}... blow up
+ // exponentially.
+ var post = m.post.length
+ ? expand(m.post, max, false)
+ : [''];
+
var n;
if (isSequence) {
n = m.body.split(/\.\./);
@@ -200,8 +215,8 @@ function expand(str, max, isTop) {
expansions.push(expansion);
}
}
- }
- return expansions;
+ return expansions;
+ }
}

View File

@ -67,7 +67,7 @@
# This is used by both the nodejs package and the npm subpackage that
# has a separate version - the name is special so that rpmdev-bumpspec
# will bump this rather than adding .1 to the end.
%global baserelease 2
%global baserelease 3
%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
@ -163,7 +163,7 @@
%global histogram_version 0.11.9
# sqlite from deps/sqlite/sqlite3.h
%global sqlite_version 3.51.3
%global sqlite_version 3.53.4
# Version: jq '.version' deps/undici/src/package.json
%global undici_version 6.27.0
@ -223,12 +223,14 @@ Source301: test-should-pass.txt
Patch1: 0001-Remove-unused-OpenSSL-config.patch
Patch2: 0002-fips-disable-options.patch
Patch3: 0001-CVE-2026-25547-braces-expansion.patch
# npm deps patches
Patch4: 0002-CVE-2026-42338-npm-ip-address-security-fix.patch
Patch5: 0003-CVE-2026-59873-CVE-2026-59874-upgrade-bundled-tar-to-7.5.19.patch
Patch6: 0004-CVE-2026-13149-brace-expansion-unbound-recursion.patch
Patch3: 0003-CVE-2026-59873-CVE-2026-59874-upgrade-bundled-tar-to-7.5.19.patch
# CVE-2026-11824 and CVE-2026-11822
Patch4: 0001-update-sqlite-to-3.53.4.patch
# CVE-2026-69192-CVE-2026-54272 within deps/npm/../ip-address
Patch5: 0001-CVE-2026-69192-CVE-2026-54272-ip-address-10.4.0.patch
# Brace-expansion rebase to 2.1.4
Patch6: 0001-CVE-2026-69152-brace-expansion-2.1.4.patch
%global pkgname nodejs
BuildRequires: make
@ -959,6 +961,16 @@ end
%changelog
* Wed Aug 5 2026 Tomas Juhasz <tjuhasz@redhat.com> - 1:22.23.1-3
- deps: update npm/ip-address to 10.4.0
- deps: update npm/brace-expansion to 2.1.4
Fix: CVE-2026-69192 & CVE-2026-54272 CVE-2026-69152
* Fri Jul 31 2026 Andrei Radchenko <aradchen@redhat.com> - 1:22.23.1-3
- Backport patch: update sqlite to 3.53.4
Fix: CVE-2026-11824, CVE-2026-11822
Resolves: RHEL-224135 RHEL-224144
* Thu Jul 23 2026 Jan Staněk <jstanek@redhat.com> - 1:22.23.1-2
- Backport patches for various CVEs
Fixes: CVE-2026-59873 CVE-2026-59874 CVE-2026-13149