@cypress/github-action 7.4.5 → 7.4.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +78 -22
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -14465,6 +14465,26 @@ var EXPANSION_MAX = 100000
|
|
|
14465
14465
|
// characters) so legitimate input is unaffected.
|
|
14466
14466
|
var EXPANSION_MAX_LENGTH = 4000000
|
|
14467
14467
|
|
|
14468
|
+
// `expand` recurses once per level of brace *nesting* - both when expanding a
|
|
14469
|
+
// set's comma members and when re-wrapping a set whose body is a single part.
|
|
14470
|
+
// The CVE-2026-14257 fix made the *tail* iterative (recursion on `m.post`, one
|
|
14471
|
+
// level per chained group), which left nesting depth unbounded: about 3,100
|
|
14472
|
+
// levels of `{{{...a,b...}}}` - only ~6KB of input - exhausted the native stack
|
|
14473
|
+
// and crashed the process. `EXPANSION_MAX_DEPTH` bounds how deep the parser
|
|
14474
|
+
// will follow nesting. It sits far above any realistic pattern and well below
|
|
14475
|
+
// the depth at which the stack runs out.
|
|
14476
|
+
var EXPANSION_MAX_DEPTH = 1000
|
|
14477
|
+
|
|
14478
|
+
// Bash keeps a quirk where a brace group followed by a comma set still expands
|
|
14479
|
+
// (`{a},b}`). The parser implements it by rewriting the string and restarting
|
|
14480
|
+
// the scan, absorbing one `}` per pass. `n` trailing braces therefore cost `n`
|
|
14481
|
+
// full passes over a string that itself grows by one `escClose` sentinel each
|
|
14482
|
+
// time - quadratic in `n`, with a ~26x constant from the sentinel's length.
|
|
14483
|
+
// 128KB of `'{a}' + '}'.repeat(n) + ',z}'` blocked the event loop for 27
|
|
14484
|
+
// seconds to produce two results. `EXPANSION_MAX_REWRITES` bounds how many
|
|
14485
|
+
// times the scan may restart. Real `{a},b}` input needs a handful.
|
|
14486
|
+
var EXPANSION_MAX_REWRITES = 1000
|
|
14487
|
+
|
|
14468
14488
|
function numeric(str) {
|
|
14469
14489
|
return parseInt(str, 10) == str
|
|
14470
14490
|
? parseInt(str, 10)
|
|
@@ -14488,34 +14508,54 @@ function unescapeBraces(str) {
|
|
|
14488
14508
|
}
|
|
14489
14509
|
|
|
14490
14510
|
|
|
14511
|
+
// Like `target.push(...items)` but doesn't overflow the stack
|
|
14512
|
+
function pushAll(target, items) {
|
|
14513
|
+
for (var i = 0; i < items.length; i++) {
|
|
14514
|
+
target.push(items[i]);
|
|
14515
|
+
}
|
|
14516
|
+
}
|
|
14517
|
+
|
|
14491
14518
|
// Basically just str.split(","), but handling cases
|
|
14492
14519
|
// where we have nested braced sections, which should be
|
|
14493
14520
|
// treated as individual members, like {a,{b,c},d}
|
|
14494
14521
|
function parseCommaParts(str) {
|
|
14495
|
-
if (!str)
|
|
14496
|
-
return [''];
|
|
14497
|
-
|
|
14498
14522
|
var parts = [];
|
|
14499
|
-
var m = balanced('{', '}', str);
|
|
14500
14523
|
|
|
14501
|
-
|
|
14502
|
-
|
|
14524
|
+
// Walk the brace groups iteratively. Recursing on `post` once per group let a
|
|
14525
|
+
// chain of them exhaust the stack - the parsing-side counterpart to
|
|
14526
|
+
// the `expand` overflow fixed for CVE-2026-14257, and not something `max` or
|
|
14527
|
+
// `maxLength` can bound, since it happens before expansion.
|
|
14528
|
+
//
|
|
14529
|
+
// The part the next chunk continues
|
|
14530
|
+
var carry = '';
|
|
14503
14531
|
|
|
14504
|
-
|
|
14505
|
-
|
|
14506
|
-
var post = m.post;
|
|
14507
|
-
var p = pre.split(',');
|
|
14532
|
+
for (;;) {
|
|
14533
|
+
var m = balanced('{', '}', str);
|
|
14508
14534
|
|
|
14509
|
-
|
|
14510
|
-
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14535
|
+
if (!m) {
|
|
14536
|
+
var tail = str.split(',');
|
|
14537
|
+
tail[0] = carry + tail[0];
|
|
14538
|
+
pushAll(parts, tail);
|
|
14539
|
+
return parts;
|
|
14540
|
+
}
|
|
14515
14541
|
|
|
14516
|
-
|
|
14542
|
+
var pre = m.pre;
|
|
14543
|
+
var body = m.body;
|
|
14544
|
+
var post = m.post;
|
|
14545
|
+
var p = pre.split(',');
|
|
14517
14546
|
|
|
14518
|
-
|
|
14547
|
+
p[0] = carry + p[0];
|
|
14548
|
+
p[p.length-1] += '{' + body + '}';
|
|
14549
|
+
|
|
14550
|
+
if (!post.length) {
|
|
14551
|
+
pushAll(parts, p);
|
|
14552
|
+
return parts;
|
|
14553
|
+
}
|
|
14554
|
+
|
|
14555
|
+
carry = p.pop();
|
|
14556
|
+
pushAll(parts, p);
|
|
14557
|
+
str = post;
|
|
14558
|
+
}
|
|
14519
14559
|
}
|
|
14520
14560
|
|
|
14521
14561
|
function expandTop(str, options) {
|
|
@@ -14525,6 +14565,8 @@ function expandTop(str, options) {
|
|
|
14525
14565
|
options = options || {};
|
|
14526
14566
|
var max = options.max == null ? EXPANSION_MAX : options.max;
|
|
14527
14567
|
var maxLength = options.maxLength == null ? EXPANSION_MAX_LENGTH : options.maxLength;
|
|
14568
|
+
var maxDepth = options.maxDepth == null ? EXPANSION_MAX_DEPTH : options.maxDepth;
|
|
14569
|
+
var maxRewrites = options.maxRewrites == null ? EXPANSION_MAX_REWRITES : options.maxRewrites;
|
|
14528
14570
|
|
|
14529
14571
|
// I don't know why Bash 4.3 does this, but it does.
|
|
14530
14572
|
// Anything starting with {} will have the first two bytes preserved
|
|
@@ -14536,7 +14578,7 @@ function expandTop(str, options) {
|
|
|
14536
14578
|
str = '\\{\\}' + str.substr(2);
|
|
14537
14579
|
}
|
|
14538
14580
|
|
|
14539
|
-
return expand(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
|
|
14581
|
+
return expand(escapeBraces(str), max, maxLength, maxDepth, 0, maxRewrites, true).map(unescapeBraces);
|
|
14540
14582
|
}
|
|
14541
14583
|
|
|
14542
14584
|
function identity(e) {
|
|
@@ -14660,8 +14702,18 @@ function expand(
|
|
|
14660
14702
|
str,
|
|
14661
14703
|
max,
|
|
14662
14704
|
maxLength,
|
|
14705
|
+
maxDepth,
|
|
14706
|
+
depth,
|
|
14707
|
+
maxRewrites,
|
|
14663
14708
|
isTop
|
|
14664
14709
|
) {
|
|
14710
|
+
// Too deeply nested to keep following: treat the rest as literal, the same
|
|
14711
|
+
// way a group that cannot expand is already handled. Truncating rather than
|
|
14712
|
+
// throwing keeps expansion total, matching `max` and `maxLength`.
|
|
14713
|
+
if (depth > maxDepth) {
|
|
14714
|
+
return [str];
|
|
14715
|
+
}
|
|
14716
|
+
|
|
14665
14717
|
// Consume the string's top-level brace groups left to right, threading a
|
|
14666
14718
|
// running set of combined prefixes (`acc`). Expanding the tail iteratively -
|
|
14667
14719
|
// rather than recursing on `m.post` once per group - keeps the native stack
|
|
@@ -14682,6 +14734,9 @@ function expand(
|
|
|
14682
14734
|
// `accBase[a]` records how much of `acc[a]` predates the current run;
|
|
14683
14735
|
// `combine` treats an expansion as empty when it adds nothing past that.
|
|
14684
14736
|
var accBase = [0]
|
|
14737
|
+
// How many times the `{a},b}` rewrite below has restarted the scan. Each pass
|
|
14738
|
+
// re-reads the whole string, so leaving this unbounded is quadratic.
|
|
14739
|
+
var rewrites = 0
|
|
14685
14740
|
var dropEmpties = false
|
|
14686
14741
|
var firstGroup = true
|
|
14687
14742
|
var nextBase
|
|
@@ -14713,7 +14768,8 @@ function expand(
|
|
|
14713
14768
|
var isOptions = m.body.indexOf(',') >= 0;
|
|
14714
14769
|
if (!isSequence && !isOptions) {
|
|
14715
14770
|
// {a},b}
|
|
14716
|
-
if (m.post.match(/,(?!,).*\}/)) {
|
|
14771
|
+
if (rewrites < maxRewrites && m.post.match(/,(?!,).*\}/)) {
|
|
14772
|
+
rewrites++;
|
|
14717
14773
|
str = m.pre + '{' + m.body + escClose + m.post;
|
|
14718
14774
|
// The rewritten string is expanded as if it were a fresh top-level one,
|
|
14719
14775
|
// so start a new empty-drop run: anchor the baseline at what `acc`
|
|
@@ -14752,7 +14808,7 @@ function expand(
|
|
|
14752
14808
|
var n = parseCommaParts(m.body);
|
|
14753
14809
|
if (n.length === 1 && n[0] !== undefined) {
|
|
14754
14810
|
// x{{a,b}}y ==> x{a}y x{b}y
|
|
14755
|
-
n = expand(n[0], max, maxLength, false).map(embrace);
|
|
14811
|
+
n = expand(n[0], max, maxLength, maxDepth, depth + 1, maxRewrites, false).map(embrace);
|
|
14756
14812
|
//XXX is this necessary? Can't seem to hit it in tests.
|
|
14757
14813
|
/* c8 ignore start */
|
|
14758
14814
|
if (n.length === 1) {
|
|
@@ -14791,7 +14847,7 @@ function expand(
|
|
|
14791
14847
|
values = []
|
|
14792
14848
|
var valuesLength = 0
|
|
14793
14849
|
outer: for (var j = 0; j < n.length; j++) {
|
|
14794
|
-
var expanded = expand(n[j], max, maxLength, false)
|
|
14850
|
+
var expanded = expand(n[j], max, maxLength, maxDepth, depth + 1, maxRewrites, false)
|
|
14795
14851
|
for (var k = 0; k < expanded.length; k++) {
|
|
14796
14852
|
var v = expanded[k]
|
|
14797
14853
|
if (dropsEmpties && !v) continue
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cypress/github-action",
|
|
3
|
-
"version": "7.4.
|
|
3
|
+
"version": "7.4.6",
|
|
4
4
|
"description": "GitHub Action for running Cypress end-to-end and component tests",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"globals": "17.11.0",
|
|
63
63
|
"husky": "9.1.7",
|
|
64
64
|
"markdown-link-check": "3.15.0",
|
|
65
|
-
"prettier": "3.9.
|
|
65
|
+
"prettier": "3.9.9"
|
|
66
66
|
},
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"access": "public"
|