Add Node 26 support alongside Node 24 (#2397)

- Widen engines range to >=24 <27
- Test against Node 24 and 26 in CI (build/deploy artefacts remain on 24)
- Replace unmaintained 'cbor' dependency with 'cbor2': the cbor package's
  synchronous encode relies on a single stream read() returning the whole
  encoding, which breaks on Node 26 where readable streams return one
  buffer at a time
- Remove stale dependabot ignore for the removed cbor package
- Update Node.js support notes in README and AGENTS
This commit is contained in:
Allan Leary 2026-07-28 14:20:53 +01:00
parent c56dd23358
commit e0fcb7412f
9 changed files with 42 additions and 31 deletions

View File

@ -29,8 +29,6 @@ updates:
versions: [ '>=0.9.0' ]
- dependency-name: 'bootstrap'
versions: [ '>=5.0.0' ]
- dependency-name: 'cbor'
versions: [ '>=10.0.0' ]
- dependency-name: 'eslint'
versions: [ '>=10.0.0' ]
- dependency-name: 'eslint-plugin-jsdoc'

View File

@ -15,13 +15,19 @@ jobs:
contents: write
pages: write
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Node 24 is the officially supported version; Node 26 is tested
# ahead of it becoming the active LTS release (see #2397)
node-version: [24, 26]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
node-version: ${{ matrix.node-version }}
registry-url: "https://registry.npmjs.org"
- name: Install
@ -59,11 +65,11 @@ jobs:
xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui
- name: Prepare for GitHub Pages
if: success()
if: success() && matrix.node-version == 24
run: npx grunt copy:ghPages
- name: Deploy to GitHub Pages
if: success() && github.ref == 'refs/heads/master'
if: success() && github.ref == 'refs/heads/master' && matrix.node-version == 24
uses: crazy-max/ghaction-github-pages@1d6ee9b181a81033a16bd707a1401afa978daab4 # v5.0.0
with:
target_branch: gh-pages

View File

@ -11,13 +11,19 @@ on:
jobs:
main:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Node 24 is the officially supported version; Node 26 is tested
# ahead of it becoming the active LTS release (see #2397)
node-version: [24, 26]
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set node version
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24
node-version: ${{ matrix.node-version }}
registry-url: "https://registry.npmjs.org"
- name: Install
@ -38,7 +44,7 @@ jobs:
run: npx grunt prod
- name: Upload Build Artefact
if: success()
if: success() && matrix.node-version == 24
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: zipped-build

View File

@ -13,7 +13,7 @@ Core principles for changes:
## Commands
CyberChef expects Node.js `>=24 <25`.
CyberChef expects Node.js `>=24 <27` (v24 is the officially supported version; v26 is also tested).
- Install: `npm install`
- Development server: `npm start`

View File

@ -117,7 +117,7 @@ CyberChef is built to support
## Node.js support
CyberChef is built to fully support Node.js `v24`. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
CyberChef is built to fully support Node.js `v24` and is also tested against Node.js `v26` ahead of it becoming the active LTS release. For more information, see the ["Node API" wiki page](https://github.com/gchq/CyberChef/wiki/Node-API)
## Security

32
package-lock.json generated
View File

@ -29,7 +29,7 @@
"browserify-zlib": "^0.2.0",
"bson": "^7.3.1",
"buffer": "^6.0.3",
"cbor": "10.0.12",
"cbor2": "2.3.0",
"chi-squared": "^1.1.0",
"codepage": "^1.15.0",
"crypto-api": "^0.8.5",
@ -165,7 +165,7 @@
"worker-loader": "^3.0.8"
},
"engines": {
"node": ">=24 <25"
"node": ">=24 <27"
}
},
"node_modules/@alexaltea/capstone-js": {
@ -2665,6 +2665,15 @@
"node": ">=18"
}
},
"node_modules/@cto.af/wtf8": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/@cto.af/wtf8/-/wtf8-0.0.5.tgz",
"integrity": "sha512-LfUFi+Vv4eDzj+XAtR89e3wwjXA/NZjUSwU5NhwbBrLecxPaBYFy3exCuc1j+D4UZeOVdqlsl8G7LmOt18V0tg==",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/@discoveryjs/json-ext": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz",
@ -6611,13 +6620,13 @@
],
"license": "CC-BY-4.0"
},
"node_modules/cbor": {
"version": "10.0.12",
"resolved": "https://registry.npmjs.org/cbor/-/cbor-10.0.12.tgz",
"integrity": "sha512-exQDevYd7ZQLP4moMQcZkKCVZsXLAtUSflObr3xTh4xzFIv/xBCdvCd6L259kQOUP2kcTC0jvC6PpZIf/WmRXA==",
"node_modules/cbor2": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/cbor2/-/cbor2-2.3.0.tgz",
"integrity": "sha512-76WB3hq8BoaGkMkBVJ27fW5LJU+qqDLEpgRNCG/SYKhODWXpVPOTD4UcUto3IEzYLA52nsvbhb0wabhHDn3qXg==",
"license": "MIT",
"dependencies": {
"nofilter": "^3.0.2"
"@cto.af/wtf8": "0.0.5"
},
"engines": {
"node": ">=20"
@ -14048,15 +14057,6 @@
"integrity": "sha512-qhfYgpoCSi37HLiViMlf94YqMQdvk3n3arI1uGbAWZK9NKCYRSI42W8lATeGloYGLYxb8us1C5rTvtsXjwdWQg==",
"license": "ISC"
},
"node_modules/nofilter": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz",
"integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==",
"license": "MIT",
"engines": {
"node": ">=12.19"
}
},
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",

View File

@ -113,7 +113,7 @@
"browserify-zlib": "^0.2.0",
"bson": "^7.3.1",
"buffer": "^6.0.3",
"cbor": "10.0.12",
"cbor2": "2.3.0",
"chi-squared": "^1.1.0",
"codepage": "^1.15.0",
"crypto-api": "^0.8.5",
@ -220,6 +220,6 @@
"setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048"
},
"engines": {
"node": ">=24 <25"
"node": ">=24 <27"
}
}

View File

@ -5,7 +5,7 @@
*/
import Operation from "../Operation.mjs";
import Cbor from "cbor";
import { decode } from "cbor2";
/**
* CBOR Decode operation
@ -33,7 +33,7 @@ class CBORDecode extends Operation {
* @returns {JSON}
*/
run(input, args) {
return Cbor.decodeFirstSync(Buffer.from(input).toString("hex"));
return decode(new Uint8Array(input));
}
}

View File

@ -5,7 +5,8 @@
*/
import Operation from "../Operation.mjs";
import Cbor from "cbor";
import { encode } from "cbor2";
import { sortCoreDeterministic } from "cbor2/sorts";
/**
* CBOR Encode operation
@ -33,7 +34,7 @@ class CBOREncode extends Operation {
* @returns {ArrayBuffer}
*/
run(input, args) {
return new Uint8Array(Cbor.encodeCanonical(input)).buffer;
return new Uint8Array(encode(input, {sortKeys: sortCoreDeterministic})).buffer;
}
}