This repository is a fork of n8n (v2.6.0) used to study and verify the fix for CVE-2026-21877, a critical Remote Code Execution (RCE) vulnerability in n8n's Git node.
| Field | Details |
|---|---|
| CVE ID | CVE-2026-21877 |
| CVSS Score | 10.0 (Critical) |
| Type | Authenticated Remote Code Execution via Arbitrary File Write |
| CWE | CWE-94 (Improper Control of Generation of Code) / CWE-434 (Unrestricted Upload of File with Dangerous Type) |
| Affected Versions | >= 0.123.0, < 1.121.3 |
| Fixed In | 1.121.3 |
| Discovered By | Theo Lelasseux (@theolelasseux) |
An authenticated user could exploit the Git node to manipulate file system operations, enabling arbitrary code execution within the n8n service. The vulnerability stems from insufficient validation of repository paths in the Git node, allowing attackers to write files to arbitrary locations and achieve RCE. It can also be chained with CVE-2026-21858 (unauthenticated access via webhook endpoints) for unauthenticated exploitation.
This fork (v2.6.0) contains the patched code. The fix introduces multiple layers of defense across several files:
The Git node now resolves the repository path and checks it against a blocklist before any operation:
const repositoryPath = this.getNodeParameter('repositoryPath', itemIndex, '') as string;
const resolvedRepositoryPath = await this.helpers.resolvePath(repositoryPath);
const isFilePathBlocked = this.helpers.isFilePathBlocked(resolvedRepositoryPath);
if (isFilePathBlocked) {
throw new NodeOperationError(
this.getNode(),
'Access to the repository path is not allowed',
);
}2. File Path Blocking (packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts)
The isFilePathBlocked() function enforces a multi-layer access control system:
- Restricted paths -- blocks access to n8n internal directories (config, cache, binary storage, email templates, custom extensions)
- Blocked file patterns -- regex-based file pattern blocking
- Allowed paths whitelist -- if configured, only permits access to explicitly allowed directories
The resolvePath() function resolves symlinks via fs.realpath() before any path check, preventing directory traversal via symbolic links.
The validateGitReference() function prevents command injection through branch/tag names by:
- Allowing only safe characters (
a-zA-Z0-9/@{}._:-) - Blocking references starting with
-(prevents argument injection) - Blocking
..sequences (prevents path traversal) - Blocking control characters
Git add and commit operations use the -- separator to prevent argument injection:
await git.add(['--', ...paths]);
await git.commit(message, ['--', ...pathsToAdd]);The isContainedWithin() utility ensures child paths are actually within their claimed parent directory using proper path separator matching.
| File | Role |
|---|---|
packages/nodes-base/nodes/Git/Git.node.ts |
Git node implementation with path validation |
packages/nodes-base/nodes/Git/GenericFunctions.ts |
Git reference validation |
packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts |
resolvePath() and isFilePathBlocked() |
packages/@n8n/backend-common/src/utils/path-util.ts |
isContainedWithin() path utility |
packages/nodes-base/nodes/Git/__test__/Git.node.test.ts |
Tests for blocked paths and validation |
packages/core/src/execution-engine/node-execution-context/utils/__tests__/file-system-helper-functions.test.ts |
Tests for file path blocking |
To verify the fix is in place, run the relevant test suites:
# Install dependencies
pnpm install
# Run Git node tests
pushd packages/nodes-base && pnpm test nodes/Git/__test__/Git.node.test.ts && popd
# Run file system helper tests
pushd packages/core && pnpm test src/execution-engine/node-execution-context/utils/__tests__/file-system-helper-functions.test.ts && popd- GitHub Advisory GHSA-v364-rw7m-3263
- The Hacker News: n8n Warns of CVSS 10.0 RCE Vulnerability
- Canadian Centre for Cyber Security Advisory
- Qualys ThreatPROTECT Advisory
- SOCRadar Analysis
- Upwind CVE Feed
This is a fork of n8n, which is fair-code distributed under the Sustainable Use License and n8n Enterprise License.