projectdiscovery/nuclei · warning

mysql handshake packet length out of range

Error message

mysql handshake packet length out of range

What it means

Beyond the 35-byte floor, the declared 3-byte payload length must lie in 25..4096 — the same gate fingerprintx applies to initial handshake packets. This error means the length field decoded below 25 (a handshake cannot fit) or above 4096 (no real greeting is that large), so the packet is not a credible MySQL handshake. It is raised by detectMySQLVersion and propagates out of FingerprintMySQL as a fingerprint failure.

Source

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

	}

	// Phase 2: best-effort enrichment. Failures here must not drop Version.
	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

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Verify the service with nmap -sV or a manual banner read before fingerprinting
  2. Confirm you reached the database directly, not through a proxy that prepends bytes
  3. If TLS is enforced on the MySQL port, use an SSL/TLS probe instead of the mysql fingerprint
  4. Wrap FingerprintMySQL in try/catch in the template and continue on failure
Defensive patterns

Strategy: try-catch

Validate before calling

// restrict fingerprinting to known-database ports to avoid non-mysql byte streams
if (!isLikelyDbPort(port)) { log('skip mysql fingerprint on ' + port); return; }

Try / catch

try { const info = mysql.FingerprintMySQL(host, port); }
catch (e) { if (String(e).includes('packet length out of range')) log('non-mysql stream on ' + host + ':' + port); else throw e; }

Prevention

When it happens

Trigger: mysql.FingerprintMySQL against services whose first three bytes decode outside 25..4096 — common for non-MySQL protocols (HTTP, Redis 'RED', TLS records) — or a corrupted/shifted stream where the length is read from the wrong offset.

Common situations: Broad port scans hitting mysql templates on everything that answers; proxies inserting preamble bytes; pcap-replay fixtures missing the first bytes so the stream is desynchronized.

Understand the failure class

Related errors


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