
Cloud Vulnerability DB
A community-led vulnerabilities database
downloadToDir() sanitizes file/directory names returned by the FTP server using basename(file.name) !== file.name. However, path.basename("..") === "..", so the check evaluates to false for the literal name .., allowing the traversal protection to be bypassed. A malicious FTP server can list a directory entry named .., causing the client to descend outside the intended local destination directory.
src/Client.ts:737 — sanitization check does not handle ..:
const hasInvalidName = !file.name || basename(file.name) !== file.name
// BYPASS: basename("..") === ".." → hasInvalidName = false → not skippedsrc/Client.ts:743 — path constructed with unsanitized name:
const localPath = join(localDirPath, file.name)
// join("/home/user/downloads", "..") → "/home/user" (outside target dir)src/Client.ts:745-746 — recursive download outside target:
await this.cd(file.name) // cd("..") on the server
await this._downloadFromWorkingDir(localPath) // downloads to /home/user insteadconst { basename, join } = require("path");
// The check that is supposed to block traversal:
const fileName = "..";
const hasInvalidName = !fileName || basename(fileName) !== fileName;
console.log("hasInvalidName:", hasInvalidName);
// Output: hasInvalidName: false ← BYPASSED
const localPath = join("/home/user/downloads", fileName);
console.log("resolved path:", localPath);
// Output: resolved path: /home/user ← ESCAPED target directoryA malicious FTP server returning [{ name: "..", isDirectory: true }] from its LIST response triggers this code path, causing _downloadFromWorkingDir to be called with the parent directory path, writing server files outside the intended download location.
A client connecting to a malicious FTP server (e.g., via a user-supplied URL, a Man-in-the-Middle attack on unencrypted FTP, or a compromised server) and calling downloadToDir() may have files written outside the intended local directory, potentially overwriting system files or placing malicious files in sensitive locations.
v6.2.4 (latest) and earlier versions with downloadToDir().
Add an explicit check for . and .. in the name guard:
const hasInvalidName =
!file.name ||
file.name === "." ||
file.name === ".." || // add this line
basename(file.name) !== file.name;Or use a path containment check:
const resolvedLocal = resolve(localDirPath, file.name);
if (!resolvedLocal.startsWith(resolve(localDirPath) + sep)) {
this.ftp.log(`Unsafe filename skipped: ${JSON.stringify(file.name)}`);
continue;
}Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."