Miggo Logo

CVE-2025-57749: n8n symlink traversal vulnerability in "Read/Write File" node allows access to restricted files

6.5

CVSS Score
3.1

Basic Information

EPSS Score
-
Published
8/20/2025
Updated
8/20/2025
KEV Status
No
Technology
TechnologyJavaScript

Technical Details

CVSS Vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Package NameEcosystemVulnerable VersionsFirst Patched Version
n8nnpm< 1.106.01.106.0

Vulnerability Intelligence
Miggo AIMiggo AI

Miggo AIRoot Cause Analysis

The core of the vulnerability exists in the isFilePathBlocked function located in packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts. This function was intended to prevent access to restricted file paths. However, it used path.resolve() to determine the absolute path of a file, which does not resolve symbolic links (symlinks). This oversight allows an attacker with the ability to create symlinks on the server (for instance, via the 'Execute Command' node) to bypass the security check. An attacker could create a symlink in an accessible directory that points to a sensitive file or directory elsewhere on the system. When the 'Read/Write File' node operates on this symlink, isFilePathBlocked would check the path of the symlink itself, deem it safe, and allow the operation to proceed on the linked, restricted file.

The patch rectifies this by replacing path.resolve() with fs.realpath(). The fs.realpath() function resolves the entire path, including any symlinks, to its canonical physical path. This ensures that the check is performed on the true destination of the path, effectively closing the traversal vulnerability.

The functions assertFileIsReadable and writeContentToFile, which are part of the object returned by getFileSystemHelperFunctions, directly utilize isFilePathBlocked to secure file operations. Consequently, these functions are the primary runtime indicators that would appear in a stack trace or profiler output during an exploit attempt involving reading from or writing to a file through a malicious symlink.

Vulnerable functions

isFilePathBlocked
packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts
The function `isFilePathBlocked` was vulnerable to a symlink traversal attack because it used `path.resolve()` which does not resolve symbolic links. An attacker could create a symlink in an allowed directory that points to a restricted file or directory, bypassing the path validation. The patch replaces `resolve()` with `fs.realpath()` which resolves symlinks to their actual paths, thus fixing the vulnerability.
getFileSystemHelperFunctions.assertFileIsReadable
packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts
This function is responsible for checking if a file is readable before any read operation is performed. It calls the vulnerable `isFilePathBlocked` function. An attacker could exploit this by providing a path to a symlink, which would then be passed to `isFilePathBlocked`, allowing unauthorized file reads.
getFileSystemHelperFunctions.writeContentToFile
packages/core/src/execution-engine/node-execution-context/utils/file-system-helper-functions.ts
This function is responsible for checking if a file is writable before any write operation is performed. It calls the vulnerable `isFilePathBlocked` function. An attacker could exploit this by providing a path to a symlink, which would then be passed to `isFilePathBlocked`, allowing unauthorized file writes.

WAF Protection Rules

WAF Rule

### Imp**t * symlink tr*v*rs*l vuln*r**ility w*s *is*ov*r** in t** `R***/Writ* *il*` no** in n*n. W*il* t** no** *tt*mpts to r*stri*t ****ss to s*nsitiv* *ir**tori*s *n* *il*s, it *o*s not prop*rly ***ount *or sym*oli* links (symlinks). *n *tt**k*r w

Reasoning

T** *or* o* t** vuln*r**ility *xists in t** `is*il*P*t**lo*k**` *un*tion lo**t** in `p**k***s/*or*/sr*/*x**ution-*n*in*/no**-*x**ution-*ont*xt/utils/*il*-syst*m-**lp*r-*un*tions.ts`. T*is *un*tion w*s int*n*** to pr*v*nt ****ss to r*stri*t** *il* p*t