v2.0.0 release notes
Release Date: 2026-08-31
Upstream Base: CyberChef v11.4.0 (was v10.19.4)
Licence: GPL-3.0-or-later (was Apache-2.0)
Node: >=24 <27
Highlights
Section titled “Highlights”A major release that closes a six-release upstream gap, relicenses the combined work, rebuilds the sync mechanism that let the gap open, fixes the HTTP transport for multiple clients, and takes the repository from 272 open security findings to zero.
| v1.9.0 | v2.0.0 | |
|---|---|---|
| Upstream base | 10.19.4 | 11.4.0 |
| Operations | 463 | 504 |
Tools in tools/list |
483 | 524 |
| Licence | Apache-2.0 | GPL-3.0-or-later |
| Node | 22 | >=24 <27 |
| MCP tests | 689 | 757 |
| Open Dependabot alerts | 194 | 0 |
| Open code-scanning alerts | 78 | 0* |
*Corrected 2026-08-31. Both alert counts were measured on the release PR immediately before merge, and were 0 at that moment. A pull-request CodeQL run analyses the merge commit in a diff-informed mode; the push to the default branch runs a full analysis. When v2.0.0 merged, that full run surfaced 55 pre-existing findings in code this fork had been carrying all along — none introduced by v2.0.0. They are dispositioned in
docs/security/2026-08-31-code-scanning-disposition.md: 8 fixed, 47 dismissed with recorded reasons. Dependabot alerts remain at 0.The lesson worth keeping: “zero alerts” measured on a PR is not the same claim as “zero alerts on the default branch.” This table did not distinguish them.
Breaking Changes
Section titled “Breaking Changes”Read docs/v2.0.0-breaking-changes.md before upgrading. In short:
The licence changes to GPL-3.0-or-later
Section titled “The licence changes to GPL-3.0-or-later”Applies to v2.0.0 and later. Versions 1.9.x and earlier remain Apache-2.0 and are unaffected.
v2.0.0 admits algorithms from reference security tools whose licences constrain the choice: katana is GPL-3.0-or-later (which rules GPLv2 out), John the Ripper is GPL-2.0-or-later (usable under GPLv3), and upstream CyberChef is Apache-2.0 (compatible with GPLv3, not GPLv2). GPL-3.0-or-later is the only licence admitting all three.
This is not a relicensing of GCHQ’s code. Upstream files keep their Apache-2.0 headers and
copyright; only the combined work changes licence, which is exactly how Apache-2.0’s one-way
compatibility with GPLv3 operates. The previous combined notice is preserved as
LICENSE.Apache-2.0.
What it means for you: running CyberChef-MCP, including serving it over HTTP, carries no obligation — GPLv3 has no network-use clause. Distributing a derivative must also be GPLv3. If your policy precludes GPLv3, stay on the v1.9.x line, which remains Apache-2.0 through its LTS window (~March 2027). See ADR 0001.
Node 24 is the floor
Section titled “Node 24 is the floor”engines: {"node": ">=24 <27"}, matching upstream exactly. The published image runs Node 26.8.1.
Three announced changes are WITHDRAWN — the cyberchef_ prefix is permanent
Section titled “Three announced changes are WITHDRAWN — the cyberchef_ prefix is permanent”DEP001, DEP007 and DEP008 are not happening, in v2.0.0 or later. Since v1.8.0 they warned that
cyberchef_to_base64 would become to_base64 and that cyberchef_bake/cyberchef_search would be
renamed.
Measured before deciding: removing the prefix saves 1,208 of 183,115 bytes in the tools/list
payload — 2.6% of roughly 45,800 tokens — while making 19 tool names collide in MCP’s flat
per-session namespace (bake search md5 sha1 sha2 hash filter sort merge diff reverse unique fork jump label comment register subtract parse_uri) and breaking every existing integration. Nearly
every other connected MCP server plausibly defines search; the prefix is what makes exposing it
safe at all.
If you renamed tool calls in anticipation, revert them. Withdrawing breaks nobody: no code can depend on a name that has never shipped.
Bcrypt emits $2b$, not $2a$
Section titled “Bcrypt emits $2b$, not $2a$”bcryptjs 2.x → 3.x changes the revision identifier it generates. Verification is unaffected —
compare() still accepts $2a$, $2y$ and $2b$, so Bcrypt Compare and Bcrypt Parse keep
working against every previously-generated hash.
What’s New
Section titled “What’s New”Upstream v11.4.0 — 463 → 504 operations
Section titled “Upstream v11.4.0 — 463 → 504 operations”New families include XPRESS (MS-XCA), the Ascon suite (NIST SP 800-232), TEA/XTEA, PRESENT,
Twofish, COBS, Modular Exponentiation/Inverse, Extended GCD, Generate Prime, Modulo, Wrap, ROR13,
Escape Smart Characters, Remove ANSI Escape Codes and Parity Bit. argSelector arguments are
supported (19 operations use it, including AES Encrypt/Decrypt).
The sync mechanism is rebuilt, which is why the gap could close
Section titled “The sync mechanism is rebuilt, which is why the gap could close”The previous sync copied only src/core/operations/*.mjs, comparing flat basenames in one
directory. That is structurally incapable of a major-version jump: 10.19.4 → 11.4.0 also changes
src/core/lib/, the six upstream-owned src/node/*.mjs files and the config generators, and it
deletes src/core/lib/ImageManipulation.mjs. Syncing operations without lib/ orphans the
library; syncing lib/ without operations breaks the build.
It now mirrors the whole synced tree with rsync -a --delete, so additions, modifications and
deletions apply atomically. Fork changes to upstream-owned files are patches/fork/*.patch,
re-applied after the mirror — and a patch that stops applying fails the sync, which is the alarm
that was missing when a ReDoS mitigation was silently reverted and stayed gone for four releases
(incident record). Scope is checked
against an allowlist, so anything outside the declared scope fails the run rather than being caught
only if someone thought to forbid it.
Streamable HTTP serves multiple clients (closes #36)
Section titled “Streamable HTTP serves multiple clients (closes #36)”The HTTP branch created one transport for the whole process, so the first client to connect
worked and every one after it got Invalid Request: Server already initialized. Each session now
gets its own MCP Server and its own transport — the shape the SDK’s advisory
GHSA-345p-7cg4-v4c7 requires, since sharing instances between clients leaks state across them.
With it: CORS preflight handling (CYBERCHEF_ALLOWED_ORIGINS, plus
Access-Control-Expose-Headers: Mcp-Session-Id without which browser clients cannot echo their
session back), DNS-rebinding protection (CYBERCHEF_ALLOWED_HOSTS), a session cap
(CYBERCHEF_MAX_SESSIONS, closing an unauthenticated CWE-400), DELETE teardown, idle reaping,
a 4 MiB body limit, path routing, and SIGINT/SIGTERM handlers so docker stop closes sessions
rather than dropping connections. See the HTTP Transport Guide.
ReDoS screening, in a place a sync cannot revert
Section titled “ReDoS screening, in a place a sync cannot revert”src/node/lib/safe-regex.mjs screens regex-bearing arguments in resolveArgValue — the single
point every user argument passes through. Unlike its v1.4.1 predecessor it lives in the fork-owned
MCP layer, outside every sync allowlist, and ships with 26 tests including a regression guard that
fails if it is ever unwired from the dispatch path.
The old module’s “timeout-based validation (100ms)” is deliberately not reimplemented:
catastrophic backtracking blocks the event loop, so no JavaScript timer can fire while it runs. The
same applies to CYBERCHEF_OPERATION_TIMEOUT, which gives no protection against ReDoS —
screening before execution is the only thing that works single-threaded.
mcp-server.mjs decomposed
Section titled “mcp-server.mjs decomposed”1,636 → ~1,000 lines, with six classes and the schema helpers extracted into src/node/lib/*.mjs
(cache, memory, telemetry, rate-limit, quota, batch, tool-schema, config,
safe-regex). Behaviour unchanged; per-module coverage now visible, and src/node/lib/** sits at
~95%.
Security
Section titled “Security”272 open findings → 0 as measured on the release PR. See the correction under Highlights: the
full CodeQL analysis that runs on a push to master subsequently surfaced 55 further pre-existing
findings, dispositioned in
2026-08-31-code-scanning-disposition.md.
Full disposition of the findings this release closed, with the reasoning for every suppression and
dismissal: docs/security/2026-08-31-open-alert-sweep.md.
- CVE-2026-42615 (HIGH, CVSS 7.2, CWE-79) — XSS in
Show Base64 offsets, fixed by adopting upstream’s file; pinned bytests/mcp/cve-regressions.test.mjs. - minimatch 3.0.8 → 3.1.5 (3 × HIGH) via a version-selector override.
- uuid 8.3.2 (MEDIUM) cleared at the root by removing
nightwatch— the browser tests it runs have not existed since v1.7.1. - Dockerfile: explicit non-root
USER 65532:65532, bothFROMlines digest-pinned. - One
.trivyignoreentry (CVE-2025-14505, elliptic) with a written justification: no fixed version exists anywhere, and it reaches the tree only through a webpack browser polyfill whose alias is never applied on Node. - Three CodeQL alerts on upstream-identical files dismissed with reasons. The intended
codeql-config.ymlscoping turned out not to be expressible —query-filtersmatch query metadata and cannot be scoped to a path — and the file was removed rather than shipped describing a scope it did not have.
Maintenance
Section titled “Maintenance”- Babel 7 → 8, ESLint 9 → 10, jimp 0.22 → 1.6, bson 6 → 7, cbor → cbor2, ua-parser-js 1 → 2,
protobufjs 7 → 8, tesseract.js 5 → 7, pino 9 → 10, piscina 4 → 5, MCP SDK 1.26 → 1.30
(which alone cleared 33 transitive
honoalerts). - 13 open Dependabot PRs consolidated into one reviewable change; 12 GitHub Actions bumped.
.github/dependabot.ymladded — the repository previously had none, which is how 194 alerts accumulated: nothing was ever bumped for currency, only for a published CVE.- Two packages held with evidence rather than by omission:
@xmldom/xmldom(0.9 breaks two upstream-owned call sites; upstream still pins^0.8.14) andjq-web(upstream pins^0.5.1).
Environment Variables
Section titled “Environment Variables”New in v2.0.0, all HTTP-transport related:
| Variable | Default | Meaning |
|---|---|---|
CYBERCHEF_ALLOWED_ORIGINS |
(unset) | Origin allowlist; enables CORS. Required by browser clients. |
CYBERCHEF_ALLOWED_HOSTS |
(loopback names) | Host allowlist. DNS-rebinding protection is on by default; * disables it. |
CYBERCHEF_MAX_SESSIONS |
100 |
Cap on concurrent HTTP sessions. |
CYBERCHEF_SESSION_TIMEOUT |
1800000 |
Idle-session reap threshold (30 min). |
CYBERCHEF_HTTP_MAX_BODY |
4194304 |
Maximum accepted request body (4 MiB). |
CYBERCHEF_HTTP_PATH |
/mcp |
MCP endpoint path. |
CYBERCHEF_MAX_REGEX_LENGTH |
1000 |
ReDoS screen: maximum accepted pattern length. |
New Files
Section titled “New Files”LICENSE GPL-3.0-or-laterLICENSE.Apache-2.0 upstream's grant, preservedNOTICE, THIRD-PARTY-NOTICES.md attributiondocs/adr/0001-relicense-to-gpl-3-0-or-later.mddocs/guides/http-transport.mddocs/security/2026-08-30-saferegex-reverted-by-upstream-sync.mddocs/security/2026-08-31-open-alert-sweep.mdpatches/fork/*.patch fork changes to upstream-owned filessrc/node/lib/*.mjs decomposed subsystemstests/mcp/http-transport-sessions.test.mjs 32 tests, real socketstests/mcp/cve-regressions.test.mjs.trivyignore, .github/dependabot.ymlUpgrading
Section titled “Upgrading”docker pull ghcr.io/doublegate/cyberchef-mcp_v2:latestThe image name changes from cyberchef-mcp_v1 to cyberchef-mcp_v2. The _v1 images stay
pullable and receive security-only patches on the v1.9.x line until ~March 2027; they remain
Apache-2.0.
Resolution Map
Section titled “Resolution Map”| Item | Resolution |
|---|---|
| #27, #28, #30, #31, #34, #35, #37, #38, #39, #40 | Upstream trackers — satisfied by the v11.4.0 sync |
| #29, #33, #59–#71, #77 | Dependabot PRs — superseded or declined with evidence |
| #32 | Spam — closed not-planned |
| #36 | Per-session HTTP transport |
| #49 | agy reviewer follow-ups |
| #56 | Benchmark comment updates in place |
| #73 | Upstream defects — tracked for reporting to gchq/CyberChef |
| 194 Dependabot + 78 code-scanning alerts | Fixed, suppressed with justification, or dismissed with reasons |
Verification
Section titled “Verification”npm run lint 0 errorsnpm run test:mcp 757 passed (22 files)npm test 241 Node-API + 2,289 operation testsnpm run testnodeconsumer greenactionlint 0 findings across 11 workflowsdocker build ok; tools/list 524 tools; uid=65532(node)