projectdiscovery/nuclei · warning

mysql handshake missing filler byte

Error message

mysql handshake missing filler byte

What it means

In a protocol-10 handshake the server version is a NUL-terminated ASCII string starting at byte 5, followed by 13 fixed bytes (4-byte thread id + 8-byte salt part 1 + filler). The parser computes fillerPos = nullPos+13 and requires that position to exist in the packet; this error means the version string ran so long that the packet ended before the expected filler location — a structurally impossible real handshake.

Source

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

	// 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) {
	length := mysqlPacketLength(packet)
	if length+4 > len(packet) {
		length = len(packet) - 4
	}
	if length <= 0 {
		return
	}
	payload := packet[4 : 4+length]
	// versionEnd is absolute index of first byte after version NUL in packet.
	pos := versionEnd - 4

View on GitHub (pinned to 265b3a3dec)

Solutions

  1. Capture the greeting and check a NUL terminator appears within a plausible version length (< ~60 bytes)
  2. Verify with the mysql CLI that the server completes a real handshake
  3. Retry once to rule out truncation, then classify the port as non-MySQL
  4. If the server uses an unusually long version string, note this parser is fingerprintx-compatible by design and will reject it — use authenticated version queries instead
Defensive patterns

Strategy: try-catch

Try / catch

try { const info = mysql.FingerprintMySQL(host, port); }
catch (e) { if (String(e).includes('missing filler byte')) log('implausible handshake layout: ' + host); else throw e; }

Prevention

When it happens

Trigger: mysql.FingerprintMySQL against a stream that passed the 35-byte/25..4096/0x0a gates but whose 'version string' has no NUL soon enough — typically a non-MySQL byte stream whose early bytes coincidentally matched the gates, or a truncated greeting cut after the version bytes.

Common situations: Banner-echo services on 3306; custom daemons whose first bytes mimic a handshake; fuzzing corpora; MTU/truncation issues clipping long version strings (e.g. very long custom version_suffix builds).

Understand the failure class

Related errors


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