Who this is for: Security engineers and DevOps professionals responsible for hardening n8n installations in production environments. We cover this in detail in the n8n Security & Hardening Guide.
Quick Diagnosis
Problem: A maliciously crafted n8n workflow can execute actions with the permissions of the n8n service account, giving an attacker a path to elevate privileges and access restricted resources.
Featured‑snippet solution:
- Identify any workflow that runs commands or accesses external services with elevated credentials.
- Restrict the
Execute Commandnode (and any node that can invoke external APIs) to the minimum required scope. - Enforce role‑based access control (RBAC) on workflow creation/modification.
- Audit workflow versions and enable “run as” isolation (Docker sandbox or separate process).
1. How n8n Workflows Can Become Privilege‑Escalation Vectors ?
If you encounter any database injection risks resolve them before continuing with the setup.
Micro‑summary: The following node types are the most common escalation bridges when they run with unrestricted privileges.
| Attack surface | Typical node(s) | What the node can do when unrestricted |
|---|---|---|
| Execute Command | `Execute Command` | Run arbitrary shell commands on the host OS. |
| HTTP Request | `HTTP Request` | Call internal APIs that require admin tokens. |
| Database | `Postgres`, `MySQL`, `MongoDB` | Query/modify privileged databases using stored credentials. |
| File System | `Write Binary File`, `Read Binary File` | Read or overwrite config files (e.g., /etc/passwd). |
| Scripting | `Function`, `Function Item` | Execute JavaScript that can invoke child_process.exec. |
EEFA note: In many production setups n8n runs as a Docker container with the host’s network stack. An unrestricted
Execute Commandnode can break out of the container if it is started with--privilegedor with excessive Linux capabilities.
2. Step‑by‑Step Exploit Example
Micro‑summary: A minimal workflow that upgrades a low‑privilege user to root on a typical Docker‑based n8n deployment.
2.1 Workflow definition – header
{
"nodes": [
2.2 First node – check current UID
{
"parameters": { "command": "id" },
"name": "Check Current UID",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [250, 300]
},
2.3 Second node – install sudo and modify sudoers
{
"parameters": {
"command": "apt-get update && apt-get install -y sudo && echo 'user ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers"
},
"name": "Escalate to Root",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [500, 300],
"executeAfter": ["Check Current UID"]
}
2.4 Connections and settings (truncated for brevity)
],
"connections": {
"Check Current UID": {
"main": [
[
{
"node": "Escalate to Root",
"type": "main",
"index": 0
}
]
]
}
},
"settings": { "executionMode": "manual" }
}
Why it works:
- The workflow is saved by a user with only the “workflow editor” role.
- n8n’s service account runs as
rootinside the container (common default). - The
Execute Commandnode runsapt-getand edits/etc/sudoers, granting the attacker full sudo rights on the host. - If you encounter any xss vectors in custom code resolve them before continuing with the setup.
3. Real‑World Constraints
| Constraint | Impact if ignored | Mitigation |
|---|---|---|
Container runs with --privileged |
Full host escape possible | Remove --privileged; use a minimal runtime profile (--cap-drop ALL). |
| Service account UID = 0 | All nodes inherit root privileges | Run n8n as a non‑root user (e.g., n8n UID 1000). |
| Stored admin tokens in environment variables | Nodes can read them without restriction | Use secret‑management (Docker secrets, HashiCorp Vault) and limit node access. |
4. Harden the Workflow Execution Environment
4.1 Run n8n in a Restricted Docker Sandbox
Context: The command below starts n8n with a non‑privileged user, drops all capabilities, and enforces a read‑only root filesystem.
docker run -d \ --name n8n \ --user 1000:1000 \ --cap-drop ALL \ --read-only \ -v /data/n8n:/home/node/.n8n \ -p 5678:5678 \ n8nio/n8n:latest
If you need writable temporary storage, bind‑mount a sub‑directory:
docker run -d \ ... \ -v /data/n8n/tmp:/tmp:rw \ n8nio/n8n:latest
EEFA note: Mount only the directories you need (
/tmpfor logs,/home/node/.n8nfor data).
4.2 Enable “Run as Separate Process” for Dangerous Nodes
| Setting | Recommended value | Reason |
|---|---|---|
| Run Node in Separate Process | Enabled | Isolates each node in its own child process, limiting blast radius. |
| Maximum Concurrent Executions | 2 (or lower) | Reduces parallel attack surface. |
| Execution Timeout | 300s | Stops long‑running malicious commands. |
5. Role‑Based Access Control (RBAC) for Workflow Creation
Micro‑summary: Restrict who can add high‑risk node types and enforce a deny list.
| Role | Permissions on Workflow Nodes |
|---|---|
| Viewer | Read‑only access to workflow definitions. |
| Editor | Can add/modify nodes except Execute Command, Function, Function Item. |
| Admin | Full access – limit to trusted users only. |
5.1 Enable RBAC in n8n
- Set
N8N_USER_MANAGEMENT=true(or edit~/.n8n/config). - In the UI, go to Settings → Users & Permissions and create the roles above.
5.2 Add a node‑type deny list for the *Editor* role
{
"nodeTypesDenied": [
"n8n-nodes-base.executeCommand",
"n8n-nodes-base.function",
"n8n-nodes-base.functionItem"
]
}
3. Save and restart n8n.
EEFA note: The deny list blocks UI creation of those nodes, but an attacker could still import a JSON workflow containing them. Combine RBAC with import validation (next section).
6. Validate Imported Workflows – Prevent “Supply‑Chain” Escalation
Context: A pre‑execution hook scans incoming workflow JSON for prohibited node types and aborts execution if any are found.
6.1 Hook implementation (part 1)
module.exports = async function preExecuteWorkflow(workflow) {
const prohibited = [
'n8n-nodes-base.executeCommand',
'n8n-nodes-base.function',
'n8n-nodes-base.functionItem'
];
6.2 Hook implementation (part 2)
const offending = workflow.nodes.filter(
node => prohibited.includes(node.type)
);
if (offending.length) {
throw new Error(
`Workflow rejected: contains prohibited node(s) ${offending
.map(n => n.type)
.join(', ')}`
);
}
return workflow;
};
6.3 Register the hook
export N8N_CUSTOM_HOOKS="/home/node/.n8n/custom/hooks"
Now any workflow import that includes a dangerous node will be blocked before execution. Secure your n8n webhooks – prevents credential leakage via exposed endpoints.
7. Detection & Monitoring
Micro‑summary: Combine audit logs, log shipping, metrics, and runtime security to surface suspicious activity.
| Tool | What to monitor | Alert condition |
|---|---|---|
| Audit Logs (n8n → Settings → Audit) | Creation/modification of Execute Command nodes |
Log entry with nodeType=executeCommand and userRole!=admin. |
| Filebeat / Fluent Bit | Container stdout/stderr for privileged commands | Regex sudo|chmod|chown → send to SIEM. |
| Prometheus Exporter | n8n_execution_time_seconds per node type |
Spike in execution time for executeCommand > 30 s. |
| Falco (runtime security) | execve syscalls from n8n container |
Alert on execve with /bin/sh -c apt-get. |
Sample Falco rule (part 1)
- rule: n8n Execute Command Abuse
desc: Detect execution of privileged commands from n8n container
condition: >
container.image = "n8nio/n8n:latest"
and evt.type = execve
Sample Falco rule (part 2)
and proc.name in (apt-get, yum, sudo, chmod, chown) output: "Potential privilege escalation via n8n workflow (container=%container.id command=%proc.cmdline)" priority: WARNING tags: [n8n, privilege_escalation]
8. Checklist – Secure Your n8n Workflows Against Privilege Escalation
- Run n8n container as non‑root (
--user 1000:1000). - Drop all Linux capabilities (
--cap-drop ALL). - Enable “Run Node in Separate Process”.
- Configure RBAC: deny
Execute Command,Function,Function Itemfor non‑admin roles. - Deploy the pre‑execution hook to reject prohibited node types on import.
- Audit workflow changes daily; alert on any new
Execute Commandnodes. - Set up Falco (or equivalent) to catch privileged syscalls.
- Rotate stored admin tokens and store them in a secret manager, not environment variables.
Conclusion
By isolating the n8n runtime (non‑root Docker sandbox, capability drop, read‑only root), enforcing strict RBAC, validating imported workflows, and continuously monitoring for privileged command execution, you eliminate the most common privilege‑escalation pathways that stem from malicious workflow design. This hardening aligns with production‑grade security standards and ensures that workflow execution never becomes a backdoor into your infrastructure.



