projectdiscovery/nuclei · warning

unsupported mysql protocol version

Error message

unsupported mysql protocol version

What it means

The parser only accepts protocol version 10 (0x0a) — the handshake protocol spoken by MySQL 3.21+ through 8.x and MariaDB. This error means payload byte 0 (packet[4]) held a different value: an older protocol (9), a pre-handshake AUTH switch or ERR-adjacent frame, or simply a non-MySQL stream that passed the length gates. fingerprintx applies the identical check, so greetings it rejects are rejected here too.

Source

Thrown at pkg/js/libs/mysql/fingerprint.go:236

	enrichMySQLHandshake(&info, packet, versionEnd)
	return info, nil
}

// detectMySQLVersion mirrors fingerprintx CheckInitialHandshakePacket so we
// accept the same greetings and always surface the server version string.
func detectMySQLVersion(packet []byte) (string, int, error) {
	if len(packet) < 35 {
		return "", 0, fmt.Errorf("mysql handshake packet too short")
	}

	// fingerprintx treats bytes[0:4] as little-endian length (seq usually 0).
	// Use the real 3-byte MySQL length for bounds, but keep the same 25..4096 gate.
	length := mysqlPacketLength(packet)
	if length < 25 || length > 4096 {
		return "", 0, fmt.Errorf("mysql handshake packet length out of range")
	}
	if packet[4] != mysqlProtocolVersion10 {
		return "", 0, fmt.Errorf("unsupported mysql protocol version")
	}

	version, nullPos, err := readNullTerminatedASCIIString(packet, 5)
	if err != nil {
		return "", 0, err
	}
	// nullPos points at the NUL; fingerprintx filler is at nullPos+13.
	fillerPos := nullPos + 13
	if fillerPos >= len(packet) {
		return "", 0, fmt.Errorf("mysql handshake missing filler byte")
	}
	if packet[fillerPos] != 0x00 {
		return "", 0, fmt.Errorf("mysql handshake filler byte is not zero")
	}
	return version, nullPos + 1, nil
}

func enrichMySQLHandshake(info *HandshakeInfo, packet []byte, versionEnd int) {

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Read the raw greeting (nc host 3306 | xxd) and check the 5th byte is 0a
  2. Confirm the server is stock MySQL/MariaDB with the mysql CLI client
  3. Treat the failure as a negative detection and use generic probes
  4. Ensure captures/fixtures include the full packet from the first length byte
Defensive patterns

Strategy: try-catch

Validate before calling

const likely = [3306, 33060, 3307].includes(port) || customDbPorts.has(port);
if (!likely) return;

Try / catch

try { const info = mysql.FingerprintMySQL(host, port); }
catch (e) { if (String(e).includes('unsupported mysql protocol version')) log('not protocol-10 mysql: ' + host); else throw e; }

Prevention

When it happens

Trigger: mysql.FingerprintMySQL against a service whose greeting passes length checks but starts with a byte other than 0x0a — e.g. protocol emulators, an alternate wire protocol on 3306, or a desynchronized stream where parsing begins mid-packet.

Common situations: Non-MySQL services on the MySQL port; MariaDB forks with experimental handshake tweaks; test fixtures with the version byte omitted; proxies shifting the byte stream.

Related errors


AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15). Data as JSON: /api/errors/c05a0b61bd8368c5. Report an issue: GitHub.