Basic FTP has Path Traversal Vulnerability in its downloadToDir() method
The basic-ftp library contains a path traversal vulnerability in the downloadToDir() method. A malicious FTP server can send directory listings with filenames containing path traversal sequences (../) that cause files to be written outside the intended download directory.
Source-to-Sink Flow
1. SOURCE: FTP server sends LIST response
└─> "-rw-r--r-- 1 user group 1024 Jan 20 12:00 ../../../etc/passwd"
2. PARSER: parseListUnix.ts:100 extracts filename
└─> file.name = "../../../etc/passwd"
3. VALIDATION: parseListUnix.ts:101 checks
└─> if (name === "." || name === "..") ❌ (only filters exact matches)
└─> "../../../etc/passwd" !== "." && !== ".." ✅ PASSES
4. SINK: Client.ts:707 uses filename directly
└─> const localPath = join(localDirPath, file.name)
└─> join("/safe/download", "../../../etc/passwd")
└─> Result: "/safe/download/../../../etc/passwd" → resolves to "/etc/passwd"
5. FILE WRITE: Client.ts:512 opens file
└─> fsOpen(localPath, "w") → writes to /etc/passwd (outside intended directory)
Vulnerable Code
File: src/Client.ts:707
protected async _downloadFromWorkingDir(localDirPath: string): Promise<void> {
await ensureLocalDirectory(localDirPath)
for (const file of await this.list()) {
const localPath = join(localDirPath, file.name) // ⚠️ VULNERABLE
// file.name comes from untrusted FTP server, no sanitization
await this.downloadTo(localPath, file.name)
}
}
Root Cause:
- Parser validation (parseListUnix.ts:101) only filters exact . or .. entries
- No sanitization of ../ sequences in filenames
path.join()doesn't prevent traversal,fs.open()resolves paths
Impact
A malicious FTP server can: - Write files to arbitrary locations on the client filesystem - Overwrite critical system files (if user has write access) - Potentially achieve remote code execution
Affected Versions
- Tested: v5.1.0
- Likely: All versions (code pattern exists since initial implementation)
Mitigation
Workaround: Do not use downloadToDir() with untrusted FTP servers.
Fix: Sanitize filenames before use:
import { basename } from 'path'
// In _downloadFromWorkingDir:
const sanitizedName = basename(file.name) // Strip path components
const localPath = join(localDirPath, sanitizedName)
Affected software
Click a technology to see all vulnerabilities affecting it.
| Platform | Package | Vulnerable versions | Fixed in |
|---|---|---|---|
| npm package | basic-ftp | < 5.2.0 | 5.2.0 |
References
- https://github.com/patrickjuchli/basic-ftp/security/advisories/GHSA-5rq4-664w-9x2c
- https://nvd.nist.gov/vuln/detail/CVE-2026-27699
- https://github.com/patrickjuchli/basic-ftp/commit/2a2a0e6514357b9eda07c2f8afbd3f04727a7cd9
- https://github.com/patrickjuchli/basic-ftp
- https://github.com/patrickjuchli/basic-ftp/releases/tag/v5.2.0
- CVSS vector
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H- Weakness (CWE)
CWE-22- Platform
- npm
- Package
basic-ftp- Disclosed
- 25.02.2026
- Updated
- 11.10.2026 10:22
Sources and licenses
OSV / GitHub Advisory Database - GHSA-5rq4-664w-9x2c - CC BY 4.0
Vulnerability history: basic-ftp
All published vulnerabilities of this package (npm package), newest first. Shows whether this is a one-off slip or a package that needs watching.
- Total entries
- 6
- First → latest
- 02.2026 10.2026
- Without a fix
- 0
- Exploited in attacks
- 0
Severity breakdown
- Critical 1
- High 5
Disclosures per year
- 2026: 6
-
Basic FTP has Path Traversal Vulnerability in its downloadToDir() method this entry
Know which vulnerabilities affect your application
With the DockRay integration and software inventory enabled, DockRay checks reported component versions against known vulnerabilities and notifies you about confirmed matches. Coverage depends on the supported technology and available advisory data.