{"record":{"id":"169f7f193ccfdaa1","repo":"projectdiscovery/nuclei","slug":"invalid-string-offset","errorCode":null,"errorMessage":"invalid string offset","messagePattern":"invalid string offset","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mysql/fingerprint.go","lineNumber":361,"sourceCode":"\tif caps&clientPluginAuth != 0 && pos < len(payload) {\n\t\tif plugin, _, err := readNullTerminatedASCIIString(payload, pos); err == nil {\n\t\t\tinfo.AuthPluginName = plugin\n\t\t}\n\t}\n}\n\nfunc mysqlPacketLength(packet []byte) int {\n\tif len(packet) < 3 {\n\t\treturn 0\n\t}\n\treturn int(uint32(packet[0]) | uint32(packet[1])<<8 | uint32(packet[2])<<16)\n}\n\n// 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","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mysql/fingerprint.go#L343-L379","documentation":"Thrown by readNullTerminatedASCIIString when its start offset is negative or beyond the end of the buffer. In the MySQL fingerprint flow it is called with start=5 (right after the 4-byte packet header), so this fires when the received handshake packet payload is shorter than 6 bytes — the greeting is too truncated to even contain a version string. It propagates out of IsMySQL / FingerprintMySQL / Connect / ExecuteQuery.","triggerScenarios":"The remote service accepts the TCP connection but sends fewer than 6 payload bytes before closing or before the fingerprint read timeout expires; or sends nothing and the reader times out with a partial/empty buffer. Typical with wrappers, honeypots, or services that immediately close on unknown clients.","commonSituations":"Probing firewalled ports that accept connections then drop; services that expect a client hello first (so they send no greeting) and time out; network middleboxes truncating responses; very slow servers where the fingerprint timeout hits mid-banner.","solutions":["Verify the port actually speaks MySQL server-first protocol (MySQL sends the greeting before the client sends anything)","Retry against the canonical MySQL port 3306 to rule out port confusion","If the target needs a client hello first (or is TLS-wrapped), this library cannot fingerprint it — use the code protocol with a raw net connection instead","Increase network timeouts / check for packet-dropping middleboxes if the target is a known MySQL server"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// confirm the service sends at least a header + version byte before probing\nconst conn = net.Open('tcp', host + ':' + port);const b = conn.Recv(16);\nconn.Close();\nif (!b || b.length < 6) { log('no greeting, skip mysql probe'); }","typeGuard":"function hasMinimumGreeting(b) {\n  return typeof b === 'string' && b.length >= 6;\n}","tryCatchPattern":"try {\n  mysql.IsMySQL(host, port);\n} catch (e) {\n  if (String(e).includes('invalid string offset')) { /* truncated greeting: not usable, skip */ }\n  else { throw e; }\n}","preventionTips":["Probe only ports known/likely to be MySQL server-first services","Handle truncated-greeting errors as skip, not retry storms","For TLS-wrapped MySQL, probe over TLS instead of plaintext","Raise scan timeouts if targets are known-slow and truncation is suspected"],"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"}