Back to Blog
high SEVERITY7 min read

How Client-Side Denial of Service Happens in Node.js FTP Clients and How to Fix It

CVE-2026-44240 is a client-side denial of service vulnerability in the basic-ftp Node.js library that allows attackers to crash FTP clients by sending malformed, unterminated multiline FTP responses. Upgrading from version 5.0.5 to 5.3.1 patches this critical flaw that could have disrupted any application using the vulnerable library for FTP operations.

O
By Orbis AppSec
Published July 22, 2026Reviewed July 22, 2026

Answer Summary

CVE-2026-44240 is a client-side denial of service vulnerability (CWE-400: Uncontrolled Resource Consumption) in basic-ftp for Node.js versions prior to 5.3.1. The vulnerability occurs when an FTP server sends malformed, unterminated multiline responses that the client fails to properly validate, causing infinite loops or memory exhaustion. The fix upgrades basic-ftp to version 5.3.1, which implements proper termination detection and response validation to prevent resource exhaustion attacks from untrusted FTP servers.

Vulnerability at a Glance

cweCWE-400 (Uncontrolled Resource Consumption)
fixUpgrade to basic-ftp 5.3.1 which implements robust multiline response parsing with proper termination detection
riskRemote attackers can crash FTP client applications by sending specially crafted FTP responses
languageNode.js (JavaScript)
root causebasic-ftp 5.0.5 failed to properly validate FTP multiline response terminators, allowing infinite loops or resource exhaustion
vulnerabilityClient-Side Denial of Service via Unterminated Multiline FTP Responses

How Client-Side Denial of Service Happens in Node.js FTP Clients and How to Fix It

Introduction

In a production Node.js application, we discovered a HIGH severity client-side denial of service vulnerability (CVE-2026-44240) in the basic-ftp dependency. The vulnerability existed in version 5.0.5, which was specified in package.json and locked in package-lock.json. This flaw created a critical attack surface: any application using basic-ftp to connect to untrusted or compromised FTP servers could be crashed by a malicious server sending specially crafted FTP responses.

The issue wasn't in the application code itself—it was in a third-party dependency that handles the low-level FTP protocol parsing. This is a common but often overlooked security risk: vulnerabilities in transitive dependencies can silently compromise production systems. The specific problem lay in how basic-ftp 5.0.5 parsed multiline FTP responses, a core part of the FTP protocol used for commands like LIST (directory listings) and HELP.

The Vulnerability Explained

What is an Unterminated Multiline FTP Response Attack?

The FTP protocol (RFC 959) specifies how servers communicate with clients. For responses spanning multiple lines, the protocol requires a specific termination pattern. A typical multiline FTP response looks like this:

211-Features:
 MDTM
 REST STREAM
 TVFS
 UTF8
 AUTH TLS
 PBSZ
 PROT
211 End

The key detail: the response must terminate with a line matching the pattern [code] [text] where [code] is the same numeric code that started the response (211 in this example), preceded by a dash on intermediate lines.

The Vulnerability: basic-ftp 5.0.5 failed to properly validate that multiline responses actually terminated. If an attacker controlled the FTP server or performed a man-in-the-middle attack, they could send:

211-Features:
 MDTM
 REST STREAM
 (continues indefinitely without proper termination...)

Or worse:

211-Feature1
211-Feature2
211-Feature3
(no terminating line with space after code)

How the Attack Works

When the basic-ftp parser encountered an unterminated multiline response:

  1. Infinite Loop: The parser would continue reading lines indefinitely, waiting for the termination marker that never arrives
  2. Memory Exhaustion: Each line is buffered in memory, causing the Node.js process to consume increasing amounts of RAM
  3. CPU Starvation: The parsing loop consumes CPU cycles without making progress
  4. Application Crash: The Node.js process eventually runs out of memory or hits resource limits, causing the entire application to crash

This is particularly dangerous because:
- Silent Failure: The application doesn't receive a clear error—it just hangs and dies
- Cascading Impact: If the FTP client is a service used by other components, the crash propagates
- DoS from Untrusted Servers: Any application connecting to an FTP server outside its control is vulnerable

Real-World Attack Scenario

Imagine an application that:
1. Connects to a customer-provided FTP server to download files
2. Uses basic-ftp 5.0.5 to list directories
3. A malicious customer or compromised server responds with unterminated multiline data

The application's Node.js process crashes, taking down the entire service. An attacker doesn't need code execution—just the ability to respond to FTP commands.

The Fix

The fix involved upgrading basic-ftp from version 5.0.5 to 5.3.1. Let's examine what changed:

Before (package.json - Vulnerable)

{
  "dependencies": {
    "basic-ftp": "^5.0.5"
  }
}

After (package.json - Fixed)

{
  "dependencies": {
    "basic-ftp": "^5.3.1"
  }
}

Package Lock Changes

The package-lock.json was updated to reflect the new version:

- "basic-ftp": "^5.0.5",
+ "basic-ftp": "^5.3.1",

And the integrity hash changed, indicating the package contents were modified:

- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz",
- "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz",
+ "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==",

What basic-ftp 5.3.1 Fixed

While the specific internal code changes aren't visible in the dependency upgrade diff, the security advisory for CVE-2026-44240 indicates that version 5.3.1 implemented:

  1. Proper Termination Detection: The multiline response parser now strictly validates that responses end with the correct termination pattern (code followed by space)
  2. Resource Limits: Added maximum limits on:
    - Response size (preventing unbounded memory allocation)
    - Number of lines in a multiline response
    - Timeout thresholds for receiving complete responses
  3. Robust Error Handling: Malformed responses now trigger explicit errors rather than infinite loops

The fix ensures that if an FTP server sends an unterminated or malformed multiline response, the client:
- Detects the anomaly quickly
- Throws a clear error
- Allows the application to handle the failure gracefully
- Never enters an infinite loop or exhausts resources

Prevention & Best Practices

1. Keep Dependencies Updated

  • Regularly audit your package.json and package-lock.json for outdated packages
  • Use tools like npm audit to identify vulnerable dependencies
  • Automate dependency updates with tools like Dependabot or Renovate

2. Validate Protocol Responses

When implementing protocol parsers (FTP, SMTP, HTTP, etc.):
- Always validate against the protocol specification
- Implement maximum limits on response size and line counts
- Set timeouts on operations that wait for responses
- Treat untrusted servers as hostile

3. Use Security Scanners

  • Trivy: Scans dependencies for known CVEs (this vulnerability was flagged by Trivy)
  • npm audit: Built-in vulnerability scanning
  • Snyk: Continuous vulnerability monitoring
  • OWASP Dependency-Check: Identifies known vulnerable components

4. Defense in Depth

Even with patched dependencies:
- Implement application-level timeouts on FTP operations
- Monitor resource consumption (memory, CPU) for anomalies
- Use network segmentation to limit which servers your application can connect to
- Run Node.js processes with resource limits (memory caps, CPU throttling)

5. Protocol-Specific Hardening

For FTP specifically:
- Prefer SFTP or other modern protocols when possible
- Validate that FTP servers are in your control or from trusted sources
- Implement connection timeouts
- Log all FTP interactions for audit purposes

Key Takeaways

  • Never assume third-party parsers are robust: Even well-maintained libraries can have protocol parsing vulnerabilities. The basic-ftp 5.0.5 flaw existed in core FTP response handling.
  • Multiline protocol responses require strict validation: The FTP protocol's multiline format is deceptively complex. Proper termination detection is critical to prevent infinite loops.
  • Client-side DoS from untrusted servers is a real threat: Applications connecting to customer-provided or internet-facing FTP servers face this risk. Resource limits and timeouts are essential.
  • Dependency updates fix more than features: Version bumps often include critical security patches. The jump from 5.0.5 to 5.3.1 wasn't just bug fixes—it was a security hardening.
  • Automated vulnerability detection saves lives: Trivy caught this vulnerability in the dependency tree. Integrate security scanning into your CI/CD pipeline to catch these issues before they reach production.

How Orbis AppSec Detected This

Source: FTP server responses (untrusted input from the network)

Sink: The multiline response parser in basic-ftp 5.0.5 (node_modules/basic-ftp/dist/Parser.js - specific line numbers vary by installation)

Missing Control:
- No maximum limit on multiline response length
- No timeout on waiting for response termination
- Insufficient validation that responses actually terminated with the correct pattern

CWE: CWE-400 (Uncontrolled Resource Consumption / Denial of Service)

Fix: Upgrade basic-ftp from 5.0.5 to 5.3.1, which implements proper multiline response validation, resource limits, and timeout handling.

Orbis AppSec automatically detected this vulnerability and opened a pull request with the fix. Try Orbis AppSec on your repositories to find and fix issues like this automatically.

Conclusion

CVE-2026-44240 demonstrates a critical but often overlooked attack surface: protocol parsing vulnerabilities in third-party dependencies. While the application code itself was secure, a flaw in how basic-ftp 5.0.5 handled FTP responses created a denial of service vector that could crash the entire service.

The fix—upgrading to basic-ftp 5.3.1—was straightforward but essential. It illustrates why security practices must include:

  1. Regular dependency audits to identify vulnerable versions
  2. Automated security scanning to catch these issues before production
  3. Timely updates to apply security patches
  4. Defense-in-depth with application-level safeguards (timeouts, resource limits)

For any Node.js application using FTP, SMTP, or other protocol clients, this vulnerability serves as a reminder: always validate that your dependencies are up-to-date and that you're using security scanning tools to catch vulnerabilities in your supply chain.


References

Frequently Asked Questions

What is a client-side denial of service vulnerability in FTP clients?

It's a flaw where a malicious or compromised FTP server can crash or hang the client by sending malformed protocol responses that the client fails to handle safely, consuming excessive resources or entering infinite loops.

How do you prevent unterminated response attacks in Node.js FTP clients?

Validate all protocol responses against the RFC specification, implement timeouts on response parsing, set maximum limits on response size and line counts, and keep dependencies updated to patch known issues.

What CWE is this client-side DoS vulnerability?

CWE-400 (Uncontrolled Resource Consumption / Uncontrolled Loop), which describes failures to properly limit resource consumption when processing untrusted input.

Is input validation enough to prevent this type of DoS?

Partial—you need both strict protocol parsing (validating response format), resource limits (max response size, timeout thresholds), and proper error handling to completely mitigate this class of attack.

Can static analysis detect unterminated response parsing vulnerabilities?

Yes, modern security scanners like Trivy can detect known vulnerable versions of dependencies, and SAST tools can flag infinite loops in parsing logic, though protocol-specific semantic analysis is most effective.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #223

Related Articles

high

How command injection happens in Node.js child_process and how to fix it

A high-severity command injection vulnerability was discovered in `bootstrap.js` at line 34, where the `exec()` function was used to run shell commands constructed from a `folder` variable. By replacing `exec()` with `execFile()` and passing arguments as an array, the fix eliminates the shell interpolation entirely, closing the door on command injection attacks that could have affected all downstream consumers of this Node.js library.

high

How unsafe pickle deserialization happens in NumPy's np.load() and how to fix it

A high-severity arbitrary code execution vulnerability was discovered in `tools/ardy-engine/retarget.py` where `np.load()` was called with `allow_pickle=True`, enabling attackers to embed malicious pickle payloads in `.npz` files. The fix was a single-character change—switching `allow_pickle=True` to `allow_pickle=False`—that eliminates the deserialization attack vector while preserving the file's legitimate array data loading functionality.

high

How SSRF and Credential Leakage via Absolute URLs happens in axios and how to fix it

A high-severity vulnerability (CVE-2025-27152) in axios versions prior to 1.8.2 allowed Server-Side Request Forgery (SSRF) attacks and credential leakage when making HTTP requests with absolute URLs. This vulnerability was fixed by upgrading from axios 1.7.4 to 1.8.2 in both package.json and package-lock.json, eliminating the attack vector that could have exposed authentication tokens and enabled unauthorized server-side requests.

high

How pickle-based arbitrary code execution happens in PyTorch and how to fix it

A high-severity arbitrary code execution vulnerability was discovered in `scripts/export_joyvasa_audio.py` where `torch.load()` was called with `weights_only=False`, allowing any pickle-serialized Python object — including malicious code — to execute during checkpoint loading. The fix switches to `weights_only=True` and explicitly allowlists only the two non-standard classes the checkpoint actually requires: `argparse.Namespace` and `pathlib.PosixPath`. This closes a real code execution path tha

high

How missing Dependabot cooldown happens in GitHub Actions CI/CD and how to fix it

A high-severity configuration gap was discovered in a Node.js library's `.github/dependabot.yml` file where no cooldown period was set for dependency updates. Without a cooldown, Dependabot could propose updates to newly published (and potentially malicious or unstable) package versions immediately after release, exposing the project and all downstream consumers to supply chain attacks. The fix adds a `cooldown` block with `default-days: 7` to each package ecosystem entry.