{"record":{"id":"54caddd4da9cc9f6","repo":"projectdiscovery/nuclei","slug":"empty-mysql-greeting","errorCode":null,"errorMessage":"empty mysql greeting","messagePattern":"empty mysql greeting","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":137,"sourceCode":"\tCapabilities      []string `json:\"capabilities,omitempty\"`\n\tCharacterSet      uint8    `json:\"characterSet,omitempty\"`\n\tStatusFlags       uint16   `json:\"statusFlags,omitempty\"`\n\tStatus            []string `json:\"status,omitempty\"`\n\tAuthPluginDataLen int      `json:\"authPluginDataLen,omitempty\"`\n\tSalt              string   `json:\"salt,omitempty\"`\n\tAuthPluginName    string   `json:\"authPluginName,omitempty\"`\n\tErrorMessage      string   `json:\"errorMsg,omitempty\"`\n\tErrorCode         int      `json:\"errorCode,omitempty\"`\n}\n\n// fingerprintConn reads the MySQL greeting once and parses an extended fingerprint.\nfunc fingerprintConn(conn net.Conn, timeout time.Duration) (HandshakeInfo, error) {\n\traw, err := recvMySQLPacket(conn, timeout)\n\tif err != nil {\n\t\treturn HandshakeInfo{}, err\n\t}\n\tif len(raw) == 0 {\n\t\treturn HandshakeInfo{}, fmt.Errorf(\"empty mysql greeting\")\n\t}\n\treturn parseMySQLGreeting(raw)\n}\n\nfunc recvMySQLPacket(conn net.Conn, timeout time.Duration) ([]byte, error) {\n\tif err := conn.SetReadDeadline(time.Now().Add(timeout)); err != nil {\n\t\treturn nil, err\n\t}\n\theader := make([]byte, 4)\n\tif _, err := io.ReadFull(conn, header); err != nil {\n\t\treturn nil, err\n\t}\n\tlength := int(uint32(header[0]) | uint32(header[1])<<8 | uint32(header[2])<<16)\n\tif length <= 0 || length > 16*1024*1024 {\n\t\treturn nil, fmt.Errorf(\"invalid mysql packet length %d\", length)\n\t}\n\tpayload := make([]byte, length)\n\tif _, err := io.ReadFull(conn, payload); err != nil {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L119-L155","documentation":"fingerprintConn reads one MySQL packet with recvMySQLPacket and then guards against a zero-length result before parsing. recvMySQLPacket already fails on short reads and rejects payload lengths <= 0, so this branch is a defensive invariant: a non-error empty read should be impossible on the wire path. Seeing it means an empty greeting buffer reached the parser — from tests calling parseMySQLGreeting directly or a future code path that bypasses the length gate.","triggerScenarios":"mssql-style FingerprintMySQL flows (mysql.FingerprintMySQL(host, port) via fingerprintConn) where the read layer yields zero bytes without error, or Go unit tests invoking parseMySQLGreeting with an empty slice.","commonSituations":"Mostly a library-internal invariant; realistically surfaces in fuzzing or when the conn deadline expires exactly between header and payload in a way that returns no data.","solutions":["If hit from JS, treat as 'target did not send a MySQL greeting' and fall back to generic service detection","Retry the fingerprint once — transient deadline races can drop the read","Check the port with nmap -sV to see whether MySQL is actually listening","If reproducing in Go tests, ensure the fixture packet has a valid 4-byte header with a positive payload length"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (!mysql.IsMySQL || !mysql.IsMySQL(host, port)) { /* probe first when available */ }","typeGuard":null,"tryCatchPattern":"try { const info = mysql.FingerprintMySQL(host, port); }\ncatch (e) { log('no mysql greeting from ' + host + ': ' + e); }","preventionTips":["Treat an empty greeting as a non-MySQL port","Retry once to rule out deadline races, then move on","Restrict mysql fingerprints to likely-database ports (3306, 33060, custom DB ports)"],"tags":["mysql","protocol-parsing","fingerprint","empty-response","network","go"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}