{"record":{"id":"a6f0bbcc8a004f51","repo":"shadow1ng/fscan","slug":"mssql-truncated-prelogin-option","errorCode":null,"errorMessage":"mssql: truncated prelogin option","messagePattern":"mssql: truncated prelogin option","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/mssql_raw.go","lineNumber":181,"sourceCode":"\t}\n\tif _, ok := fields[tdsPreloginEncryption]; !ok {\n\t\treturn fmt.Errorf(\"mssql: prelogin response missing encryption field\")\n\t}\n\treturn nil\n}\n\nfunc mssqlParsePreloginFields(payload []byte) (map[byte][]byte, error) {\n\tfields := make(map[byte][]byte)\n\tfor pos := 0; ; pos += 5 {\n\t\tif pos >= len(payload) {\n\t\t\treturn nil, fmt.Errorf(\"mssql: invalid prelogin option table\")\n\t\t}\n\t\ttoken := payload[pos]\n\t\tif token == tdsPreloginTerminator {\n\t\t\treturn fields, nil\n\t\t}\n\t\tif pos+5 > len(payload) {\n\t\t\treturn nil, fmt.Errorf(\"mssql: truncated prelogin option\")\n\t\t}\n\t\toffset := int(binary.BigEndian.Uint16(payload[pos+1 : pos+3]))\n\t\tlength := int(binary.BigEndian.Uint16(payload[pos+3 : pos+5]))\n\t\tif offset < 0 || length < 0 || offset+length > len(payload) {\n\t\t\treturn nil, fmt.Errorf(\"mssql: invalid prelogin option bounds\")\n\t\t}\n\t\tfields[token] = payload[offset : offset+length]\n\t}\n}\n\nfunc mssqlSendLogin7(w io.Writer, host, username, password string) error {\n\tvalues := []struct {\n\t\ttext     string\n\t\tpassword bool\n\t}{\n\t\t{\"\", false},\n\t\t{username, false},\n\t\t{password, true},","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mssql_raw.go#L163-L199","documentation":"A prelogin option entry was started but fewer than 5 bytes remained in the payload, so the offset+length pair could not be read. Each non-terminator entry needs exactly 5 bytes: token (1) + offset (2) + length (2).","triggerScenarios":"mssqlParsePreloginFields finds a non-0xFF token at pos but pos+5 > len(payload) — e.g. 1–4 trailing bytes after the last complete entry.","commonSituations":"Packet truncation by network devices; partial reads being concatenated incorrectly; hand-crafted or fuzzed TDS responses.","solutions":["Capture the full packet and check whether the server truly sent a truncated table or a middlebox dropped bytes.","Retry against a known-good SQL Server to isolate server vs network.","If writing the peer side, ensure the option table is emitted fully before the value data.","Treat as protocol corruption: reconnect and log the raw payload for diagnosis."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := mssqlRawLogin(ctx, host, port, user, pass, timeout)\nif err != nil && strings.Contains(err.Error(), \"truncated prelogin option\") {\n    // packet ended mid-option: retry or capture traffic\n}","preventionTips":["Retry transient truncations before alarming.","Use packet captures to distinguish server bugs from middlebox drops.","Keep timeouts generous enough to receive full packets."],"tags":["mssql","tds","prelogin","malformed-data"],"backgroundTag":"invalid-argument-format","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}