Skip to content

[WIP] Fix path traversal vulnerability in basic-ftp library#683

Closed
Copilot wants to merge 1 commit into
mainfrom
copilot/fix-basic-ftp-path-traversal-vulnerability
Closed

[WIP] Fix path traversal vulnerability in basic-ftp library#683
Copilot wants to merge 1 commit into
mainfrom
copilot/fix-basic-ftp-path-traversal-vulnerability

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 16, 2026

  • Identify the direct dependency path to basic-ftp and confirm current vulnerable resolution
  • Run baseline install/lint/build/test commands to capture pre-change state
  • Update dependency resolution to basic-ftp >= 5.2.0 with minimal manifest/lock changes
  • Add or update focused tests only if needed for changed behavior
  • Run targeted validation for affected package(s), then run repo-level checks as feasible
  • Verify lockfile resolves a non-vulnerable basic-ftp and document reachability assessment
Original prompt

This section details the Dependabot vulnerability alert you should resolve

<alert_title>Basic FTP has Path Traversal Vulnerability in its downloadToDir() method</alert_title>
<alert_description>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)
```</alert_description>

<severity>critical</severity>
<identifiers>GHSA-5rq4-664w-9x2c, CVE-2026-27699</identifiers>
<package>basic-ftp</package>
<ecosystem>npm</ecosystem>
<vulnerable_versions>5.0.5</vulnerable_versions>
<patched_version>5.2.0</patched_version>
<manifest_path>package-lock.json</manifest_path>

<references>
<url>https://github.com/patrickjuchli/basic-ftp/security/advisories/GHSA-5rq4-664w-9x2c</url>
<url>https://nvd.nist.gov/vuln/detail/CVE-2026-27699</url>
<url>https://github.com/patrickjuchli/basic-ftp/commit/2a2a0e6514357b9eda07c2f8afbd3f04727a7cd9</url>
<url>https://github.com/patrickjuchli/basic-ftp/releases/tag/v5.2.0</url>
<url>https://github.com/advisories/GHSA-5rq4-664w-9x2c</url>
</references>

<agent_instructions>Upgrade dependencies in the relevant packages to address this CVE. If this is a transitive dependency, find the direct dependency that brings it in and attempt to update that one, even if it requires a major version upgrade. If a major version bump is required, make the necessary code changes to adapt to the new API. Only ever use `overrides` in package.json if there's no new version of the direct dependency that pulls in the fixed transitive dependency.</agent_instructions>

<task_instructions>Resolve this alert by updating the affected package to a non-vulnerable version. Prefer the lowest non-vulnerable version (see the patched_version field above) over the latest to minimize breaking changes. Include a Reachability Assessment section in the PR description. Review the alert_description field to understand which APIs, features, or configurations are affected, then search the codebase for usage of those specific items. If the vulnerable code path is reachable, explain how (which files, APIs, or call sites use the affected functionality) and note that the codebase is actively exposed to this vulnerability. If the vulnerable code path is not reachable, explain why (e.g. the affected API is never called, the vulnerable configuration is not used) and note that the update is primarily to satisfy vulnerability scanners rather than to address an active risk. If the advisory is too vague to determine reachability (e.g. 'improper input validation' with no specific API named), state that reachability could not be determined and explain why. Include a confidence level in the reachability assessment (e.g. high confidence if the advisory names a specific API and you confirmed it is or is not called, low confidenc...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Resolves mongodb-js/devtools-shared alert #155

@nirinchev
Copy link
Copy Markdown
Collaborator

Duplicate of #682

@nirinchev nirinchev marked this as a duplicate of #682 Apr 16, 2026
Copilot stopped work on behalf of nirinchev due to an error April 16, 2026 18:24
Copilot AI requested a review from nirinchev April 16, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants