@cypress/github-action 7.4.1 → 7.4.3

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.
Files changed (3) hide show
  1. package/README.md +6 -27
  2. package/dist/index.js +408 -103
  3. package/package.json +8 -8
package/README.md CHANGED
@@ -75,7 +75,6 @@ The following examples demonstrate the actions' functions.
75
75
  - Split [install and tests](#split-install-and-tests) into separate jobs
76
76
  - Split [install and tests](#split-install-and-test-with-artifacts) with artifacts
77
77
  - Use [custom install commands](#custom-install)
78
- - Install [only Cypress](#install-cypress-only) to avoid installing all dependencies
79
78
  - Use [timeouts](#timeouts) to avoid hanging CI jobs
80
79
  - Print [Cypress info](#print-cypress-info) like detected browsers
81
80
  - Run [tests nightly](#nightly-tests) or on any schedule
@@ -598,7 +597,7 @@ jobs:
598
597
  - name: Checkout
599
598
  uses: actions/checkout@v7
600
599
  - name: Install Node.js
601
- uses: actions/setup-node@v6
600
+ uses: actions/setup-node@v7
602
601
  with:
603
602
  node-version: ${{ matrix.node }}
604
603
  - run: node -v
@@ -1218,7 +1217,7 @@ jobs:
1218
1217
  with:
1219
1218
  version: 11
1220
1219
  - name: Install Node.js
1221
- uses: actions/setup-node@v6
1220
+ uses: actions/setup-node@v7
1222
1221
  with:
1223
1222
  node-version: 24
1224
1223
  cache: 'pnpm'
@@ -1298,7 +1297,7 @@ jobs:
1298
1297
  uses: actions/checkout@v7
1299
1298
  - run: corepack enable # (experimental and optional)
1300
1299
  - name: Set up Yarn cache
1301
- uses: actions/setup-node@v6
1300
+ uses: actions/setup-node@v7
1302
1301
  with:
1303
1302
  node-version: 24
1304
1303
  cache: yarn
@@ -1391,7 +1390,7 @@ jobs:
1391
1390
  name:
1392
1391
  steps:
1393
1392
  - uses: actions/checkout@v7
1394
- - uses: actions/setup-node@v6
1393
+ - uses: actions/setup-node@v7
1395
1394
  with:
1396
1395
  node-version: lts
1397
1396
  cache: 'pnpm'
@@ -1423,7 +1422,7 @@ jobs:
1423
1422
  - name: Checkout
1424
1423
  uses: actions/checkout@v7
1425
1424
  - name: Install Node.js
1426
- uses: actions/setup-node@v6
1425
+ uses: actions/setup-node@v7
1427
1426
  with:
1428
1427
  node-version: ${{ matrix.node }}
1429
1428
  # run Cypress tests and record them under the same run
@@ -1458,7 +1457,7 @@ jobs:
1458
1457
  name: E2E on Node v${{ matrix.node }}
1459
1458
  steps:
1460
1459
  - uses: actions/checkout@v7
1461
- - uses: actions/setup-node@v6
1460
+ - uses: actions/setup-node@v7
1462
1461
  with:
1463
1462
  node-version: ${{ matrix.node }}
1464
1463
  - uses: cypress-io/github-action@v7
@@ -1549,26 +1548,6 @@ jobs:
1549
1548
 
1550
1549
  Finally, you might not need this GH Action at all. For example, if you want to split the npm dependencies installation from the Cypress binary installation, then it makes no sense to use this action. Instead you can install and cache Cypress yourself.
1551
1550
 
1552
- ### Install Cypress only
1553
-
1554
- If the project has many dependencies, but you want to install just Cypress you can combine this action with `actions/cache` and `npm i cypress` commands yourself.
1555
-
1556
- ```yml
1557
- - uses: actions/checkout@v7
1558
- - uses: actions/cache@v5
1559
- with:
1560
- path: |
1561
- ~/.cache/Cypress
1562
- node_modules
1563
- key: my-cache-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
1564
- - run: npm i cypress
1565
- - uses: cypress-io/github-action@v7
1566
- with:
1567
- install: false
1568
- ```
1569
-
1570
- [![Install only Cypress example](https://github.com/cypress-io/github-action/actions/workflows/example-install-only.yml/badge.svg)](.github/workflows/example-install-only.yml)
1571
-
1572
1551
  ### Timeouts
1573
1552
 
1574
1553
  You can tell the CI to stop the job or the individual step if it runs for longer then a given time limit. This is a good practice to ensure the hanging process does not accidentally use up all your CI minutes.
package/dist/index.js CHANGED
@@ -15027,6 +15027,20 @@ var escClose = '\0CLOSE'+Math.random()+'\0';
15027
15027
  var escComma = '\0COMMA'+Math.random()+'\0';
15028
15028
  var escPeriod = '\0PERIOD'+Math.random()+'\0';
15029
15029
 
15030
+ var EXPANSION_MAX = 100000
15031
+
15032
+ // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
15033
+ // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
15034
+ // truncated to 100k results - while making every result ~1500 characters
15035
+ // long. The result set, and the intermediate arrays built while combining
15036
+ // brace sets, then grow large enough to exhaust memory and crash the process
15037
+ // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
15038
+ // characters the accumulator may hold at any point, so memory stays flat no
15039
+ // matter how many brace groups are chained. The limit sits well above any
15040
+ // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
15041
+ // characters) so legitimate input is unaffected.
15042
+ var EXPANSION_MAX_LENGTH = 4000000
15043
+
15030
15044
  function numeric(str) {
15031
15045
  return parseInt(str, 10) == str
15032
15046
  ? parseInt(str, 10)
@@ -15080,10 +15094,14 @@ function parseCommaParts(str) {
15080
15094
  return parts;
15081
15095
  }
15082
15096
 
15083
- function expandTop(str) {
15097
+ function expandTop(str, options) {
15084
15098
  if (!str)
15085
15099
  return [];
15086
15100
 
15101
+ options = options || {};
15102
+ var max = options.max == null ? EXPANSION_MAX : options.max;
15103
+ var maxLength = options.maxLength == null ? EXPANSION_MAX_LENGTH : options.maxLength;
15104
+
15087
15105
  // I don't know why Bash 4.3 does this, but it does.
15088
15106
  // Anything starting with {} will have the first two bytes preserved
15089
15107
  // but *only* at the top level, so {},a}b will not expand to anything,
@@ -15094,7 +15112,7 @@ function expandTop(str) {
15094
15112
  str = '\\{\\}' + str.substr(2);
15095
15113
  }
15096
15114
 
15097
- return expand(escapeBraces(str), true).map(unescapeBraces);
15115
+ return expand(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
15098
15116
  }
15099
15117
 
15100
15118
  function identity(e) {
@@ -15115,106 +15133,270 @@ function gte(i, y) {
15115
15133
  return i >= y;
15116
15134
  }
15117
15135
 
15118
- function expand(str, isTop) {
15119
- var expansions = [];
15120
-
15121
- var m = balanced('{', '}', str);
15122
- if (!m || /\$$/.test(m.pre)) return [str];
15123
-
15124
- var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
15125
- var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
15126
- var isSequence = isNumericSequence || isAlphaSequence;
15127
- var isOptions = m.body.indexOf(',') >= 0;
15128
- if (!isSequence && !isOptions) {
15129
- // {a},b}
15130
- if (m.post.match(/,(?!,).*\}/)) {
15131
- str = m.pre + '{' + m.body + escClose + m.post;
15132
- return expand(str);
15136
+ // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
15137
+ // number of results at `max` and the total number of characters at `maxLength`.
15138
+ // This is the one place output grows, so bounding it here keeps the single
15139
+ // accumulator - and therefore memory - flat regardless of how many brace groups
15140
+ // are combined (CVE-2026-14257).
15141
+ //
15142
+ // `base[a]` is the length of the part of `acc[a]` that predates the current
15143
+ // empty-drop baseline (see `expand`). The matching baselines for the results
15144
+ // are appended to `outBase`, which the caller carries forward alongside them.
15145
+ function combine(
15146
+ acc,
15147
+ base,
15148
+ pre,
15149
+ values,
15150
+ max,
15151
+ maxLength,
15152
+ dropEmpties,
15153
+ outBase
15154
+ ) {
15155
+ var out = []
15156
+ var length = 0
15157
+ for (var a = 0; a < acc.length; a++) {
15158
+ for (var v = 0; v < values.length; v++) {
15159
+ if (out.length >= max) return out
15160
+ var expansion = acc[a] + pre + values[v]
15161
+ // Bash drops empty results at the top level. Skip them before they count
15162
+ // against `max`, so `max` bounds the number of *kept* results. "Empty"
15163
+ // means "adds nothing past the baseline", not "empty overall".
15164
+ if (dropEmpties && expansion.length === base[a]) continue
15165
+ if (length + expansion.length > maxLength) return out
15166
+ out.push(expansion)
15167
+ outBase.push(base[a])
15168
+ length += expansion.length
15133
15169
  }
15134
- return [str];
15135
15170
  }
15171
+ return out
15172
+ }
15136
15173
 
15137
- var n;
15138
- if (isSequence) {
15139
- n = m.body.split(/\.\./);
15140
- } else {
15141
- n = parseCommaParts(m.body);
15142
- if (n.length === 1) {
15143
- // x{{a,b}}y ==> x{a}y x{b}y
15144
- n = expand(n[0], false).map(embrace);
15145
- if (n.length === 1) {
15146
- var post = m.post.length
15147
- ? expand(m.post, false)
15148
- : [''];
15149
- return post.map(function(p) {
15150
- return m.pre + n[0] + p;
15151
- });
15174
+ // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
15175
+ // sequence body.
15176
+ function expandSequence(
15177
+ body,
15178
+ isAlphaSequence,
15179
+ max,
15180
+ maxLength
15181
+ ) {
15182
+ var n = body.split(/\.\./)
15183
+ var N = []
15184
+ // A sequence body always splits into two or three parts, but the compiler
15185
+ // can't know that.
15186
+ /* c8 ignore start */
15187
+ if (n[0] === undefined || n[1] === undefined) {
15188
+ return N
15189
+ }
15190
+ /* c8 ignore stop */
15191
+ var x = numeric(n[0])
15192
+ var y = numeric(n[1])
15193
+ var width = Math.max(n[0].length, n[1].length)
15194
+ var incr =
15195
+ n.length === 3 && n[2] !== undefined ?
15196
+ Math.max(Math.abs(numeric(n[2])), 1)
15197
+ : 1
15198
+ var test = lte
15199
+ var reverse = y < x
15200
+ if (reverse) {
15201
+ incr *= -1
15202
+ test = gte
15203
+ }
15204
+ var pad = n.some(isPadded)
15205
+
15206
+ var length = 0
15207
+ for (var i = x; test(i, y) && N.length < max; i += incr) {
15208
+ var c
15209
+ if (isAlphaSequence) {
15210
+ c = String.fromCharCode(i)
15211
+ if (c === '\\') {
15212
+ c = ''
15213
+ }
15214
+ } else {
15215
+ c = String(i)
15216
+ if (pad) {
15217
+ var need = width - c.length
15218
+ if (need > 0) {
15219
+ var z = new Array(need + 1).join('0')
15220
+ if (i < 0) {
15221
+ c = '-' + z + c.slice(1)
15222
+ } else {
15223
+ c = z + c
15224
+ }
15225
+ }
15152
15226
  }
15153
15227
  }
15228
+ if (length + c.length > maxLength) break
15229
+ N.push(c)
15230
+ length += c.length
15154
15231
  }
15232
+ return N
15233
+ }
15155
15234
 
15156
- // at this point, n is the parts, and we know it's not a comma set
15157
- // with a single entry.
15235
+ function expand(
15236
+ str,
15237
+ max,
15238
+ maxLength,
15239
+ isTop
15240
+ ) {
15241
+ // Consume the string's top-level brace groups left to right, threading a
15242
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
15243
+ // rather than recursing on `m.post` once per group - keeps the native stack
15244
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
15245
+ // longer overflow the stack, and leaves a single accumulator whose size
15246
+ // `maxLength` bounds directly (CVE-2026-14257).
15247
+ var acc = ['']
15248
+
15249
+ // Bash drops empty results, but only when the *first* group of the run is a
15250
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
15251
+ // is on the final strings, so it is applied to whichever `combine` produces
15252
+ // them (the one with no brace set left in the tail).
15253
+ //
15254
+ // The old implementation recursed on `m.post`, so the drop tested only the
15255
+ // expansion of the current call's substring. The `{a},b}` rewrite below turns
15256
+ // `isTop` back on part-way through a string, starting a fresh such run, so
15257
+ // the drop must ignore whatever `acc` already holds from earlier groups.
15258
+ // `accBase[a]` records how much of `acc[a]` predates the current run;
15259
+ // `combine` treats an expansion as empty when it adds nothing past that.
15260
+ var accBase = [0]
15261
+ var dropEmpties = false
15262
+ var firstGroup = true
15263
+ var nextBase
15264
+
15265
+ for (;;) {
15266
+ var m = balanced('{', '}', str);
15267
+
15268
+ // No brace set left: the rest of the string is literal.
15269
+ if (!m) {
15270
+ return combine(acc, accBase, str, [''], max, maxLength, dropEmpties, [])
15271
+ }
15272
+
15273
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
15274
+ var pre = m.pre;
15275
+
15276
+ // For compatibility reasons, `${` is not eligible for brace expansion, and
15277
+ // on the 1.x line it suppresses expansion of the rest of the string too:
15278
+ // the whole remainder is literal. The 2.x and 5.x lines instead keep
15279
+ // expanding the tail, which is what bash does, but changing that here would
15280
+ // be a breaking change for 1.x consumers. Routed through `combine` so the
15281
+ // result is still bounded by `max` and `maxLength`.
15282
+ if (/\$$/.test(pre)) {
15283
+ return combine(acc, accBase, str, [''], max, maxLength, dropEmpties, [])
15284
+ }
15285
+
15286
+ var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
15287
+ var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
15288
+ var isSequence = isNumericSequence || isAlphaSequence;
15289
+ var isOptions = m.body.indexOf(',') >= 0;
15290
+ if (!isSequence && !isOptions) {
15291
+ // {a},b}
15292
+ if (m.post.match(/,(?!,).*\}/)) {
15293
+ str = m.pre + '{' + m.body + escClose + m.post;
15294
+ // The rewritten string is expanded as if it were a fresh top-level one,
15295
+ // so start a new empty-drop run: anchor the baseline at what `acc`
15296
+ // holds now, and let the next expanding group decide whether to drop.
15297
+ isTop = true
15298
+ firstGroup = true
15299
+ dropEmpties = false
15300
+ accBase = []
15301
+ for (var b = 0; b < acc.length; b++) {
15302
+ accBase.push(acc[b].length)
15303
+ }
15304
+ continue
15305
+ }
15306
+ // Nothing here expands, so the whole remaining string is literal.
15307
+ return combine(
15308
+ acc,
15309
+ accBase,
15310
+ pre + '{' + m.body + '}' + m.post,
15311
+ [''],
15312
+ max,
15313
+ maxLength,
15314
+ dropEmpties,
15315
+ []
15316
+ )
15317
+ }
15158
15318
 
15159
- // no need to expand pre, since it is guaranteed to be free of brace-sets
15160
- var pre = m.pre;
15161
- var post = m.post.length
15162
- ? expand(m.post, false)
15163
- : [''];
15164
-
15165
- var N;
15166
-
15167
- if (isSequence) {
15168
- var x = numeric(n[0]);
15169
- var y = numeric(n[1]);
15170
- var width = Math.max(n[0].length, n[1].length)
15171
- var incr = n.length == 3
15172
- ? Math.max(Math.abs(numeric(n[2])), 1)
15173
- : 1;
15174
- var test = lte;
15175
- var reverse = y < x;
15176
- if (reverse) {
15177
- incr *= -1;
15178
- test = gte;
15179
- }
15180
- var pad = n.some(isPadded);
15181
-
15182
- N = [];
15183
-
15184
- for (var i = x; test(i, y); i += incr) {
15185
- var c;
15186
- if (isAlphaSequence) {
15187
- c = String.fromCharCode(i);
15188
- if (c === '\\')
15189
- c = '';
15190
- } else {
15191
- c = String(i);
15192
- if (pad) {
15193
- var need = width - c.length;
15194
- if (need > 0) {
15195
- var z = new Array(need + 1).join('0');
15196
- if (i < 0)
15197
- c = '-' + z + c.slice(1);
15198
- else
15199
- c = z + c;
15319
+ if (firstGroup) {
15320
+ dropEmpties = isTop && !isSequence
15321
+ firstGroup = false
15322
+ }
15323
+
15324
+ var values;
15325
+ if (isSequence) {
15326
+ values = expandSequence(m.body, isAlphaSequence, max, maxLength);
15327
+ } else {
15328
+ var n = parseCommaParts(m.body);
15329
+ if (n.length === 1 && n[0] !== undefined) {
15330
+ // x{{a,b}}y ==> x{a}y x{b}y
15331
+ n = expand(n[0], max, maxLength, false).map(embrace);
15332
+ //XXX is this necessary? Can't seem to hit it in tests.
15333
+ /* c8 ignore start */
15334
+ if (n.length === 1) {
15335
+ nextBase = []
15336
+ acc = combine(
15337
+ acc,
15338
+ accBase,
15339
+ pre + n[0],
15340
+ [''],
15341
+ max,
15342
+ maxLength,
15343
+ dropEmpties && !m.post.length,
15344
+ nextBase
15345
+ )
15346
+ accBase = nextBase
15347
+ if (!m.post.length) break
15348
+ str = m.post
15349
+ continue
15350
+ }
15351
+ /* c8 ignore stop */
15352
+ }
15353
+
15354
+ // Values that `combine` is going to drop as empty produce no result, so
15355
+ // they must not count against `max` - otherwise `{a,,b}` with `max: 2`
15356
+ // would stop at `['a', '']` and yield one result instead of two. Skipping
15357
+ // them outright keeps `values` bounded while leaving `max` a bound on
15358
+ // *kept* results. A value is dropped when it adds nothing past the
15359
+ // baseline, which is what `combine` tests.
15360
+ var dropsEmpties = dropEmpties && !m.post.length && !pre
15361
+ for (var d = 0; dropsEmpties && d < acc.length; d++) {
15362
+ if (acc[d].length !== accBase[d]) {
15363
+ dropsEmpties = false
15364
+ }
15365
+ }
15366
+
15367
+ values = []
15368
+ var valuesLength = 0
15369
+ outer: for (var j = 0; j < n.length; j++) {
15370
+ var expanded = expand(n[j], max, maxLength, false)
15371
+ for (var k = 0; k < expanded.length; k++) {
15372
+ var v = expanded[k]
15373
+ if (dropsEmpties && !v) continue
15374
+ if (values.length >= max || valuesLength + v.length > maxLength) {
15375
+ break outer
15200
15376
  }
15377
+ values.push(v)
15378
+ valuesLength += v.length
15201
15379
  }
15202
15380
  }
15203
- N.push(c);
15204
15381
  }
15205
- } else {
15206
- N = concatMap(n, function(el) { return expand(el, false) });
15207
- }
15208
15382
 
15209
- for (var j = 0; j < N.length; j++) {
15210
- for (var k = 0; k < post.length; k++) {
15211
- var expansion = pre + N[j] + post[k];
15212
- if (!isTop || isSequence || expansion)
15213
- expansions.push(expansion);
15214
- }
15383
+ nextBase = []
15384
+ acc = combine(
15385
+ acc,
15386
+ accBase,
15387
+ pre,
15388
+ values,
15389
+ max,
15390
+ maxLength,
15391
+ dropEmpties && !m.post.length,
15392
+ nextBase
15393
+ )
15394
+ accBase = nextBase
15395
+ if (!m.post.length) break
15396
+ str = m.post
15215
15397
  }
15216
15398
 
15217
- return expansions;
15399
+ return acc
15218
15400
  }
15219
15401
 
15220
15402
 
@@ -35220,7 +35402,13 @@ function processHeader (request, key, val) {
35220
35402
  } else if (typeof val[i] === 'object') {
35221
35403
  throw new InvalidArgumentError(`invalid ${key} header`)
35222
35404
  } else {
35223
- arr.push(`${val[i]}`)
35405
+ // Coerce primitives (and reject unsafe coercions such as functions
35406
+ // with a crafted toString/Symbol.toPrimitive).
35407
+ const str = `${val[i]}`
35408
+ if (!isValidHeaderValue(str)) {
35409
+ throw new InvalidArgumentError(`invalid ${key} header`)
35410
+ }
35411
+ arr.push(str)
35224
35412
  }
35225
35413
  }
35226
35414
  val = arr
@@ -35231,7 +35419,12 @@ function processHeader (request, key, val) {
35231
35419
  } else if (val === null) {
35232
35420
  val = ''
35233
35421
  } else {
35422
+ // Coerce primitives (and reject unsafe coercions such as functions
35423
+ // with a crafted toString/Symbol.toPrimitive).
35234
35424
  val = `${val}`
35425
+ if (!isValidHeaderValue(val)) {
35426
+ throw new InvalidArgumentError(`invalid ${key} header`)
35427
+ }
35235
35428
  }
35236
35429
 
35237
35430
  if (headerName === 'host') {
@@ -36608,6 +36801,7 @@ const {
36608
36801
  RequestContentLengthMismatchError,
36609
36802
  ResponseContentLengthMismatchError,
36610
36803
  RequestAbortedError,
36804
+ InvalidArgumentError,
36611
36805
  HeadersTimeoutError,
36612
36806
  HeadersOverflowError,
36613
36807
  SocketError,
@@ -37591,8 +37785,16 @@ function writeH1 (client, request) {
37591
37785
  }
37592
37786
  body = bodyStream.stream
37593
37787
  contentLength = bodyStream.length
37594
- } else if (util.isBlobLike(body) && request.contentType == null && body.type) {
37595
- headers.push('content-type', body.type)
37788
+ } else if (util.isBlobLike(body) && request.contentType == null) {
37789
+ const contentType = body.type
37790
+ if (contentType) {
37791
+ const contentTypeValue = `${contentType}`
37792
+ if (!util.isValidHeaderValue(contentTypeValue)) {
37793
+ util.errorRequest(client, request, new InvalidArgumentError('invalid content-type header'))
37794
+ return false
37795
+ }
37796
+ headers.push('content-type', contentTypeValue)
37797
+ }
37596
37798
  }
37597
37799
 
37598
37800
  if (body && typeof body.read === 'function') {
@@ -41079,6 +41281,28 @@ function calculateRetryAfterHeader (retryAfter) {
41079
41281
  return new Date(retryAfter).getTime() - current
41080
41282
  }
41081
41283
 
41284
+ function validatePartialResponseContentLength (headers, range, statusCode, retryCount) {
41285
+ const contentLength = headers['content-length']
41286
+ if (contentLength == null) {
41287
+ return null
41288
+ }
41289
+
41290
+ if (!Number.isFinite(range.start) || !Number.isFinite(range.end)) {
41291
+ return null
41292
+ }
41293
+
41294
+ const length = Number(contentLength)
41295
+ const expectedLength = range.end - range.start + 1
41296
+ if (!Number.isFinite(length) || length !== expectedLength) {
41297
+ return new RequestRetryError('Content-Length mismatch', statusCode, {
41298
+ headers,
41299
+ data: { count: retryCount }
41300
+ })
41301
+ }
41302
+
41303
+ return null
41304
+ }
41305
+
41082
41306
  class RetryHandler {
41083
41307
  constructor (opts, handlers) {
41084
41308
  const { retryOptions, ...dispatchOpts } = opts
@@ -41293,6 +41517,12 @@ class RetryHandler {
41293
41517
  return false
41294
41518
  }
41295
41519
 
41520
+ const contentLengthError = validatePartialResponseContentLength(headers, contentRange, statusCode, this.retryCount)
41521
+ if (contentLengthError != null) {
41522
+ this.abort(contentLengthError)
41523
+ return false
41524
+ }
41525
+
41296
41526
  const { start, size, end = size - 1 } = contentRange
41297
41527
 
41298
41528
  assert(this.start === start, 'content-range mismatch')
@@ -41316,6 +41546,12 @@ class RetryHandler {
41316
41546
  )
41317
41547
  }
41318
41548
 
41549
+ const contentLengthError = validatePartialResponseContentLength(headers, range, statusCode, this.retryCount)
41550
+ if (contentLengthError != null) {
41551
+ this.abort(contentLengthError)
41552
+ return false
41553
+ }
41554
+
41319
41555
  const { start, size, end = size - 1 } = range
41320
41556
  assert(
41321
41557
  start != null && Number.isFinite(start),
@@ -45587,7 +45823,7 @@ function validateCookiePath (path) {
45587
45823
 
45588
45824
  if (
45589
45825
  code < 0x20 || // exclude CTLs (0-31)
45590
- code === 0x7F || // DEL
45826
+ code > 0x7E || // exclude DEL and non-ascii
45591
45827
  code === 0x3B // ;
45592
45828
  ) {
45593
45829
  throw new Error('Invalid cookie path')
@@ -45596,16 +45832,80 @@ function validateCookiePath (path) {
45596
45832
  }
45597
45833
 
45598
45834
  /**
45599
- * I have no idea why these values aren't allowed to be honest,
45600
- * but Deno tests these. - Khafra
45835
+ * <let-dig> ::= <letter> | <digit>
45836
+ *
45837
+ * <letter> ::= any one of the 52 alphabetic characters A through Z in
45838
+ * upper case and a through z in lower case
45839
+ *
45840
+ * <digit> ::= any one of the ten digits 0 through 9r
45841
+ *
45842
+ * @see https://www.rfc-editor.org/rfc/rfc1034#section-3.5
45843
+ * @param {number} code
45844
+ */
45845
+ function isLetterOrDigit (code) {
45846
+ return (
45847
+ (code >= 0x30 && code <= 0x39) || // 0-9
45848
+ (code >= 0x41 && code <= 0x5A) || // A-Z
45849
+ (code >= 0x61 && code <= 0x7A) // a-z
45850
+ )
45851
+ }
45852
+
45853
+ /**
45854
+ * Validates a cookie domain against the "preferred name syntax".
45855
+ *
45856
+ * <domain> ::= <subdomain> | " "
45857
+ * <subdomain> ::= <label> | <subdomain> "." <label>
45858
+ * <label> ::= <let-dig> [ [ <ldh-str> ] <let-dig> ]
45859
+ * <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
45860
+ * <let-dig-hyp> ::= <let-dig> | "-"
45861
+ *
45862
+ * @see https://www.rfc-editor.org/rfc/rfc1034#section-3.5
45863
+ * @see https://www.rfc-editor.org/rfc/rfc1123#section-2.1
45864
+ * @see https://www.rfc-editor.org/rfc/rfc1035#section-2.3.4
45601
45865
  * @param {string} domain
45602
45866
  */
45603
45867
  function validateCookieDomain (domain) {
45604
- if (
45605
- domain.startsWith('-') ||
45606
- domain.endsWith('.') ||
45607
- domain.endsWith('-')
45608
- ) {
45868
+ // <domain> ::= <subdomain> | " "
45869
+ if (domain === ' ') {
45870
+ return
45871
+ }
45872
+
45873
+ if (domain.length > 255) {
45874
+ throw new Error('Invalid cookie domain')
45875
+ }
45876
+
45877
+ let labelLength = 0
45878
+
45879
+ for (let i = 0; i < domain.length; ++i) {
45880
+ const code = domain.charCodeAt(i)
45881
+
45882
+ if (code === 0x2E) {
45883
+ if (labelLength === 0) {
45884
+ throw new Error('Invalid cookie domain')
45885
+ }
45886
+
45887
+ if (domain.charCodeAt(i - 1) === 0x2D) { // "-"
45888
+ throw new Error('Invalid cookie domain')
45889
+ }
45890
+
45891
+ labelLength = 0
45892
+ continue
45893
+ }
45894
+
45895
+ if (labelLength === 0 && !isLetterOrDigit(code)) {
45896
+ throw new Error('Invalid cookie domain')
45897
+ }
45898
+
45899
+ if (!isLetterOrDigit(code) && code !== 0x2D) { // "-"
45900
+ throw new Error('Invalid cookie domain')
45901
+ }
45902
+
45903
+ if (++labelLength > 63) {
45904
+ throw new Error('Invalid cookie domain')
45905
+ }
45906
+ }
45907
+
45908
+ if (labelLength === 0 || domain.charCodeAt(domain.length - 1) === 0x2D) { // "-"
45609
45909
  throw new Error('Invalid cookie domain')
45610
45910
  }
45611
45911
  }
@@ -45748,7 +46048,13 @@ function stringify (cookie) {
45748
46048
 
45749
46049
  const [key, ...value] = part.split('=')
45750
46050
 
45751
- out.push(`${key.trim()}=${value.join('=')}`)
46051
+ const trimmedKey = key.trim()
46052
+ const joinedValue = value.join('=')
46053
+
46054
+ validateCookieName(trimmedKey)
46055
+ validateCookieValue(joinedValue)
46056
+
46057
+ out.push(`${trimmedKey}=${joinedValue}`)
45752
46058
  }
45753
46059
 
45754
46060
  return out.join('; ')
@@ -101749,6 +102055,9 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.
101749
102055
  /******/ }
101750
102056
  /******/
101751
102057
  /************************************************************************/
102058
+ /******/ /* webpack/runtime/asset-relocator-loader */
102059
+ /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
102060
+ /******/
101752
102061
  /******/ /* webpack/runtime/define property getters */
101753
102062
  /******/ (() => {
101754
102063
  /******/ // define getter functions for harmony exports
@@ -101777,10 +102086,6 @@ module.exports = /*#__PURE__*/JSON.parse('{"name":"@actions/cache","version":"5.
101777
102086
  /******/ };
101778
102087
  /******/ })();
101779
102088
  /******/
101780
- /******/ /* webpack/runtime/compat */
101781
- /******/
101782
- /******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
101783
- /******/
101784
102089
  /************************************************************************/
101785
102090
  var __webpack_exports__ = {};
101786
102091
  // @ts-check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cypress/github-action",
3
- "version": "7.4.1",
3
+ "version": "7.4.3",
4
4
  "description": "GitHub Action for running Cypress end-to-end and component tests",
5
5
  "private": false,
6
6
  "main": "dist/index.js",
@@ -55,14 +55,14 @@
55
55
  "devDependencies": {
56
56
  "@eslint/js": "10.0.1",
57
57
  "@stylistic/eslint-plugin": "5.10.0",
58
- "@types/node": "25.4.0",
59
- "@vercel/ncc": "0.44.0",
60
- "eslint": "10.4.0",
61
- "eslint-plugin-cypress": "6.4.1",
62
- "globals": "17.6.0",
58
+ "@types/node": "25.9.4",
59
+ "@vercel/ncc": "0.45.0",
60
+ "eslint": "10.8.0",
61
+ "eslint-plugin-cypress": "6.4.3",
62
+ "globals": "17.9.0",
63
63
  "husky": "9.1.7",
64
- "markdown-link-check": "3.14.2",
65
- "prettier": "3.8.4"
64
+ "markdown-link-check": "3.15.0",
65
+ "prettier": "3.9.6"
66
66
  },
67
67
  "publishConfig": {
68
68
  "access": "public"