{"record":{"id":"c6ca2d4b6ee0e36d","repo":"projectdiscovery/nuclei","slug":"unterminated-mysql-string","errorCode":null,"errorMessage":"unterminated mysql string","messagePattern":"unterminated mysql string","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":375,"sourceCode":"// readNullTerminatedASCIIString mirrors fingerprintx: printable ASCII only,\n// returns the index of the NUL terminator (not the next byte).\nfunc readNullTerminatedASCIIString(buf []byte, start int) (string, int, error) {\n\tif start < 0 || start >= len(buf) {\n\t\treturn \"\", 0, fmt.Errorf(\"invalid string offset\")\n\t}\n\tvar characters []byte\n\tfor position := start; position < len(buf); position++ {\n\t\tc := buf[position]\n\t\tif c >= 0x20 && c <= 0x7e {\n\t\t\tcharacters = append(characters, c)\n\t\t\tcontinue\n\t\t}\n\t\tif c == 0x00 {\n\t\t\treturn string(characters), position, nil\n\t\t}\n\t\treturn \"\", 0, fmt.Errorf(\"encountered invalid ASCII character\")\n\t}\n\treturn \"\", 0, fmt.Errorf(\"unterminated mysql string\")\n}\n\nfunc readPrintableASCII(buf []byte) string {\n\tvar characters []byte\n\tfor _, c := range buf {\n\t\tif c >= 0x20 && c <= 0x7e {\n\t\t\tcharacters = append(characters, c)\n\t\t}\n\t}\n\treturn string(characters)\n}\n\nfunc bytesTrimRightNull(b []byte) []byte {\n\tfor len(b) > 0 && b[len(b)-1] == 0x00 {\n\t\tb = b[:len(b)-1]\n\t}\n\treturn b\n}","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L357-L393","documentation":"Thrown by readNullTerminatedASCIIString when it scans to the end of the handshake packet without ever finding the 0x00 terminator for the server version string. A valid MySQL greeting always NUL-terminates its version, so an unterminated run of printable bytes means the buffer is truncated or the payload is not a greeting. It propagates out of IsMySQL / FingerprintMySQL / Connect / ExecuteQuery.","triggerScenarios":"The read deadline (mysqlFingerprintTimeout) expires mid-banner leaving a partial packet; the server sends a banner with no NUL inside the received window; or a non-MySQL service streams printable text (e.g. an HTTP banner or SMTP greeting) that never terminates within the buffer.","commonSituations":"Slow or heavily loaded MySQL servers whose greeting is split across TCP segments with only the first part read; services that keep the connection open and send continuous text; MTU/fragmentation issues or middleboxes clipping packets.","solutions":["If the target is a known MySQL server, retry when the network is less loaded and check for MTU/firewall truncation","Confirm the port serves MySQL (server-first greeting, version NUL-terminated)","Treat as 'not MySQL' in template logic — this is a probe failure, not a scanner defect","Compare with a manual read: `net.Open('tcp','host:port')` + Recv and inspect whether the version string ends with a 0x00 byte"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify the version string is NUL-terminated within the first bytes\nconst conn = net.Open('tcp', host + ':' + port);\nconst b = conn.Recv(64);\nconn.Close();\nif (b.indexOf('\\u0000', 5) === -1) { log('no NUL terminator, skip'); }","typeGuard":"function isNulTerminatedAt(b) {\n  return b.indexOf('\\u0000', 5) !== -1;\n}","tryCatchPattern":"try {\n  mysql.FingerprintMySQL(host, port);\n} catch (e) {\n  if (String(e).includes('unterminated mysql string')) { /* truncated/greeting-less: skip */ }\n  else { throw e; }\n}","preventionTips":["Expect truncated banners on slow links; treat as skip","Avoid pointing the mysql lib at streaming/text services","Reuse one raw pre-read to validate greeting shape before all mysql calls","Retry manually with longer timeouts only for known-good MySQL targets"],"tags":["mysql","fingerprinting","truncated-response","network"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}