{"record":{"id":"b1b65332d489fd6e","repo":"projectdiscovery/nuclei","slug":"mysql-handshake-missing-filler-byte","errorCode":null,"errorMessage":"mysql handshake missing filler byte","messagePattern":"mysql handshake missing filler byte","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":246,"sourceCode":"\n\t// fingerprintx treats bytes[0:4] as little-endian length (seq usually 0).\n\t// Use the real 3-byte MySQL length for bounds, but keep the same 25..4096 gate.\n\tlength := mysqlPacketLength(packet)\n\tif length < 25 || length > 4096 {\n\t\treturn \"\", 0, fmt.Errorf(\"mysql handshake packet length out of range\")\n\t}\n\tif packet[4] != mysqlProtocolVersion10 {\n\t\treturn \"\", 0, fmt.Errorf(\"unsupported mysql protocol version\")\n\t}\n\n\tversion, nullPos, err := readNullTerminatedASCIIString(packet, 5)\n\tif err != nil {\n\t\treturn \"\", 0, err\n\t}\n\t// nullPos points at the NUL; fingerprintx filler is at nullPos+13.\n\tfillerPos := nullPos + 13\n\tif fillerPos >= len(packet) {\n\t\treturn \"\", 0, fmt.Errorf(\"mysql handshake missing filler byte\")\n\t}\n\tif packet[fillerPos] != 0x00 {\n\t\treturn \"\", 0, fmt.Errorf(\"mysql handshake filler byte is not zero\")\n\t}\n\treturn version, nullPos + 1, nil\n}\n\nfunc enrichMySQLHandshake(info *HandshakeInfo, packet []byte, versionEnd int) {\n\tlength := mysqlPacketLength(packet)\n\tif length+4 > len(packet) {\n\t\tlength = len(packet) - 4\n\t}\n\tif length <= 0 {\n\t\treturn\n\t}\n\tpayload := packet[4 : 4+length]\n\t// versionEnd is absolute index of first byte after version NUL in packet.\n\tpos := versionEnd - 4","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L228-L264","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { const info = mysql.FingerprintMySQL(host, port); }\ncatch (e) { if (String(e).includes('missing filler byte')) log('implausible handshake layout: ' + host); else throw e; }","preventionTips":["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"],"tags":["mysql","protocol-parsing","fingerprint","bounds-check","network","go"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}