{"record":{"id":"8eba2fdcd18e8cd6","repo":"shadow1ng/fscan","slug":"mssql-invalid-prelogin-option-bounds","errorCode":null,"errorMessage":"mssql: invalid prelogin option bounds","messagePattern":"mssql: invalid prelogin option bounds","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/mssql_raw.go","lineNumber":186,"sourceCode":"}\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},\n\t\t{\"\", false},\n\t\t{\"\", false},\n\t\t{\"\", false},\n\t\t{\"\", false},\n\t\t{\"master\", false},","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mssql_raw.go#L168-L204","documentation":"A prelogin option entry declared an offset/length pair whose value range falls outside the payload (offset+length > len(payload) or negative values). The option table points to data that is not present in the packet.","triggerScenarios":"mssqlParsePreloginFields reads a 5-byte entry whose decoded offset/length exceed the payload bounds when slicing payload[offset:offset+length].","commonSituations":"Corrupted packets in transit; malicious or buggy TDS endpoints; a proxy that rewrites payload length but not the option table offsets.","solutions":["Verify packet integrity end-to-end with a capture; retransmit if corruption is transient.","Check any TDS proxy/gateway for offset-rewriting bugs.","Harden the client by logging offset, length, and payload size when this fires.","Confirm the endpoint is genuine SQL Server; arbitrary services can send arbitrary garbage."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"_, err := mssqlRawLogin(ctx, host, port, user, pass, timeout)\nif err != nil && strings.Contains(err.Error(), \"invalid prelogin option bounds\") {\n    // offsets point outside payload: corrupt/malicious peer; mark endpoint untrusted\n}","preventionTips":["Treat repeated bounds errors as a sign of a non-SQL-Server or hostile endpoint.","Log offset/length/payload-size to diagnose rewriting proxies.","Only probe endpoints you control or trust."],"tags":["mssql","tds","prelogin","malformed-data","bounds"],"backgroundTag":"value-out-of-range","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"}