{"record":{"id":"028ce86df6e08dd7","repo":"projectdiscovery/nuclei","slug":"unexpected-tds-type-0x-02x","errorCode":null,"errorMessage":"unexpected TDS type 0x%02x","messagePattern":"unexpected TDS type 0x%02x","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/js/libs/mssql/fingerprint.go","lineNumber":184,"sourceCode":"\ntype preloginData struct {\n\tVersion         string\n\tMajorVersion    int\n\tMinorVersion    int\n\tBuildNumber     int\n\tEncryption      int\n\tEncryptionMode  string\n\tMars            bool\n\tInstanceMatches bool\n}\n\nfunc parsePreloginResponse(response []byte) (preloginData, error) {\n\tvar out preloginData\n\tif len(response) < 8 {\n\t\treturn out, fmt.Errorf(\"response too short for TDS header\")\n\t}\n\tif response[0] != tdsTypeTabularResult {\n\t\treturn out, fmt.Errorf(\"unexpected TDS type 0x%02x\", response[0])\n\t}\n\tif response[1] != tdsStatusEOM {\n\t\treturn out, fmt.Errorf(\"unexpected TDS status 0x%02x\", response[1])\n\t}\n\tpacketLength := int(binary.BigEndian.Uint16(response[2:4]))\n\tif len(response) != packetLength {\n\t\treturn out, fmt.Errorf(\"packet length mismatch: header=%d body=%d\", packetLength, len(response))\n\t}\n\n\ttype optionToken struct {\n\t\ttoken  byte\n\t\toffset uint16\n\t\tlength uint16\n\t\tdata   []byte\n\t}\n\n\tposition := 8\n\tvar tokens []optionToken","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/projectdiscovery/nuclei/blob/265b3a3dec374741614e342f813c10f8b38d2bb7/pkg/js/libs/mssql/fingerprint.go#L166-L202","documentation":"Returned by parsePreloginResponse when the first response byte is not 0x04 (TDSTYPE_TABULARRESULT, the packet type a pre-login reply must use), wrapped into errNotMssql by FingerprintMssql. A TDS pre-login response starts 04 01; any other leading byte means the reply is a different packet type or a different protocol entirely.","triggerScenarios":"Server answers with a TLS record (first byte 0x16 handshake / 0x15 alert) because encryption is forced from byte zero; an HTTP response (letter bytes) on the probed port; any non-MSSQL banner whose length field happened to be >= 8.","commonSituations":"Probing a port in front of a TLS terminator; SQL Server configured with force encryption behind some proxies; scanning mixed services on a port range and hitting SSH/HTTP first bytes.","solutions":["Interpret as 'not MSSQL (or TLS-wrapped)': fall back to mssql.IsMssql or skip the target","If MSSQL is expected, verify the port is the direct SQL TCP port and not a TLS frontend; try the TLS dial variant if available","Compare the first byte heuristics in the template (0x16 => TLS, 0x04 => TDS) before fingerprinting"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const info = mssql.FingerprintMssql(host, port);\n} catch (e) {\n  if (String(e).includes('not a mssql service')) return; // wrong protocol on this port\n  throw e;\n}","preventionTips":["Expect TLS-first listeners (byte 0x16) to fail this check; probe the correct port instead","Use IsMssql for boolean service classification","When authoring detection logic, branch on the raw first byte before deep fingerprinting"],"tags":["mssql","protocol","tds","fingerprinting","service-detection"],"backgroundTag":null,"analyzedSha":"265b3a3dec374741614e342f813c10f8b38d2bb7","analyzedAt":"2026-08-15T20:05:51.855Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}