{"record":{"id":"a3214f86b0d83900","repo":"projectdiscovery/nuclei","slug":"mysql-handshake-filler-byte-is-not-zero","errorCode":null,"errorMessage":"mysql handshake filler byte is not zero","messagePattern":"mysql handshake filler byte is not zero","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":249,"sourceCode":"\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\n\tif pos < 0 || pos > len(payload) {\n\t\treturn\n\t}","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L231-L267","documentation":"Thrown by the MySQL fingerprint parser while decoding the server's initial handshake (greeting) packet. After reading the NUL-terminated server version string starting at offset 5, the parser expects the fingerprintx packet layout: 4-byte thread id, 8-byte auth-plugin-data part 1, and then a filler byte at nullPos+13 that must be 0x00. A non-zero byte at that position means the greeting does not match the MySQL wire format, so the fingerprint is rejected. The error propagates out of mysql.IsMySQL / FingerprintMySQL (and thus Connect / ExecuteQuery, which call IsMySQL first).","triggerScenarios":"Calling mysql.IsMySQL, mysql.FingerprintMySQL, mysql.Connect or mysql.ExecuteQuery against a TCP port where something answers with bytes but is not a real MySQL server (e.g. another database, a custom TCP service, or a proxy that rewrites the banner). Concretely: the version string parses fine, but packet[nullPos+13] != 0x00.","commonSituations":"Scanning a port list where 3306 is actually served by another protocol; MySQL-compatible forks or intermediaries that alter the greeting header layout; TLS-wrapped MySQL ports probed in plaintext producing a parseable-looking prefix but garbage filler byte; version-detection templates run against arbitrary open ports.","solutions":["Confirm the target is really MySQL on that port (e.g. `mysql -h host -P port -u x` or an nmap mysql probe) and fix the port in the template","Treat this error as 'not MySQL' in the template logic and continue scanning other ports — it is an expected probe outcome, not a bug","If the target should be MySQL, capture the raw greeting (hexdump the first packet) and verify byte 0 is protocol version 0x0a and a 0x00 filler exists 13 bytes after the version's NUL terminator","Check for transparent proxies / IPS devices between scanner and target that may rewrite the banner"],"exampleFix":"// before\nconst info = mysql.FingerprintMySQL('acme.com', 3306);\nlog(to_json(info)); // error kills the script on non-mysql targets\n\n// after\ntry {\n  const info = mysql.FingerprintMySQL('acme.com', 3306);\n  log(to_json(info));\n} catch (e) {\n  log('not a mysql service: ' + e); // keep scanning\n}","handlingStrategy":"try-catch","validationCode":"// cheap pre-check: read the greeting and verify MySQL protocol version 0x0a\nconst conn = net.Open('tcp', host + ':' + port);\nconst banner = conn.Recv(128);\nconn.Close();\nif (banner.charCodeAt(4) !== 0x0a) { log('not mysql, skip'); }","typeGuard":"function looksLikeMysqlGreeting(b) {\n  return b && b.length > 5 && b.charCodeAt(4) === 0x0a && b.indexOf('\\u0000', 5) !== -1;\n}","tryCatchPattern":"try {\n  const info = mysql.FingerprintMySQL(host, port);\n} catch (e) {\n  // any fingerprint parse error === treat as non-mysql, continue template\n  log('fingerprint rejected: ' + e);\n}","preventionTips":["Always gate mysql.Connect/ExecuteQuery behind mysql.IsMySQL","Treat fingerprint parse errors as negative probe results, never as template failures","Prefer the default port or a verified port map instead of probing arbitrary ports","Remember IsMySQL/FingerprintMySQL results are memoized per execution — one bad probe answer is cached"],"tags":["mysql","fingerprinting","protocol-parsing","network"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}