<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Most recent entries from all</title>
    <link>https://vulnerability.circl.lu</link>
    <description>Contains only the most 10 recent entries.</description>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>python-feedgen</generator>
    <language>en</language>
    <lastBuildDate>Thu, 01 Oct 2026 23:03:32 +0000</lastBuildDate>
    <item>
      <title>fkie_cve-2026-102990</title>
      <link>https://vulnerability.circl.lu/vuln/fkie_cve-2026-102990</link>
      <description>&lt;p&gt;basic-ftp is an FTP client for Node.js. Prior to 6.2.1, Client.list() can be forced by a malicious or compromised FTP server to spend quadratic CPU time parsing a directory listing because the RE_LINE expression in src/parseListUnix.ts backtracks across adjacent variable-length owner and group fields when a long Unix-style line has a valid prefix but cannot satisfy the later size and date fields. parseList() selects a parser from the last nonblank line and then applies it to every line, so a normal final line can select the Unix parser while an earlier crafted line blocks the Node.js event loop and freezes the process. This issue is fixed in version 6.2.1.&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;basic-ftp is an FTP client for Node.js. Prior to 6.2.1, Client.list() can be forced by a malicious or compromised FTP server to spend quadratic CPU time parsing a directory listing because the RE_LINE expression in src/parseListUnix.ts backtracks across adjacent variable-length owner and group fields when a long Unix-style line has a valid prefix but cannot satisfy the later size and date fields. parseList() selects a parser from the last nonblank line and then applies it to every line, so a normal final line can select the Unix parser while an earlier crafted line blocks the Node.js event loop and freezes the process. This issue is fixed in version 6.2.1.&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/fkie_cve-2026-102990</guid>
    </item>
    <item>
      <title>GHSA-c475-qrg2-pj4r — basic-ftp: Quadratic-time CPU denial of service in Client.list() Unix directory-listing parser (RE_LINE backtracking)</title>
      <link>https://vulnerability.circl.lu/vuln/ghsa-c475-qrg2-pj4r</link>
      <description>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; npm: basic-ftp&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;`Client.list()` parses the server&amp;#39;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&amp;#39;s length.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;## Proof of concept&lt;/p&gt;
&lt;p&gt;`npm i basic-ftp &amp;amp;&amp;amp; node repro.js`:&lt;/p&gt;
&lt;p&gt;```js
const net = require(&amp;#34;net&amp;#34;), ftp = require(&amp;#34;basic-ftp&amp;#34;);
const KB = Number(process.env.LINE_KB || 128);
const payload = &amp;#34;-rw-r--r-- 1 &amp;#34; + &amp;#34;a &amp;#34;.repeat((KB * 1024 - 13) / 2) + &amp;#34;!&amp;#34;;
const listing = payload + &amp;#34;\r\n-rw-r--r-- 1 owner group 42 Jan 1 2020 file.txt\r\n&amp;#34;;
const server = net.createServer(c =&amp;gt; {
  c.setEncoding(&amp;#34;latin1&amp;#34;); c.write(&amp;#34;220 ok\r\n&amp;#34;); let buf = &amp;#34;&amp;#34;;
  c.on(&amp;#34;data&amp;#34;, d =&amp;gt; { buf += d; let i;
    while ((i = buf.indexOf(&amp;#34;\r\n&amp;#34;)) !== -1) {
      const cmd = buf.slice(0, i).toUpperCase(); buf = buf.slice(i + 2);
      if (cmd.startsWith(&amp;#34;US…&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;strong&gt;Affected:&lt;/strong&gt; npm: basic-ftp&lt;/p&gt;
&lt;p&gt;## Summary&lt;/p&gt;
&lt;p&gt;`Client.list()` parses the server&amp;#39;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&amp;#39;s length.&lt;/p&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;## Proof of concept&lt;/p&gt;
&lt;p&gt;`npm i basic-ftp &amp;amp;&amp;amp; node repro.js`:&lt;/p&gt;
&lt;p&gt;```js
const net = require(&amp;#34;net&amp;#34;), ftp = require(&amp;#34;basic-ftp&amp;#34;);
const KB = Number(process.env.LINE_KB || 128);
const payload = &amp;#34;-rw-r--r-- 1 &amp;#34; + &amp;#34;a &amp;#34;.repeat((KB * 1024 - 13) / 2) + &amp;#34;!&amp;#34;;
const listing = payload + &amp;#34;\r\n-rw-r--r-- 1 owner group 42 Jan 1 2020 file.txt\r\n&amp;#34;;
const server = net.createServer(c =&amp;gt; {
  c.setEncoding(&amp;#34;latin1&amp;#34;); c.write(&amp;#34;220 ok\r\n&amp;#34;); let buf = &amp;#34;&amp;#34;;
  c.on(&amp;#34;data&amp;#34;, d =&amp;gt; { buf += d; let i;
    while ((i = buf.indexOf(&amp;#34;\r\n&amp;#34;)) !== -1) {
      const cmd = buf.slice(0, i).toUpperCase(); buf = buf.slice(i + 2);
      if (cmd.startsWith(&amp;#34;US…&lt;/p&gt;</content:encoded>
      <guid isPermaLink="false">https://vulnerability.circl.lu/vuln/ghsa-c475-qrg2-pj4r</guid>
    </item>
  </channel>
</rss>
