Feb 26, 2026·7 min read·162 visits
A critical RCE in n8n's Merge node allows authenticated users to execute arbitrary code via malicious SQL queries. The flaw stems from the AlaSQL engine escaping the sandbox.
n8n, the popular workflow automation tool that connects everything to everything, recently discovered it had connected its internal server shell to authenticated users. CVE-2026-27497 is a critical RCE vulnerability residing in the Merge node's SQL mode. By leveraging the AlaSQL engine—a library that brings the chaos of SQL to the flexibility of JavaScript—attackers could bypass n8n's sandbox and execute arbitrary code or write files to the underlying server. It’s a classic case of 'feature creep' turning into 'security breach,' allowing anyone with workflow permissions to turn the automation server into their personal playground.
In the world of low-code automation, n8n is the heavy lifter. It’s the glue that holds together your Slack, AWS, and database infrastructure. But as any engineer knows, the more powerful the tool, the sharper the edges. Enter the Merge Node. Its job is simple: take data from Input A, data from Input B, and mash them together. To make this even more 'flexible,' the developers introduced SQL Mode, powered by a library called AlaSQL.
AlaSQL is an open-source SQL database for JavaScript. It’s incredibly cool—it lets you run full SQL queries on JSON objects in memory. However, AlaSQL is also notoriously permissive. It treats JavaScript functions as first-class citizens within SQL queries. Do you see where this is going? n8n essentially wrapped a feature that says 'Run this SQL' around an engine that says 'Sure, I can also run this JavaScript code and write these files to disk while I'm at it.'
For a hacker, this is the holy grail. We aren't just looking for a SQL Injection to dump a database table; we are looking for a way to break out of the data plane and into the control plane. By exposing AlaSQL directly to user input, n8n didn't just open a window; they installed a doggy door for attackers to crawl through and start executing shell commands on the host server.
The root cause of CVE-2026-27497 isn't a simple buffer overflow; it's a logic flaw in trust boundaries. n8n implements a sandbox to prevent user-defined expressions from wrecking the server. They know that users will write JavaScript in their workflows, so they try to contain it. However, the implementation of the SQL Merge mode failed to realize just how 'meta' AlaSQL is. The engine supports syntax that allows for the definition and execution of JavaScript functions inside the SQL query string, effectively bypassing the initial layer of expression sandboxing.
The vulnerability, flagged as CWE-94 (Code Injection) and CWE-89 (SQL Injection), arises because the input validation sanitizing the SQL query didn't account for AlaSQL's advanced features. Specifically, AlaSQL allows for SELECT ... INTO syntax which can write files, and it allows for user-defined functions (UDFs) that execute in the context of the application.
Think of it like this: n8n built a prison cell (the sandbox) and put the prisoner (the user input) inside. But then they gave the prisoner a magic wand (AlaSQL) that can conjure keys. The sandbox checks if the prisoner is trying to pick the lock, but it doesn't check if the prisoner is casting a spell to teleport out. The failure here was assuming that the SQL engine would behave like a strict database, rather than a dynamic JavaScript interpreter.
The remediation for this vulnerability was not a one-line fix. It required a scorched-earth approach to the JavaScript execution environment. Analyzing the git history, specifically commits 49d7e160287556e65d7daf754bd155095b7738d5 and e9e2456708c8025151e5a9f3096f589a87be241f, we see a massive overhaul in packages/workflow/src/expression-sandboxing.ts.
The developers had to implement what is essentially a 'global freeze.' In previous versions, the sandbox context might have looked something like this (simplified):
// Vulnerable Context Setup
const context = vm.createContext({
require: () => { throw new Error('No require allowed') },
// ... other mocks
});
vm.runInContext(userCode, context);The problem is that complex objects passed into the context often retain references to their constructors. If you have access to {} (an object), you have access to Object, and from there Object.constructor, and eventually you might find a way to Function constructor to compile new code.
The fix involved over 200 lines of code dedicated to locking down these prototypes. They implemented a deep freeze on global objects within the execution realm. Furthermore, in packages/nodes-base/nodes/Merge/v3/actions/mode/combineBySql.ts, they explicitly blacklisted dangerous AlaSQL keywords. The patch essentially says: 'If the query contains INTO, ATTACH, Use, or Load, kill it with fire.'
So, how do we weaponize this? We need an authenticated user account, but in many organizations, n8n access is shared or loosely guarded. Once in, we create a new Workflow, drag in a Merge Node, and switch the mode to SQL Query.
In a standard SQL injection, you might try ' OR 1=1 --. Boring. Here, we are speaking AlaSQL. We can define a JavaScript function directly in the query and execute it. The goal is to escape the Node.js sandbox and access the child_process module to run system commands.
Here is a conceptual payload that demonstrates the RCE. This payload abuses the VALUE modifier in AlaSQL to evaluate a closure:
SELECT VALUE (function(){
// We are now inside a JS execution context managed by AlaSQL
// Attempt to leverage the host's process binding if not properly stripped
const process = this.constructor.constructor('return this.process')();
process.mainModule.require('child_process').exec('id > /tmp/pwned.txt');
return 'Command Executed';
})()
FROM ?If the direct child_process access is blocked, an attacker might pivot to the Arbitrary File Write vector using AlaSQL's export features:
SELECT * INTO CSV('/app/static/shell.js') FROM ?By writing a malicious JS file to a directory served by the web application, the attacker can then simply browse to https://n8n.target/static/shell.js (or trigger it via another node) to achieve execution. It is a dual-threat vector: direct memory corruption via JS or persistence via filesystem.
Why should you panic? Because n8n is the keeper of the keys. By design, n8n stores credentials for everything it automates: AWS Access Keys, Stripe API tokens, Slack Webhooks, Database connection strings, and SSH keys. It is a central repository of secrets.
Successfully exploiting CVE-2026-27497 gives an attacker Code Execution on the n8n server. This means they can:
This isn't just 'the server crashed.' This is 'we need to rotate every credential in the company and call legal.'
If you are running n8n versions < 1.123.22, 2.0.0 through 2.9.2, or 2.10.0, you are vulnerable. The fix is straightforward: Update immediately. The patched versions (1.123.22, 2.9.3, 2.10.1) introduce the necessary sandbox hardening.
If you cannot update right now (perhaps you enjoy living dangerously), you have two partial mitigations:
NODES_EXCLUDE environment variable to disable the vulnerable component entirely. Set NODES_EXCLUDE=n8n-nodes-base.merge. Note that this will break any workflow using this node, which is likely all of them.For the long term, security teams should treat low-code platforms like n8n as critical infrastructure. They are not just 'tools'; they are privileged identity providers.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H| Product | Affected Versions | Fixed Version |
|---|---|---|
n8n n8n | < 1.123.22 | 1.123.22 |
n8n n8n | >= 2.0.0, < 2.9.3 | 2.9.3 |
n8n n8n | >= 2.10.0, < 2.10.1 | 2.10.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-94 (Code Injection) |
| CVSS v4.0 | 9.4 (Critical) |
| Attack Vector | Network (Authenticated) |
| Impact | Remote Code Execution (RCE) |
| Affected Component | Merge Node (v3) - SQL Mode |
| Engine | AlaSQL |
Improper Control of Generation of Code ('Code Injection')
Netflix Lemur, a TLS/SSL certificate management framework, contains a missing authorization check in its certificate export endpoint. Prior to version 1.9.3, the validation logic verifying whether a user had permission to export a certificate was incorrectly placed inside a block that executed only if the selected plugin required a private key. When an authenticated user attempted to export a certificate using a plugin that did not require the private key, the authorization check was bypassed, allowing unauthorized access to the public portions of the certificate and producing misleading audit logs.
A critical security flaw in LibreNMS allows authenticated administrators to execute arbitrary commands by modifying the configured binary path for snmpget and accessing the About page. This occurs due to insufficient verification of the executable file's identity and integrity prior to executing it with shell_exec.
LibreNMS versions prior to 26.7.0 are vulnerable to a stored Cross-Site Scripting (XSS) vulnerability. An authenticated administrator can inject arbitrary HTML or JavaScript into graph descriptions via specific administrative configuration endpoints. When another authenticated user views the affected graph, the unescaped payload executes within their browser context.
An injection vulnerability in LibreNMS's Oxidized integration component allows administrative or network-positioned attackers to achieve stored cross-site scripting (XSS). By setting a malicious oxidized.url endpoint, the server makes outbound queries and processes returned JSON fields containing malicious HTML or JavaScript. These payloads are outputted directly in the web UI without appropriate output encoding.
CVE-2026-17106 (CopyEscape) is a container-to-host arbitrary file-write vulnerability within Docker's archiving and extraction library moby/go-archive. By utilizing a Time-of-Check to Time-of-Use (TOCTOU) race condition during the file-walking stage inside a running container, a malicious container process can force the host engine to produce a compromised tar stream. During client-side extraction, the Docker CLI resolves directory entries through absolute symbolic links, resulting in arbitrary file creation or modification on the host system.
CVE-2026-73974 is a local path traversal vulnerability in linuxfabrik-lib and Linuxfabrik Monitoring Plugins. Under standard monitoring configurations running with elevated privileges via sudo, this flaw can be exploited by an unprivileged local user to read arbitrary root-only files, resulting in local privilege escalation.