Skip to content

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

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.

Read docs/v2.0.0-breaking-changes.md before upgrading. In short:

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.

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.

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.

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.

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%.

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 by tests/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, both FROM lines digest-pinned.
  • One .trivyignore entry (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.yml scoping turned out not to be expressiblequery-filters match query metadata and cannot be scoped to a path — and the file was removed rather than shipped describing a scope it did not have.
  • 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 hono alerts).
  • 13 open Dependabot PRs consolidated into one reviewable change; 12 GitHub Actions bumped.
  • .github/dependabot.yml added — 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) and jq-web (upstream pins ^0.5.1).

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.
LICENSE GPL-3.0-or-later
LICENSE.Apache-2.0 upstream's grant, preserved
NOTICE, THIRD-PARTY-NOTICES.md attribution
docs/adr/0001-relicense-to-gpl-3-0-or-later.md
docs/guides/http-transport.md
docs/security/2026-08-30-saferegex-reverted-by-upstream-sync.md
docs/security/2026-08-31-open-alert-sweep.md
patches/fork/*.patch fork changes to upstream-owned files
src/node/lib/*.mjs decomposed subsystems
tests/mcp/http-transport-sessions.test.mjs 32 tests, real sockets
tests/mcp/cve-regressions.test.mjs
.trivyignore, .github/dependabot.yml
Terminal window
docker pull ghcr.io/doublegate/cyberchef-mcp_v2:latest

The 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.

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
npm run lint 0 errors
npm run test:mcp 757 passed (22 files)
npm test 241 Node-API + 2,289 operation tests
npm run testnodeconsumer green
actionlint 0 findings across 11 workflows
docker build ok; tools/list 524 tools; uid=65532(node)