import UBI nodejs-22.23.1-3.module+el8.10.0+24640+6eba5e6e
This commit is contained in:
parent
eb93c3f399
commit
b225097bcd
@ -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);
|
|
||||||
391
SOURCES/0001-CVE-2026-69152-brace-expansion-2.1.4.patch
Normal file
391
SOURCES/0001-CVE-2026-69152-brace-expansion-2.1.4.patch
Normal 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"
|
||||||
|
|
||||||
1994
SOURCES/0001-CVE-2026-69192-CVE-2026-54272-ip-address-10.4.0.patch
Normal file
1994
SOURCES/0001-CVE-2026-69192-CVE-2026-54272-ip-address-10.4.0.patch
Normal file
File diff suppressed because it is too large
Load Diff
21461
SOURCES/0001-update-sqlite-to-3.53.4.patch
Normal file
21461
SOURCES/0001-update-sqlite-to-3.53.4.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -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, '&')
|
|
||||||
+ .replace(/</g, '<')
|
|
||||||
+ .replace(/>/g, '>')
|
|
||||||
+ .replace(/"/g, '"')
|
|
||||||
+ .replace(/'/g, ''');
|
|
||||||
+}
|
|
||||||
/**
|
|
||||||
* @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",
|
|
||||||
@ -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;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -67,7 +67,7 @@
|
|||||||
# This is used by both the nodejs package and the npm subpackage that
|
# 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
|
# has a separate version - the name is special so that rpmdev-bumpspec
|
||||||
# will bump this rather than adding .1 to the end.
|
# will bump this rather than adding .1 to the end.
|
||||||
%global baserelease 2
|
%global baserelease 3
|
||||||
|
|
||||||
%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
|
%{?!_pkgdocdir:%global _pkgdocdir %{_docdir}/%{name}-%{version}}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@
|
|||||||
%global histogram_version 0.11.9
|
%global histogram_version 0.11.9
|
||||||
|
|
||||||
# sqlite – from deps/sqlite/sqlite3.h
|
# 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
|
# Version: jq '.version' deps/undici/src/package.json
|
||||||
%global undici_version 6.27.0
|
%global undici_version 6.27.0
|
||||||
@ -223,12 +223,14 @@ Source301: test-should-pass.txt
|
|||||||
|
|
||||||
Patch1: 0001-Remove-unused-OpenSSL-config.patch
|
Patch1: 0001-Remove-unused-OpenSSL-config.patch
|
||||||
Patch2: 0002-fips-disable-options.patch
|
Patch2: 0002-fips-disable-options.patch
|
||||||
Patch3: 0001-CVE-2026-25547-braces-expansion.patch
|
|
||||||
# npm deps patches
|
# npm deps patches
|
||||||
Patch4: 0002-CVE-2026-42338-npm-ip-address-security-fix.patch
|
Patch3: 0003-CVE-2026-59873-CVE-2026-59874-upgrade-bundled-tar-to-7.5.19.patch
|
||||||
Patch5: 0003-CVE-2026-59873-CVE-2026-59874-upgrade-bundled-tar-to-7.5.19.patch
|
# CVE-2026-11824 and CVE-2026-11822
|
||||||
Patch6: 0004-CVE-2026-13149-brace-expansion-unbound-recursion.patch
|
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
|
%global pkgname nodejs
|
||||||
|
|
||||||
BuildRequires: make
|
BuildRequires: make
|
||||||
@ -959,6 +961,16 @@ end
|
|||||||
|
|
||||||
|
|
||||||
%changelog
|
%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
|
* Thu Jul 23 2026 Jan Staněk <jstanek@redhat.com> - 1:22.23.1-2
|
||||||
- Backport patches for various CVEs
|
- Backport patches for various CVEs
|
||||||
Fixes: CVE-2026-59873 CVE-2026-59874 CVE-2026-13149
|
Fixes: CVE-2026-59873 CVE-2026-59874 CVE-2026-13149
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user