Aditya's Blog

🚨 n8n Expression Injection RCE CVE-2025-68613

What is n8n?

Avatar

n8n is a visual workflow automation platform that connects different apps, services, and AI models so they can talk to each other. It acts as a digital assistant to automate boring, repetitive tasks without requiring you to write everything from scratch.

Versions 0.211.0 through 1.120.3 contain a critical Remote Code Execution (RCE) vulnerability within the workflow expression evaluation system. If exploited, this flaw enables an authenticated attacker to execute system-level commands, potentially leading to data breaches, service disruptions, or full system compromise, all with the privileges assigned to the n8n process.

How does n8n work exactly?

It is built on Node.js, using JavaScript for platform internals and user workflow logic. Its architecture includes:

Weakness in the Express Evaluation System

The vulnerability exists in the Express Evaluation system that n8n uses. Any authenticated user had the ability to execute expressions during workflow configuration in an insecure execution environment.

Expression Injection vulnerability is the core flaw here in the n8n system where authenticated users could execute arbitrary javascript code under the privileges of an official n8n process.

In short,

The Exploit

Let us consider a payload by wioui

function () {
    return this.process.mainModule.require('child_process')
    .execSync('id').toString()
}

The payload uses a function in which a return is executed. Within the evaluation context, n8n will try to execute the function starting with whatever is written within the return statement.

In our case, its the this global object. Let us dissect the above payload so it becomes easier to understand what is exactly happening ,

this.process.mainModule

This code tries to bypass regular javascript sandbox restriction by accessing Node.js application internals (root modules). This is typically not allowed to executed under regular user expressions.

require('child_process')

.execSync('pwd').toString()

Steps to perform the Exploit

Let us now perform this exploit using tryHackMe’s virtual attacker and target VM’s.

We’ll log into n8n on the attacker machine using the target machines ip address (Technically any authenticated user can perform this on any device)

After logging in, we see the n8n workflow space and area. Click on the ‘Add first step..’ to add a trigger.

Now search for ‘Manual Trigger’. This trigger will allow us to manually set the field.

Now click on the ‘+’ sign as shown in the image above. Search for ‘Edit fields (Set)’ to allow us to edits fields as needed.

Now make sure, the mode is set to ‘Manual Mapping. Now this is where the actual exploit takes place. Click on ‘Add Field’ and name it anything you want. Here I have named it ‘Exploit’ and in the value field just below, paste the payload from wioui as seen above.

Now before clicking on ‘Execute Step’, make sure inside the execSync() function, you’ve typed in a system command you’d like to run. In my case, I’ve left is as id. Finally click on ‘Execute Step’

That is it. That is all it takes to successfully perform the exploit. As soon as it executes the step, we can see that our system command (id and pwd) has been executed successfully.

How to detect the Expression Injection Remote Code Execution

Let us discuss on we can configure a SIEM to detect Expression Injection Remote Code Execution (CVE-2025-68613)

1. nginx log method

Below you can see a sample configuration for nginx to log body content with 'Request-Body: "$request_body" '.

http {
    # Load Lua module
    lua_package_path "/etc/nginx/lua/?.lua;;";

    # Custom log format
    log_format detailed '$remote_addr - $remote_user [$time_local] '
                       '"$request" $status $body_bytes_sent '
                       '"$http_referer" "$http_user_agent" '
                       'Request-Body: "$request_body" '
                       'Content-Type: "$http_content_type" '
                       'Duration: $request_time s';

    # ... rest of http block ...

The key idea is that the malicious payload is usually delivered in the HTTP request body. Logging the request body gives defenders visibility into what was actually submitted to the application, making it much easier to detect attempted exploitation

Normally, nginx access logs record things like:

They do not include the POST body by default. With this configuration, a request like the one below would have the JSON payload written into the access log.

POST /rest/workflows HTTP/1.1
Content-Type: application/json

{
  "name":"test",
  "nodes":[...]
}

Vulnerable versions of n8n allowed workflow definitions using JSON. An attacker could perform expression injection RCE using JSON as workflow definition.

{
  "parameters": {
    "value": "={{ malicious_expression }}"
  }
}

Via the the custom nginx log rule, we can detect such RCE attempts and identify the payload right at the beginning using a proxy.

2. Sigma Rule

💡 What is a Sigma Rule?
→ Sigma Rules are YAML-written textual signatures designed to identify suspicious activity potentially related to cyber threat anomalies in log events. One of the main advantages of these rules is their standardized format that permits writing the rule once and applying it across various SIEM products without needing to rewrite the rule.

The main focus of Sigma rules is to detect log events matching criteria established by the SoC engineer. This is especially useful for creating Incident Response detection or automated responses.

Below is sigma rule provided by the TryHackMe content engineering team,

title: N8N Workflow RCE Attempt
status: experimental
description: Detects attempts to inject JavaScript expressions into n8n workflow
payloads that execute OS commands via 
"this.process.mainModule.require('child_process').execSync(...)""
author: TryHackMe Content Engineering Team
references:
  - <https://github.com/wioui/n8n-CVE-2025-68613-exploit>
date: 2025-12-23
tags:
  - attack.execution
  - attack.t1059.007
logsource:
  category: webserver
  product: generic
detection:
  selection:
    cs-method: POST
    cs-uri-stem|endswith: /rest/workflows

  keywords:
    # Strong indicators of this n8n expression injection RCE
    - "this.process.mainModule.require('child_process')"
    - ".execSync("
    - "={{ (function(){"
    - "toString() })()"

  condition: selection and all of keywords
falsepositives:
  - Security testing / red team simulations
  - Developers storing these exact strings in logged fields
level: high

In summary, this Sigma rule does:

It also important to make sure monitoring takes place after the attacker performs the exploitation.

This is critical, since an attacker who only has a valid n8n credentials can fully abuse this RCE to carry out a wide range of malicious actions, such as:

Conclusion

Today we talked about CVE-2025-68613 (n8n Expression Injection RCE) and discussed how a simple payload can exploit the application design flaws in n8n. It highlights the importance of not just input validation but making sure user inputed code stays within the intended application runtime and sandbox environment.

Sources

Payload Script by wioui
VM's and nginx / sigma rule scripts by TryHackMe Content Engineering Team

#RCE #cybersecurity #n8n #vulnerability research