{"record":{"id":"4bf38f8aa49807a0","repo":"shadow1ng/fscan","slug":"mssql-invalid-error-token-size","errorCode":null,"errorMessage":"mssql: invalid error token size","messagePattern":"mssql: invalid error token size","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/services/mssql_raw.go","lineNumber":340,"sourceCode":"\t\t\t\treturn false, fmt.Errorf(\"mssql: truncated done token\")\n\t\t\t}\n\t\t\tstatus := binary.LittleEndian.Uint16(payload[pos : pos+2])\n\t\t\treturn status&(tdsDoneError|tdsDoneSrvError) == 0, nil\n\t\tdefault:\n\t\t\treturn false, fmt.Errorf(\"mssql: unexpected login token 0x%02x\", token)\n\t\t}\n\t}\n\treturn false, nil\n}\n\nfunc mssqlParseErrorToken(payload []byte, pos int) (mssqlRawError, int, error) {\n\tif pos+2 > len(payload) {\n\t\treturn mssqlRawError{}, pos, fmt.Errorf(\"mssql: truncated error token\")\n\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 mssqlRawError{}, pos, fmt.Errorf(\"mssql: invalid error token size\")\n\t}\n\tpos += 2\n\tnumber := int32(binary.LittleEndian.Uint32(payload[pos : pos+4]))\n\tpos += 4\n\tpos += 2\n\tmessage, next, err := mssqlReadUSVarChar(payload, pos)\n\tif err != nil {\n\t\treturn mssqlRawError{}, pos, err\n\t}\n\treturn mssqlRawError{number: number, message: message}, end, mssqlEnsureSkipBVarStrings(payload, next, end)\n}\n\nfunc mssqlSkipUSVarError(payload []byte, pos int) (int, error) {\n\tif pos+2 > len(payload) {\n\t\treturn pos, fmt.Errorf(\"mssql: truncated info token\")\n\t}\n\tsize := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\n\tend := pos + 2 + size","sourceCodeStart":322,"sourceCodeEnd":358,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/plugins/services/mssql_raw.go#L322-L358","documentation":"mssqlParseErrorToken read the 2-byte length header of a TDS ERROR token and found it structurally impossible: the token size is smaller than the mandatory 6-byte fixed header, or the token extends past the end of the payload, or the fixed header would cross the payload end. The library throws this instead of parsing out-of-bounds, because the token is malformed and cannot be trusted.","triggerScenarios":"mssqlParseLoginTokens encounters an ERROR token whose declared length < 6, or whose end = pos+2+size exceeds len(payload), or pos+8 > len(payload).","commonSituations":"A middlebox reassembles TCP segments incorrectly and splices token bytes; a hostile/fuzzed server sends an under-sized length to probe the parser; version mismatches between server and a protocol-shifting proxy corrupt token boundaries.","solutions":["Retry the login; if reproducible, capture the packet and inspect the ERROR token length field.","Verify there is no proxy/VPN mangling the TDS stream between client and server.","If the payload comes from your own code, log it hex-dumped and check the token framing against the TDS spec.","Treat the server as untrusted/misbehaving and abort the connection rather than retrying blindly."],"exampleFix":"// before: blindly trust the declared size\nsize := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\nend := pos + 2 + size\n// after: validate before slicing\nsize := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\nend := pos + 2 + size\nif size < 6 || end > len(payload) {\n    return fmt.Errorf(\"mssql: invalid error token size (size=%d, payload=%d)\", size, len(payload))\n}","handlingStrategy":"validation","validationCode":"size := int(binary.LittleEndian.Uint16(payload[pos : pos+2]))\nif size < 6 || pos+2+size > len(payload) {\n    return fmt.Errorf(\"ERROR token size %d invalid for payload %d\", size, len(payload))\n}","typeGuard":null,"tryCatchPattern":"if _, _, err := mssqlParseErrorToken(payload, pos); err != nil {\n    conn.Close()\n    return fmt.Errorf(\"server sent malformed ERROR token: %w\", err)\n}","preventionTips":["Treat all declared token lengths as untrusted input; validate min/max bounds.","Verify endpoint is genuine SQL Server to avoid garbage from other services.","Avoid TDS-rewriting proxies; prefer direct or plain TCP+TLS paths.","Fuzz-test your parser harness against under-sized length fields."],"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"}