CVE-2026-21877: why the CVSS 9.9 score is justified
The vulnerability is classified CWE-434 — unrestricted upload of a file with a dangerous type. The Git node in n8n allows, under certain conditions, an authenticated user to write an arbitrary file to the server's filesystem. An attacker can write a script to a directory executed by the n8n process, then trigger it via a workflow to achieve remote code execution.
The attack vector is network-based, with no additional user interaction required. The scope changes (scope: Changed), meaning the impact extends beyond the n8n process: confidentiality, integrity, and availability of the host are all compromised. The EPSS score reaches 5.449% (92nd percentile), indicating a high probability of active exploitation within 30 days.
Alert AL26-001 from the Canadian Centre for Cyber Security also covers CVE-2026-21858 (insufficient input validation on webhooks, CVSS 10.0 per some sources) and CVE-2025-68613 (insufficient isolation of expressions in workflow configurations). All three should be addressed within the same remediation scope.
Who is exposed and in which version range
- All self-hosted n8n instances >= 0.123.0 and < 1.121.3 are vulnerable to CVE-2026-21877 according to GitHub advisory GHSA-v364-rw7m-3263.
- Instances behind a reverse proxy are not protected: the vulnerability is authenticated — a compromised account or a malicious insider is sufficient; the network perimeter does not change the exposure.
- Both Docker and npm deployments are affected: the vector is the Git node, present in all n8n distributions regardless of installation method.
- n8n Cloud instances managed by n8n.io received the patch with no operator action required.
- CVE-2025-68613 covers versions 0.211.0 to < 1.120.4: if you have not yet reached 1.120.4, you are exposed to both CVEs simultaneously.
- CVE-2026-21858 affects versions 1.65.0 to < 1.121.0: updating to 1.121.3 addresses all three CVEs in a single operation.
- The EPSS score of 5.449% places this CVE in the 92nd percentile of active exploitation probability, justifying patch priority over other scheduled maintenance.
Check your n8n instance version
Before applying the patch, identify the exact version currently running. Three methods depending on your deployment context.
Via the web interface: log in to your instance, click the profile icon at the bottom left, then click "About n8n". The version is displayed in the modal window.
Via Docker: the command docker inspect <container-name> --format '{{index .Config.Labels "org.opencontainers.image.version"}}' returns the version of the running image. If the container was started from the n8nio/n8n:latest image, this value reflects what was current at the time of the last docker pull.
Via the internal API: a curl http://localhost:5678/healthz on the host returns {"status":"ok"} with the version in the headers if the instance is running.
If your version is below 1.121.3, apply the procedure below without waiting for your next maintenance window.
Update procedure to n8n ≥ 1.121.3
Back up your database and configuration files
Before any update, back up the current state. For a Docker Compose installation, export the SQLite or PostgreSQL database according to your configuration:
# SQLite (default path) cp ~/.n8n/database.sqlite ~/.n8n/database.sqlite.bak-$(date +%Y%m%d) # PostgreSQL pg_dump -U n8n -d n8n > n8n-backup-$(date +%Y%m%d).sqlAlso copy your
docker-compose.ymland.envfile to a backup directory.Update the docker-compose.yml file
If you are using the
n8nio/n8n:latestimage, no changes to thedocker-compose.ymlfile are required. If you have pinned an explicit version (for examplen8nio/n8n:1.115.0), update theimageline:services: n8n: image: n8nio/n8n:1.121.3If you want to follow the long-term stable branch, using an explicit version tag is preferable to
latestfor controlling maintenance windows.Pull the new image
From the directory containing your
docker-compose.yml:docker compose pullThis command downloads only the layers of the image that have changed. On a 100 Mbit/s uplink, expect 30 to 90 seconds depending on your local cache.
Stop the current instance
docker compose downThe shutdown is graceful: n8n waits for running executions to finish before stopping, unless you add
--timeout 0. On a heavily loaded instance, prefer waiting for active workflows to complete before running this command, or suspend critical workflows from the interface.Restart with the new image
docker compose up -dDocker Compose uses the newly pulled image. Startup typically takes 10 to 20 seconds. The startup log should display version 1.121.3 or higher.
Verify the deployed version
docker compose logs n8n | grep -i 'version\|n8n@'Or via the internal API, from the host:
curl -s http://localhost:5678/healthzConfirm that the version displayed in the interface (profile icon → About n8n) is 1.121.3 or higher before considering the update complete.
Disable the Git node if you do not use it
To neutralize the attack vector immediately without waiting for the update (for example if a maintenance window is not immediately available), disable the Git node via the environment variable:
N8N_NODES_EXCLUDE='["n8n-nodes-base.git"]'Add this variable to your
.envfile and restart the instance. This is not a substitute for the update: apply the patch as soon as possible.For an npm installation (without Docker)
npm update -g n8n # Or, if you use a process manager: pm2 stop n8n npm update -g n8n pm2 start n8nVerify the installed version with
n8n --version. Migrating to Docker is recommended for new installations — the dedicated guiden8n-migration-npm-docker-avant-v3covers this path in detail.
Post-patch hardening: reducing the attack surface
The update fixes the known vulnerability, but several configurations strengthen the overall security posture of the instance.
Restrict n8n process permissions. The container should not run as root. The official image uses the node user by default for several versions — verify that your docker-compose.yml does not contain user: root.
Enable authentication. If your instance is exposed on the internet without authentication, add N8N_BASIC_AUTH_ACTIVE=true with strong credentials, or place the instance behind a proxy that requires authentication. CVE-2026-21877 is authenticated, but other unauthenticated vectors exist in the ecosystem.
Limit allowed nodes. The N8N_NODES_INCLUDE variable allows only a subset of nodes. On instances dedicated to workflows that do not require Git or system access, an inclusion list reduces the surface.
Audit user accounts. In the administration interface, verify that every active account is legitimate and that test accounts or former collaborators' accounts are disabled.
Subscribe to n8n security alerts. The GitHub repository n8n-io/n8n allows subscribing to security notifications via "Watch → Security alerts".
Scheduling bug after version 2.21.7: symptom and workaround
GitHub issue #31100 documents behavior reported after updating to version 2.21.7: workflows with scheduled triggers (Schedule Trigger node) stop executing at their scheduled time, without any visible error message in the logs.
Exact symptom: workflows remain in "active" state in the interface, the next scheduled trigger time is displayed, but executions do not occur. The execution log shows no failed attempts — the workflows are simply not triggered. This behavior is primarily observed on queue-mode deployments (multi-worker), with PostgreSQL, but can also affect single-process instances.
What the issue indicates about the workaround: at the time this article was published, the issue is marked "Needs Feedback" by the n8n team, and no official documented workaround has been published in the thread. Several operators reported that the following approaches restored scheduled executions in their environment:
- Manually deactivate then reactivate each affected workflow from the interface (Active/Inactive toggle).
- Restart the n8n container or service, which forces reinitialization of the internal scheduling queue.
- On queue-mode deployments: restart the main node first, before workers.
These actions are not a fix: the problem may recur. Monitor issue #31100 for official status and the fix version.
Quickly identifying affected workflows: in the n8n interface, filter the execution history by "Schedule" trigger and check for missing executions over the expected period. A workflow that should have run ten times since midnight with no trace in the log is a clear signal.
Post-migration checks: what to verify before reopening traffic
A successful n8n update is confirmed on several axes, not just the displayed version.
Version: the "About n8n" interface shows 1.121.3 or higher. The docker inspect command on the running image returns the same number.
Credential integrity: n8n encrypts credentials with a key derived from N8N_ENCRYPTION_KEY. If this variable has not changed between versions, existing credentials are intact. Open a workflow that uses an external connection (HTTP Request, database, third-party API) and verify it runs without decryption errors.
Active workflows: in the dashboard, verify that the number of active workflows matches the pre-update state. A workflow that was active and is no longer active after restart is a warning signal.
Scheduled executions: if your instance uses Schedule Trigger nodes, wait for the next trigger time and confirm execution in the log. If you are on version 2.21.7 of the 2.x branch, consult the previous section on the scheduling bug.
Startup logs: docker compose logs n8n --tail 50 should show a clean startup without exceptions. Database connection errors or credential decryption errors appear in these first lines.
Network access: if your instance is exposed via a reverse proxy, verify that the /webhook/ and /webhook-test/ routes respond correctly after the update.
n8n versions: exposure to CVEs from alert AL26-001
Scroll the table
| Version | CVE-2025-68613 | CVE-2026-21858 | CVE-2026-21877 | Required action |
|---|---|---|---|---|
| < 1.120.4 | Vulnerable | Vulnerable | Vulnerable | Update to ≥ 1.121.3 |
| 1.120.4 – 1.120.x | Fixed | Vulnerable | Vulnerable | Update to ≥ 1.121.3 |
| 1.121.0 – 1.121.2 | Fixed | Fixed | Vulnerable | Update to ≥ 1.121.3 |
| ≥ 1.121.3 | Fixed | Fixed | Fixed | No CVE action required |
| 2.x < 2.21.7 | Check release notes | Check release notes | Check release notes | Check 2.x release notes |
| 2.21.7+ | Check release notes | Check release notes | Check release notes | Scheduling bug #31100 active |
Keeping your n8n instance up to date: the VPS approach
CVE-2026-21877 illustrates the cost of a self-hosted instance whose updates depend on an external maintenance window. On a VPS with root access, docker compose pull && docker compose up -d applies the patch in under ten minutes, without depending on a provider to decide the timing.
This autonomy comes with a responsibility: monitoring security advisories falls to the operator. Two sources to watch for n8n: the GitHub repository (Security tab, notifications can be enabled) and alerts from the Canadian Centre for Cyber Security or the equivalent CERT in your region.
For more on setting up a robust n8n instance — initial installation, Caddy or nginx reverse proxy, automatic TLS, and backups — see the guide install n8n on VPS. If you are coming from an npm installation and considering migration to Docker before moving to the 2.x branch, the guide migration from npm to Docker before v3 covers this path. The patch pattern applied here is identical to the one documented for CVE-2026-6471 on PostgreSQL.