{"record":{"id":"c05a0b61bd8368c5","repo":"projectdiscovery/nuclei","slug":"unsupported-mysql-protocol-version","errorCode":null,"errorMessage":"unsupported mysql protocol version","messagePattern":"unsupported mysql protocol version","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":236,"sourceCode":"\tenrichMySQLHandshake(&info, packet, versionEnd)\n\treturn info, nil\n}\n\n// detectMySQLVersion mirrors fingerprintx CheckInitialHandshakePacket so we\n// accept the same greetings and always surface the server version string.\nfunc detectMySQLVersion(packet []byte) (string, int, error) {\n\tif len(packet) < 35 {\n\t\treturn \"\", 0, fmt.Errorf(\"mysql handshake packet too short\")\n\t}\n\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) {","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L218-L254","documentation":"The parser only accepts protocol version 10 (0x0a) — the handshake protocol spoken by MySQL 3.21+ through 8.x and MariaDB. This error means payload byte 0 (packet[4]) held a different value: an older protocol (9), a pre-handshake AUTH switch or ERR-adjacent frame, or simply a non-MySQL stream that passed the length gates. fingerprintx applies the identical check, so greetings it rejects are rejected here too.","triggerScenarios":"mysql.FingerprintMySQL against a service whose greeting passes length checks but starts with a byte other than 0x0a — e.g. protocol emulators, an alternate wire protocol on 3306, or a desynchronized stream where parsing begins mid-packet.","commonSituations":"Non-MySQL services on the MySQL port; MariaDB forks with experimental handshake tweaks; test fixtures with the version byte omitted; proxies shifting the byte stream.","solutions":["Read the raw greeting (nc host 3306 | xxd) and check the 5th byte is 0a","Confirm the server is stock MySQL/MariaDB with the mysql CLI client","Treat the failure as a negative detection and use generic probes","Ensure captures/fixtures include the full packet from the first length byte"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const likely = [3306, 33060, 3307].includes(port) || customDbPorts.has(port);\nif (!likely) return;","typeGuard":null,"tryCatchPattern":"try { const info = mysql.FingerprintMySQL(host, port); }\ncatch (e) { if (String(e).includes('unsupported mysql protocol version')) log('not protocol-10 mysql: ' + host); else throw e; }","preventionTips":["Only protocol 10 (0x0a) greetings are accepted by design — treat others as non-MySQL","Check the 5th byte of the raw banner when diagnosing","For exotic forks, use authenticated queries after login instead of the greeting fingerprint"],"tags":["mysql","protocol-parsing","fingerprint","version-mismatch","network","go"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}