chore(deps): update dependency basic-ftp@<5.2.0 to v5.3.1 [security]#6358
Open
renovate[bot] wants to merge 1 commit into
Open
chore(deps): update dependency basic-ftp@<5.2.0 to v5.3.1 [security]#6358renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
5.3.0→5.3.1basic-ftp allows a malicious FTP server to cause client-side denial of service via unbounded multiline control response buffering
CVE-2026-44240 / GHSA-rpmf-866q-6p89
More information
Details
Summary
basic-ftpis vulnerable to client-side denial of service when parsing FTP control-channel multiline responses.A malicious or compromised FTP server can send an unterminated multiline response during the initial FTP banner phase, before authentication. The client keeps appending attacker-controlled data into
FtpContext._partialResponseand repeatedly reparses the accumulated buffer without enforcing a maximum control response size.As a result, an application using
basic-ftpcan remain stuck inconnect()while memory and CPU usage grow under attacker-controlled input. This can lead to process-level denial of service, container OOM kills, worker restarts, queue backlog, or service degradation in applications that automatically connect to FTP endpoints.Details
Root cause
The root cause is that incomplete FTP multiline control responses are buffered without an upper bound.
FtpContextstores incomplete control-channel data in_partialResponse:https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/FtpContext.ts#L63-L64
Incoming control-channel data is handled in
_onControlSocketData. The implementation concatenates the previous incomplete response with the new chunk, parses the entire accumulated string, and storesparsed.restback into_partialResponse:https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/FtpContext.ts#L328-L340
The relevant flow is:
completeResponse = this._partialResponse + chunk
parsed = parseControlResponse(completeResponse)
this._partialResponse = parsed.rest
There is no maximum size check before concatenating, before parsing, or before storing
parsed.rest.The parser accepts incomplete multiline responses and returns the entire unterminated multiline group as
rest:https://github.com/patrickjuchli/basic-ftp/blob/50827c73ca6c1d786c97276e47be8a33d0f2277d/src/parseControlResponse.ts#L15-L43
If a server starts a multiline FTP response:
220-malicious banner starts
but never sends the terminating line:
220 ready
then
parseControlResponse()treats the accumulated multiline data as incomplete and returns it asrest.Because
_onControlSocketData()feeds_partialResponse + chunkback into the parser on every new data event, the client repeatedly reparses a growing attacker-controlled buffer. This creates both memory growth and increasing parsing work.Why this is security-relevant
The vulnerable component is a client library. The attacker does not need to authenticate to the victim system and does not need valid FTP credentials.
The attack occurs automatically when an application using
basic-ftpconnects to a malicious or compromised FTP server. The malicious response is sent as the FTP server banner before login. No additional user interaction is required after the application initiates a normal FTP connection.This is realistic for applications that use FTP for:
In those environments, one malicious or compromised FTP endpoint can cause the Node.js process using
basic-ftpto consume excessive memory and CPU or remain stuck in a pending connection state.Proof of Concept
The PoC uses a local malicious FTP server that accepts a victim connection and sends an unterminated multiline FTP banner. The banner starts with
220-, but the server never sends the required terminating220line.Reproduction steps
From the root of the
basic-ftpproject:poc_control_parser_direct.js
CHUNKS=1000 node poc_control_parser_direct.js | tee poc-results/parser_direct_1000.logparser_direct_1000.log
Run the end-to-end malicious FTP server PoC:
poc_control_multiline_dos.js
CHUNK_SIZE=8192 CHUNKS=1000 DELAY_MS=1 node poc_control_multiline_dos.js | tee poc-results/control_multiline_dos_1000.logcontrol_multiline_dos_1000.log
Observed result: parser-only PoC
This shows that
parseControlResponse()retained the full unterminated multiline response asrest.The retained buffer grew to
7.81 MiB. Heap usage increased from3.69 MiBto80.77 MiB, and RSS increased from54.77 MiBto141.64 MiB.Observed result: end-to-end malicious FTP server PoC
Only
7.8 MiBof malicious control-channel data was sent. The client retained7.8 MiBin_partialResponse, showed large memory spikes, and remained pending insideconnect()because the multiline response was never terminated.Expected behavior
The client should enforce a maximum size for incomplete FTP control responses. If the accumulated multiline response exceeds a safe limit, the client should close the connection and reject the active task with an error.
The client should not allow a remote FTP server to make
_partialResponsegrow without bound.Actual behavior
A malicious FTP server can keep the client in a pending connection state by sending an unterminated multiline control response.
basic-ftpcontinues buffering and reparsing the accumulated data without a maximum response size.Impact
A malicious or compromised FTP server can cause denial of service in applications using
basic-ftp.Possible real-world impact includes:
Threat model
The attacker controls, compromises, or can impersonate an FTP server that a victim application connects to.
Examples:
In each case, the victim application initiates a normal FTP connection. The malicious server sends an unterminated multiline banner before authentication. The vulnerable client then buffers and reparses the response indefinitely.
No FTP credentials are required for exploitation because the attack happens before login.
Suggested fix
Introduce a maximum control response buffer size, especially for incomplete multiline responses.
Recommended changes:
maxControlResponseBytesormaxControlResponseLengthlimit.Example defensive logic:
A regression test should verify that a response beginning with
220-and never terminating with220is rejected after the configured size limit instead of being retained indefinitely.Suggested regression test scenario
A test server should:
220-malicious banner\r\n.220line._partialResponsedoes not grow without bound.Credit request
If you publish an advisory or assign a CVE, please credit me as:
Ali Firas (thesmartshadow) - https://www.smartshadow.dev
Severity
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:HReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
patrickjuchli/basic-ftp (basic-ftp@<5.2.0)
v5.3.1Compare Source
Configuration
📅 Schedule: (UTC)
🚦 Automerge: Enabled.
♻ 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.
This PR was generated by Mend Renovate. View the repository job log.