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 - 4View on GitHub (pinned to 265b3a3dec)
Solutions
- Capture the greeting and check a NUL terminator appears within a plausible version length (< ~60 bytes)
- Verify with the mysql CLI that the server completes a real handshake
- Retry once to rule out truncation, then classify the port as non-MySQL
- 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
- A missing filler means the 'version string' never terminated early enough — the stream is not a real greeting
- Retry once to rule out truncation, then classify the port as non-MySQL
- Validate with the mysql CLI client when a target must be MySQL
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
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- empty mysql greeting
- invalid mysql packet length %d
- mysql handshake packet too short
- mysql handshake packet length out of range
- unsupported mysql protocol version
AI-assisted analysis of projectdiscovery/nuclei@265b3a3dec (2026-08-15).
Data as JSON: /api/errors/b1b65332d489fd6e.
Report an issue: GitHub.