npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

basic-ftp-fixed

v5.1.2

Published

Fork of basic-ftp with fixes for TLS 1.3 upload failures (vsftpd 426 bug) and passive mode listener leaks.

Readme

basic-ftp-fixed

Drop-in replacement for basic-ftp 5.1.0 with critical bug fixes for FTPS over TLS 1.3.

Installation

npm install basic-ftp-fixed

Usage is identical to basic-ftp — just change the package name in your require() / import.

Fixes

Fix 1: Passive mode listener leak (transfer.js — connectForPassiveTransfer)

Bug: When FTPS wraps a plain TCP socket in TLS, the local variable socket is reassigned to the new TLS socket. The subsequent removeListener("error"/timeout") calls operate on the TLS wrapper (which never had those listeners), leaving the original plain socket with active listeners and a running setTimeout.

Impact: If the plain socket's idle timeout fires, the handleTimeout closure captures the reassigned socket variable (now the TLS wrapper) and calls socket.destroy(), killing the active TLS data connection and causing transfer failures.

Fix: Save a reference to the original plain socket before TLS wrapping. Remove listeners and clear the timeout on the original socket.

Fix 2: TLS 1.3 session ticket caching (FtpContext.js)

Bug: In TLS 1.3, session tickets are delivered asynchronously via the session event after the handshake completes. getSession() may return stale or missing session data if called before the latest ticket arrives.

Fix: Listen for the session event on the control socket and cache the latest session ticket. Data connections prefer the cached session, falling back to getSession().

Fix 3: Upload 426 error with vsftpd + TLS 1.3 (transfer.js — uploadFrom + connectForPassiveTransfer)

Bug: pipeline(source, dataSocket, callback) automatically calls end() on the TLS data socket immediately after the source stream ends. This sends a TLS close_notify alert. On vsftpd 3.0.5 with TLS 1.3, the close_notify arrives before the server has finished reading all data from its internal SSL buffers, causing vsftpd to report 426 Failure reading network stream.

Impact: FTPS uploads to vsftpd servers running TLS 1.3 fail with 426 errors in the vast majority of attempts. The data is fully transmitted from the client's perspective, but the server rejects it.

Root cause: vsftpd 3.0.5 has a bug in its TLS 1.3 close_notify handling — when the client sends close_notify shortly after the last data record, the server's SSL_read() fails to read remaining data from its internal SSL buffers.

Fix: Replace pipeline with manual source.pipe(dataSocket, { end: false }). After the source stream ends, instead of calling dataSocket.end() (which sends TLS close_notify), we close the underlying TCP socket directly — bypassing the TLS layer entirely:

  1. During passive connection setup, the original plain TCP socket is saved as dataSocket._plainSocket before TLS wrapping.
  2. When the upload source ends, we wait for the drain event (if write buffer has backpressure) to ensure all encrypted data has been handed to the OS kernel.
  3. Then we call plainSocket.end(), which sends a TCP FIN without any TLS close_notify.
  4. The server's SSL_read() reads all application data normally, then encounters an EOF — which vsftpd handles correctly, returning 226 Transfer complete.

This approach is fully event-driven (no setTimeout) and avoids the problematic close_notify entirely. For non-TLS (plain FTP) connections, the normal dataSocket.end() is used as a fallback.

Affected Servers

This fix is primarily for vsftpd 3.0.5 with TLS 1.3 enabled, but the listener leak fix (Fix 1) benefits all FTPS connections.

Compatibility

  • API: 100% compatible with [email protected]
  • Node.js: >= 10.0.0
  • License: MIT (same as original)

Credits

Original library by Patrick Juchli.