{"record":{"id":"f131d00e807767f9","repo":"shadow1ng/fscan","slug":"mssql-invalid-string-in-error-token","errorCode":null,"errorMessage":"mssql: invalid string in error token","messagePattern":"mssql: invalid string in error token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/mssql_raw.go","lineNumber":374,"sourceCode":"\t}\n\tsize := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\n\tend := pos + 2 + size\n\tif size < 6 || end > len(payload) || pos+8 > len(payload) {\n\t\treturn pos, fmt.Errorf(\"mssql: invalid info token size\")\n\t}\n\t_, _, err := mssqlReadUSVarChar(payload, pos+8)\n\treturn end, err\n}\n\nfunc mssqlEnsureSkipBVarStrings(payload []byte, pos, end int) error {\n\tfor i := 0; i < 2; i++ {\n\t\tif pos >= end {\n\t\t\treturn fmt.Errorf(\"mssql: truncated string in error token\")\n\t\t}\n\t\tlength := int(payload[pos]) * 2\n\t\tpos++\n\t\tif pos+length > end {\n\t\t\treturn fmt.Errorf(\"mssql: invalid string in error token\")\n\t\t}\n\t\tpos += length\n\t}\n\tif pos+4 > end {\n\t\treturn fmt.Errorf(\"mssql: truncated error line number\")\n\t}\n\treturn nil\n}\n\nfunc mssqlSkipLen16(payload []byte, pos int) (int, error) {\n\tif pos+2 > len(payload) {\n\t\treturn pos, fmt.Errorf(\"mssql: truncated token\")\n\t}\n\tsize := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\n\tnext := pos + 2 + size\n\tif next > len(payload) {\n\t\treturn pos, fmt.Errorf(\"mssql: invalid token size\")\n\t}","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mssql_raw.go#L356-L392","documentation":"While skipping the BVarChar strings in an ERROR token, mssqlEnsureSkipBVarStrings read a 1-byte character count whose doubled byte-length extends beyond the token end (pos+length > end). The declared string does not fit inside the token, so the library throws instead of reading out of bounds.","triggerScenarios":"An ERROR token's BVarChar length byte claims a string larger than the remaining bytes between pos and the token end.","commonSituations":"Fuzzed or hostile server sends an inflated length byte; byte corruption in transit (e.g. a proxy mangling UTF-16 strings); TDS protocol mismatch producing misaligned length fields.","solutions":["Hex-dump the offending packet and compare the string length byte against the token size.","Retry the connection to rule out transient corruption.","Bypass or update any proxy/TLS terminator that may be rewriting payload bytes.","Abort parsing this response; never trust the remaining token stream after a framing violation."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"length := int(payload[pos]) * 2\nif pos+1+length > end {\n    return fmt.Errorf(\"BVarChar length %d exceeds token end %d\", length, end)\n}","typeGuard":null,"tryCatchPattern":"if err := mssqlEnsureSkipBVarStrings(payload, pos, end); err != nil {\n    conn.Close()\n    return fmt.Errorf(\"ERROR token string out of bounds: %w\", err)\n}","preventionTips":["Never trust length bytes; always check pos+length <= end before advancing.","Use TLS to prevent in-transit byte corruption of string lengths.","Add structured fuzz tests with inflated BVarChar lengths.","Pin the negotiated TDS version so token layouts stay consistent."],"tags":["mssql","tds-protocol","malformed-packet","wire-parsing"],"backgroundTag":"unexpected-api-response-shape","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"}