From e7362c67f0778a77de18117159daa2a329535349 Mon Sep 17 00:00:00 2001 From: dprevost-perso-macos Date: Sun, 25 Oct 2026 13:15:26 -0400 Subject: [PATCH] fix: require Node.js 22.23.4, 24.22.1 or 26.12.1 for the eMudhra intermediate CA compromise --- .agents/resume | 7 ++++--- .agents/setup | 7 ++++--- .agents/skills/driver-release/SKILL.md | 2 +- .agents/skills/verify-driver/SKILL.md | 2 +- .github/workflows/audit.yml | 2 ++ .github/workflows/ci.yml | 6 ++++-- .github/workflows/release.yml | 2 ++ AGENTS.md | 8 ++++---- README.md | 4 ++-- package.json | 2 +- packages/node-edgedriver/README.md | 2 +- packages/node-edgedriver/package.json | 2 +- packages/node-geckodriver/README.md | 2 +- packages/node-geckodriver/package.json | 2 +- packages/node-safaridriver/README.md | 2 +- packages/node-safaridriver/package.json | 2 +- 16 files changed, 31 insertions(+), 23 deletions(-) diff --git a/.agents/resume b/.agents/resume index 5737416..176456e 100755 --- a/.agents/resume +++ b/.agents/resume @@ -12,9 +12,10 @@ fi EXPECTED_NODE="$(tr -d 'v[:space:]' < .nvmrc)" ACTUAL_NODE="$(node -p "process.versions.node")" -MIN_NODE="$(node -p "require('./package.json').engines.node.replace(/^>=\\s*/, '')")" -if ! node -e "const p = (v) => v.split('.').map(Number); const a = p(process.versions.node); const b = p(process.argv[1]); process.exit((a[0] - b[0] || a[1] - b[1] || a[2] - b[2]) < 0 ? 1 : 0)" "$MIN_NODE"; then - echo "Node $ACTUAL_NODE is too old (package.json#engines: >=$MIN_NODE). Run .agents/setup" >&2 +ENGINES="$(node -p "require('./package.json').engines.node")" +# engines is a list of ">=x.y.z { const b = c.match(/>=\\s*([\\d.]+)/)[1].split('.').map(Number); const max = c.match(/<\\s*(\\d+)/); return (v[0] - b[0] || v[1] - b[1] || v[2] - b[2]) >= 0 && (!max || v[0] < Number(max[1])) }) ? 0 : 1)" "$ENGINES"; then + echo "Node $ACTUAL_NODE is not supported (package.json#engines: $ENGINES). Run .agents/setup" >&2 exit 1 fi if [[ "${ACTUAL_NODE%%.*}" != "${EXPECTED_NODE%%.*}" ]]; then diff --git a/.agents/setup b/.agents/setup index b92726e..ff78b3a 100755 --- a/.agents/setup +++ b/.agents/setup @@ -12,9 +12,10 @@ fi EXPECTED_NODE="$(tr -d 'v[:space:]' < .nvmrc)" ACTUAL_NODE="$(node -p "process.versions.node")" -MIN_NODE="$(node -p "require('./package.json').engines.node.replace(/^>=\\s*/, '')")" -if ! node -e "const p = (v) => v.split('.').map(Number); const a = p(process.versions.node); const b = p(process.argv[1]); process.exit((a[0] - b[0] || a[1] - b[1] || a[2] - b[2]) < 0 ? 1 : 0)" "$MIN_NODE"; then - echo "Node $ACTUAL_NODE is too old. Install Node $EXPECTED_NODE (see .nvmrc) or at least Node $MIN_NODE (package.json#engines)." >&2 +ENGINES="$(node -p "require('./package.json').engines.node")" +# engines is a list of ">=x.y.z { const b = c.match(/>=\\s*([\\d.]+)/)[1].split('.').map(Number); const max = c.match(/<\\s*(\\d+)/); return (v[0] - b[0] || v[1] - b[1] || v[2] - b[2]) >= 0 && (!max || v[0] < Number(max[1])) }) ? 0 : 1)" "$ENGINES"; then + echo "Node $ACTUAL_NODE is not supported. Install Node $EXPECTED_NODE (see .nvmrc) or a version in package.json#engines ($ENGINES)." >&2 exit 1 fi if [[ "${ACTUAL_NODE%%.*}" != "${EXPECTED_NODE%%.*}" ]]; then diff --git a/.agents/skills/driver-release/SKILL.md b/.agents/skills/driver-release/SKILL.md index 65afcac..89ddab5 100644 --- a/.agents/skills/driver-release/SKILL.md +++ b/.agents/skills/driver-release/SKILL.md @@ -33,7 +33,7 @@ WebdriverIO log file. ## 2. Check before the run -- `main` is green on every CI job, including the push-only Node 22.19.0 row. +- `main` is green on every CI job, including the push-only rows on the `engines` floors (22.23.4, 24.22.1, 26.12.1). - Each `package.json` version equals `npm view version`. If not, a previous run published without pushing its bump: open a recovery PR that sets each version to the npm one (the exception in AGENTS.md "Do not diff --git a/.agents/skills/verify-driver/SKILL.md b/.agents/skills/verify-driver/SKILL.md index acb8c46..5038ca0 100644 --- a/.agents/skills/verify-driver/SKILL.md +++ b/.agents/skills/verify-driver/SKILL.md @@ -37,7 +37,7 @@ Drive every row the change can reach. | What WebdriverIO does with the driver (`wdio:*Options`, logging) | The e2e tests that call `remote()`, and `tests/logger.e2e.test.ts` | A `remote()` against a driver you started yourself, when the change is in the path `@wdio/utils` starts | | `exports`, `types`, the CJS entry, `files` / `.npmignore`, `LICENSE` | In the package dir: `pnpm run check:pack` (the file list, the source map references, publint and attw), and the CJS interop test in `pnpm --filter test` | A green build | | A type or export that `@wdio/utils` imports | A webdriverio worktree with `overrides` in its `pnpm-workspace.yaml` on the packed tarballs. There: `pnpm run compile && pnpm run compile:all:core && pnpm -r --filter=@wdio/compiler run build -p @wdio/utils`, then `npx tsc -p packages/wdio-utils/tsconfig.json --noEmit` and `npx vitest --config vitest.config.ts --run packages/wdio-utils` | Type-checking this repo only | -| `engines`, a dependency major, the TS target | `pnpm test` and the e2e file again under Node 22.19.0 (the floor): put `dirname "$(npx -y node@22.19.0 -p process.execPath)"` first on `PATH` | A run on `.nvmrc` (24) only | +| `engines`, a dependency major, the TS target | `pnpm test` and the e2e file again under the lowest floor, Node 22.23.4: put `dirname "$(npx -y node@22.23.4 -p process.execPath)"` first on `PATH` | A run on `.nvmrc` (24) only | `attw` reports `FalseExportDefault` for `safaridriver`: `require()` of the ESM build returns the namespace, which has `default`. A strict `node16` `.cts` diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml index 2eb9a38..839ba04 100644 --- a/.github/workflows/audit.yml +++ b/.github/workflows/audit.yml @@ -26,6 +26,8 @@ jobs: uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version-file: .nvmrc + # the runner cache can hold a 24.x below the engines floor + check-latest: true cache: 'pnpm' - name: pnpm install diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0bdd1a..ba83225 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,8 +19,8 @@ jobs: fail-fast: false matrix: os: [macos-latest, ubuntu-latest, windows-latest] - # full matrix on push, including the engines floor; PRs test Node 24 only, for fast feedback - node: ${{ github.event_name == 'pull_request' && fromJson('[24]') || fromJson('["22.19.0", 22, 24, 26]') }} + # push runs the engines floor of each line; PRs test the latest Node 24 only, for fast feedback + node: ${{ github.event_name == 'pull_request' && fromJson('[24]') || fromJson('["22.23.4", "24.22.1", "26.12.1"]') }} runs-on: ${{ matrix.os }} steps: - name: Set git to use LF @@ -36,6 +36,8 @@ jobs: uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version: ${{ matrix.node }} + # the runner cache can hold a 24.x below the engines floor + check-latest: true cache: 'pnpm' - name: 🚧 Install Dependencies diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 195d27d..bbad91a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -166,6 +166,8 @@ jobs: - uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 with: node-version-file: .nvmrc + # the runner cache can hold a 24.x below the engines floor + check-latest: true registry-url: https://registry.npmjs.org cache: 'pnpm' - name: Upgrade npm for OIDC trusted publishing diff --git a/AGENTS.md b/AGENTS.md index 5dbd0ee..e7e5326 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -72,10 +72,10 @@ either with `--no-verify`. ## CI [ci.yml](.github/workflows/ci.yml) runs lint, unit and e2e on macOS, Linux and -Windows. Pull requests run Node 24 only; the required checks are -`build (, 24)` and EasyCLA. A push to `main` also runs Node 22.19.0 (the -`engines` floor), 22 and 26, so a floor break shows up only after the merge: -check that run. +Windows. Pull requests run the latest Node 24 only; the required checks are +`build (, 24)` and EasyCLA. A push to `main` runs the `engines` floor of +each line instead (22.23.4, 24.22.1, 26.12.1), so a floor break shows up only +after the merge: check that run. ## Releases diff --git a/README.md b/README.md index 6cfa017..80a7392 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,14 @@ WebdriverIO installs the driver packages it needs through `@wdio/utils`. If you | WebdriverIO | `geckodriver` | `edgedriver` | `safaridriver` | Node.js | `@wdio/logger` | | --- | --- | --- | --- | --- | --- | -| 10 | 8.x | 8.x | 3.x | 22.19.0 or newer | 10, peer dependency | +| 10 | 8.x | 8.x | 3.x | 22.23.4, 24.22.1, 26.12.1 or a later release of these lines | 10, peer dependency | | 9 | 6.x or 7.x | 6.x or 7.x | 1.x or 2.x | 20 or newer (`safaridriver`: 18) | 9, dependency | From geckodriver 8 and edgedriver 8, `@wdio/logger` is a peer dependency, so the drivers use the logger of your WebdriverIO install. A second copy of the logger empties the WebdriverIO log file (`outputDir`). ### Upgrading to geckodriver 8, edgedriver 8 and safaridriver 3 -- Use Node.js 22.19.0 or newer. +- Use Node.js 22.23.4, 24.22.1, 26.12.1 or a later release of these lines. - If you use `geckodriver` or `edgedriver` without WebdriverIO and install with Yarn, add `@wdio/logger` to your dependencies. npm and pnpm install it for you. - `geckodriver` no longer reads `GECKODRIVER_FILEPATH`. Use `GECKODRIVER_PATH`. - `require()` now returns every export of the package, for example `findEdgePath` from `edgedriver`, with CommonJS types. diff --git a/package.json b/package.json index e185f8d..7babfc0 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "homepage": "https://webdriver.io", "license": "MIT", "engines": { - "node": ">=22.19.0" + "node": ">=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1" }, "packageManager": "pnpm@12.5.1+sha512.e3f305bc784a2bc89f5ad3b6138889470fae8d2af5f36b61216ec91c2c3d64089775f9de38aac331044ea40f245cb0d5666392dfdf65824e1907ef6a2c62de5f", "scripts": { diff --git a/packages/node-edgedriver/README.md b/packages/node-edgedriver/README.md index f1087bb..0d12f38 100644 --- a/packages/node-edgedriver/README.md +++ b/packages/node-edgedriver/README.md @@ -3,7 +3,7 @@ EdgeDriver [![CI](https://github.com/webdriverio/driver/actions/workflows/ci.yml An NPM wrapper for Microsoft's [EdgeDriver](https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/). It manages to download various (or the latest) Edgedriver versions and provides a programmatic interface to start and stop it within Node.js. __Note:__ this is a wrapper module. If you discover any bugs with EdgeDriver, please report them in the [official repository](https://github.com/MicrosoftEdge/EdgeWebDriver). -__Requirements:__ Node.js 22.19.0 or newer. With Yarn and without WebdriverIO, also install `@wdio/logger`. See [Compatibility](https://github.com/webdriverio/driver#compatibility). +__Requirements:__ Node.js 22.23.4, 24.22.1, 26.12.1 or a later release of these lines. With Yarn and without WebdriverIO, also install `@wdio/logger`. See [Compatibility](https://github.com/webdriverio/driver#compatibility). # Installing diff --git a/packages/node-edgedriver/package.json b/packages/node-edgedriver/package.json index 151a281..3c9cfac 100644 --- a/packages/node-edgedriver/package.json +++ b/packages/node-edgedriver/package.json @@ -20,7 +20,7 @@ "directory": "packages/node-edgedriver" }, "engines": { - "node": ">=22.19.0" + "node": ">=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1" }, "type": "module", "types": "./dist/cjs/index.d.ts", diff --git a/packages/node-geckodriver/README.md b/packages/node-geckodriver/README.md index 8b9b740..ca39619 100644 --- a/packages/node-geckodriver/README.md +++ b/packages/node-geckodriver/README.md @@ -3,7 +3,7 @@ Geckodriver [![CI](https://github.com/webdriverio/driver/actions/workflows/ci.ym An npm wrapper for Mozilla's [Geckodriver](https://github.com/mozilla/geckodriver). It manages to download various (or the latest) Geckodriver versions and provides a programmatic interface to start and stop it within Node.js. __Note:__ this is a wrapper module. If you discover any bugs with Geckodriver, please report them in the [official repository](https://github.com/mozilla/geckodriver). -__Requirements:__ Node.js 22.19.0 or newer. With Yarn and without WebdriverIO, also install `@wdio/logger`. See [Compatibility](https://github.com/webdriverio/driver#compatibility). +__Requirements:__ Node.js 22.23.4, 24.22.1, 26.12.1 or a later release of these lines. With Yarn and without WebdriverIO, also install `@wdio/logger`. See [Compatibility](https://github.com/webdriverio/driver#compatibility). # Installing diff --git a/packages/node-geckodriver/package.json b/packages/node-geckodriver/package.json index fc28a51..dd608ac 100644 --- a/packages/node-geckodriver/package.json +++ b/packages/node-geckodriver/package.json @@ -17,7 +17,7 @@ } ], "engines": { - "node": ">=22.19.0" + "node": ">=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1" }, "keywords": [ "geckodriver", diff --git a/packages/node-safaridriver/README.md b/packages/node-safaridriver/README.md index 70296ba..8bb8d12 100644 --- a/packages/node-safaridriver/README.md +++ b/packages/node-safaridriver/README.md @@ -4,7 +4,7 @@ The Safaridriver utility is used to launch an HTTP server that implements the [WebDriver](https://w3c.github.io/webdriver/) REST API. When launched, Safaridriver allows for automated testing of web content using the version of Safari that is installed with macOS. -__Requirements:__ Node.js 22.19.0 or newer. See [Compatibility](https://github.com/webdriverio/driver#compatibility). +__Requirements:__ Node.js 22.23.4, 24.22.1, 26.12.1 or a later release of these lines. See [Compatibility](https://github.com/webdriverio/driver#compatibility). ## Install diff --git a/packages/node-safaridriver/package.json b/packages/node-safaridriver/package.json index d67a2db..3410ee6 100644 --- a/packages/node-safaridriver/package.json +++ b/packages/node-safaridriver/package.json @@ -21,7 +21,7 @@ "url": "https://github.com/webdriverio/driver/issues" }, "engines": { - "node": ">=22.19.0" + "node": ">=22.23.4 <23 || >=24.22.1 <25 || >=26.12.1" }, "main": "./dist/cjs/index.js", "type": "module",