ClickHouse v25.8.29.51-lts 发布解析:安全加固、数据正确性与稳定性修复全景
2026/9/18 21:35:25 网站建设 项目流程

ClickHouse v25.8.29.51-lts 发布解析:安全加固、数据正确性与稳定性修复全景

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

导读

本文基于 ClickHouse 官方发布记录 docs/changelogs/v25.8.29.51-lts.md,系统梳理 v25.8.29.51-lts(相对基准版本 v25.8.28.1-lts)的变更全貌:包括 bcrypt 认证缓存与 MySQL 握手修复两项改进、20 余项面向用户可见的错误修复(安全、数据正确性、崩溃三大类)、以及依赖升级等构建/打包改进。文章结合当前仓库源码给出实现级佐证,帮助你在升级前评估风险、理解修复原理,并据此制定回归测试清单。

一、版本概览:从 v25.8.28.1-lts 到 v25.8.29.51-lts

本版本属于 ClickHouse 25.8 系列的 LTS(长期支持)分支补丁版本,变更集提交号为54df9137dcf,对比基线为cfec8e085ba(v25.8.28.1-lts)。整个变更清单按官方惯例分为四类:

  • Improvement(改进):2 项,集中在认证路径的性能与协议正确性;
  • Bug Fix(用户可见缺陷修复):24 项左右,覆盖安全漏洞、数据正确性、崩溃三大主题;
  • Build/Testing/Packaging Improvement(构建测试打包改进):5 项,全部为第三方依赖升级或 CVE 修复;
  • NOT FOR CHANGELOG / INSIGNIFICANT(内部改动):3 项,不面向用户。

从类别分布可以清晰看出,本版本的核心主题是安全与可靠性:多项 RBAC(基于角色的访问控制)绕过、凭据泄露、SQL 注入等安全问题被修复,同时修复了一批在特定并发或畸形输入下才会触发的崩溃与数据损坏问题。下文按主题深度展开。

二、认证与协议改进(Improvement)

2.1 bcrypt 认证缓存:降低高频认证开销

变更记录:为 bcrypt 认证增加缓存(backport #111210,原 PR #87115)。

bcrypt 是一种刻意"慢"的密码哈希算法(计算成本高、抗暴力破解强),因此每次认证都要做一次完整的 bcrypt 计算时,高并发登录场景会成为性能瓶颈。本次改动为 bcrypt 认证结果引入了缓存,使短时间内重复的认证请求可以复用已计算的结果。

仓库中 bcrypt 认证类型定义在 src/Access/Common/AuthenticationType.h,认证数据的核心逻辑在 src/Access/AuthenticationData.cpp,接入点还包括 src/Access/AccessControl.cpp 与 src/Access/Authentication.cpp。从结构看,ClickHouse 支持plaintextsha256_passworddouble_sha1_passwordbcrypt_password等多种认证方式,bcrypt 是其中计算代价最高的一种,缓存机制对该类型的意义尤为明显。

需要说明的是,本次记录属于改进而非缺陷修复,缓存命中逻辑对用户完全透明,升级后无需额外配置。

2.2 MySQL 握手auth_response长度读取修复

变更记录:修复 MySQL 握手协议中auth_response长度读取问题(backport #110486,原 PR #107384)。当长度字节>= 128时,由于该字节按有符号char读取,会被错误地解释为"数十亿字节"的多 GB 数值。

MySQL 客户端认证握手时,auth_response的长度由单字节字段表示,其取值在 0~255 之间。若实现把该字节当作有符号char读取,则128~255范围内的值会被解释为负数,进而被无符号扩展成巨大的无符号长度(multi-gigabyte),导致后续的缓冲区分配或读取失控。

仓库中该逻辑位于 src/Core/MySQL/PacketsConnection.cpp:握手响应解析时先读取长度编码字段,再根据auth_plugin_name分支决定按readLengthEncodedString、定长readStrict或空终止字符串方式读取auth_response。修复点即在长度读取处改用无符号语义,确保>= 128的长度被正确解析。这对使用mysql()表函数、MySQL 引擎、MySQL 字典及原生 MySQL 协议接入的用户有直接影响——此前携带长认证响应(例如某些带长密码或扩展认证插件的客户端)的握手可能失败或异常。

三、安全类修复:权限绕过、注入与凭据泄露

本版本安全修复量级最大,且多数属于"可被低权限用户利用"的实质性漏洞,建议生产环境优先评估升级。

3.1 RBAC 绕过修复(4 项)

漏洞场景修复说明关联 PR
loop()表函数绕过行级策略loop此前直接调用inner_storage->read(),跳过了解释器层,行级策略(row policies)、列级授权等安全检查全部失效。受行策略限制的用户可通过loop(table)读回全部行,即使直接 SELECT 返回 0 行#97682
remote()/remoteSecure()/cluster()/clusterAllReplicas()指向 localhost 时的 DESCRIBE 绕过无需SHOW_COLUMNS权限即可 DESCRIBE 任意表#98669
表函数上的 DESCRIBE/CREATE TABLE AS 绕过mysql()postgresql()sqlite()arrowFlight()jdbc()odbc()等表函数执行DESCRIBE TABLECREATE TABLE AS无需源访问权限;对需要从远端服务器推断 schema 的函数,还可在未授权的情况下触发出站连接(SSRF 风险)#99122
MySQL 协议COM_FIELD_LIST/COM_INIT_DB访问控制缺失这两个命令现在与其 SQL 等价物(SHOW COLUMNS/DESCRIBEUSE)执行相同的访问控制,此前会泄露用户仅有部分列权限的表的列名,且可在无SHOW DATABASES权限时切换当前数据库#108508

loop()表函数为例,其实现位于 src/TableFunctions/TableFunctionLoop.cpp。修复后的getActualTableStructure(第 101-124 行)在读取 schema 前调用context->checkAccess(AccessType::SHOW_COLUMNS, ...),并在内嵌表函数路径下改用getActualTableStructureWithAccess强制源访问检查;executeImpl(第 126-174 行)则对普通表路径显式检查AccessType::SELECT,并对Alias存储的目标表做完整性校验(第 146-154 行)。同时,该文件底部的函数注册描述(第 176-233 行)给出了loop的完整语法:loop(database, table)loop(database.table)loop(table)以及loop(other_table_function(...))(如SELECT * FROM loop(numbers(10))),可用于编写针对行策略场景的回归测试。

3.2 物化视图权限检查前置

变更记录:在物化视图创建阶段,对其内部底层查询执行完整的权限检查(backport #111699,原 PR #89180)。

此前物化视图创建时可能只在后续触发时检查权限,导致拥有建视图权限但无底层表读取权限的用户能够通过物化视图间接读取数据,或创建出后续无法正常工作的视图。本次修复将权限检查提前到 CREATE 阶段。

3.3 SQL 注入修复:字典源的引号转义(CVE 级别问题)

变更记录:修复 PostgreSQL、Cassandra 与 XDBC 字典源的 SQL 注入漏洞(backport #105181,原 PR #104009)。这些后端中,字符串键中的单引号此前以\'(反斜杠转义)处理,但这些后端把反斜杠当作字面量而非转义符,攻击者可以向字典查询 SQL 中注入任意 SQL。

修复方案是ExternalQueryBuilder对上述后端改用 SQL 标准的''(双单引号)转义;ClickHouse 与 MySQL 字典源继续使用反斜杠转义,因为这两个后端语义不同。这是一处典型的"方言差异导致注入"的案例,升级后若存在依赖反斜杠转义行为的自定义字典查询,建议回归验证。

3.4 凭据泄露修复(4 项)

本版本集中修复了多路径凭据泄露,覆盖"日志可见"与"输出可见"两类场景:

泄露路径修复说明关联 PR
query_log中 paimon/deltaLake 系列表函数修复paimonClusterpaimonS3ClusterpaimonAzureClusterdeltaLakeS3表函数在query_log中的凭据泄露#100529
system.query_views_log.view_query隐藏其中的敏感信息#108214
S3 全形态凭据泄露修复SHOW CREATEsystem.query_log、服务器日志与EXPLAIN输出中的凭据泄露:所有 S3 locator 形式现在都会对session_token、Google ADC 密钥、extra_credentials/headers值(任意参数位置)、重复或表达式形式的密钥、非法位置参数(fail closed)以及嵌入在 S3 URL 中的凭据进行掩码;覆盖s3/s3Cluster表函数、S3 系表引擎、S3数据库引擎、BACKUP ... TO S3Backup数据库引擎。此外,由表达式构建的encrypt/decrypt/HMAC 密钥参数(包括从 SQL UDF 内联的)现在会在投影名、EXPLAIN QUERY TREEEXPLAIN actions中被隐藏#109768
URL 引擎掩码改进URL()表引擎与url()表函数中对 URL 内密码的掩码#95006

这类修复与http_forbid_headers的强化(见 3.5)共同构成"凭据不落盘、不外泄"的安全闭环,对把 S3 凭据写进查询、依赖system.query_log做审计的平台团队尤为重要。

3.5 HTTP 头过滤强化:大小写不敏感

变更记录:http_forbid_headers配置改为大小写不敏感匹配(backport #109568,原 PR #108509);同时getClientHTTPHeader中的头过滤按 RFC 9110 大小写不敏感(backport #110374,原 PR #109791,将authorization加入过滤列表)。

HTTP 头名称本身大小写不敏感(RFC 7230/9110),但此前禁止Authorization并不能挡住authorizationAUTHORIZATION等变体。修复后配置的header_regexp模式无需显式(?i)标志即大小写不敏感。

实现位于 src/Common/HTTPHeaderFilter.cpp:setValuesFromConfig(第 56-98 行)将精确匹配的header条目统一小写后存入集合,并基于 RE2 options 将header_regexp编译为大小写不敏感模式(同时对无法编译的模式给出警告而不中断配置加载);checkAndNormalizeHeaders(第 18-54 行)在校验每个请求头时:拒绝含\n/\r的头(防请求/响应拆分)、剥离名称中的空白与控制字符、小写化后查禁列表、再用编译好的正则做全匹配。相关测试见 src/Common/tests/gtest_http_header_filter.cpp。此外,DataLakeCatalog现在会在校验auth_header配置时遵循服务器http_forbid_headers配置(#98827)。

四、数据正确性修复

4.1arrayJoinJOIN ON的行数错误

变更记录:修复arrayJoin()用于JOIN ON时行数计算错误——结果被额外乘以了数组长度(backport #108571,原 PR #104785)。

此前SELECT ... FROM t JOIN u ON arrayJoin(arr) = k这类查询返回的行数是正确值的数倍,升级后将恢复正确语义。涉及该写法的查询需要重点回归。

4.2 ALTER RENAME COLUMN 与后台合并的竞态(可能造成数据丢失)

本版本针对 MergeTree 的ALTER TABLE ... RENAME COLUMN与并发后台操作之间的竞态做了两项关键修复:

  • OPTIMIZE TABLE ... FINAL/ 后台合并的竞态(#104822):可能在重命名后把列数据静默替换为默认值。修复方式为在"发布新内存元数据"与"在current_mutations_by_version注册重命名 mutation"两个操作期间持有currently_processing_in_background_mutex,关闭竞态窗口。
  • 无默认表达式列的数据丢失(#109356):当合并与RENAME COLUMN并发、或列的唯一值来自轻量级UPDATE时,该列可能从合并 part 中被丢弃,读取全部变 NULL。修复后此类列不会再被错误裁剪。

这两项修复对大量使用列重命名 + 后台合并的生产表意义重大,建议升级后对相关表执行校验。

4.3 分布式查询中 ALIAS 列错位

变更记录:修复分布式查询选取共享公共子表达式的ALIAS列时结果错误——列可能错位,值被放在错误的列名下(backport #109787,原 PR #107675)。

4.4 投影(Projection)返回错误的 DEFAULT 值

变更记录:当投影创建之后又用ALTER TABLE ... ADD COLUMN ... DEFAULT添加列时,SELECT *经投影读取会返回类型默认值(如0)而非DEFAULT值(如-1)。基础表读取正确,只有命中投影的读取受影响,直至投影被重建(backport #110095,原 PR #108569)。

4.5 动态列 / Iceberg 兼容性

  • Dynamic 列表的 mutation part 读取:修复合并或读取由含Dynamic列表的 mutation 产生的 part 时可能出现的Logical error: Stream ... variant_discr ... is not found(#107562)。
  • Iceberg 表格式版本升级:修复外部工具(如 Spark)升级了格式版本的 Iceberg 表读取时的 logical error(#100407)。
  • Delta Lake:延续 #96754 对 delta lake 的同类修复(#106115)。

4.6 分区参数化 mutation 的可解析性校验

变更记录:修复ALTER TABLE ... UPDATE/DELETE ... IN PARTITION {param:Type}中分区参数替换后序列化格式无法解析回的问题——此前会导致表加载失败(复制表上每个副本都失败)。现在 mutation 命令在写入 ZooKeeper 或磁盘前会先验证可解析回,类似不匹配会直接使ALTER失败,而不是破坏表(backport #111853,原 PR #111518)。

五、崩溃与健壮性修复(Crash / OOB)

本版本修复了一批由畸形输入、并发或深层嵌套触发的崩溃,多数与 deserialization/压缩/格式解析相关:

组件问题与修复关联 PR
CompressionCodecT64/CompressionCodecMultiple解压畸形压缩数据时堆缓冲区溢出/进程中止(由新 libFuzzer 目标发现),现改为抛异常#99680
Protobuf 格式读取input_format_allow_errors_num > 0且同一 block 内有效消息后跟坏(可跳过)消息时 SIGSEGV#107739
S3Queue/AzureQueueenable_hash_ring_filtering = 1时,批内含不可处理文件且 Keeper 设置批处理状态请求同时失败时越界崩溃#108977
uniqExact并行合并两级集合的并行合并数据竞争(GROUPING SETS/ROLLUP/CUBE场景)#109389
groupArrayLastMerge聚合状态反序列化未校验导致越界,现对损坏状态做校验并拒绝#109485
聚合状态反序列化String值的畸形聚合状态导致越界段错误,现校验并拒绝#111606
quantileTDigest状态列作为GROUP BY键被多线程并发序列化时堆缓冲区溢出#110263
深层嵌套字面量max_parser_depth提高后,深层嵌套Array/Tuple/Map/Object字面量在拷贝/析构时原生栈溢出#110393
Arrow/ArrowStream兼容 Apache Arrow Java < 19.0.0(随 Spark 分发)产生的空嵌套Array/Map列,此前误报 offsets buffer 过小的INCORRECT_DATA#111101
TLS 证书每次开启证书校验的 TLS 握手泄漏对端证书内存(SSL_get1_peer_certificate未释放)#111425
加密盘 Compact part 直接 IOReadBufferFromEncryptedFile: Wrong file positionlogical error 导致合并卡在system.replication_queue#112943
File引擎/file表函数追加对不支持追加的格式(如 Avro)向非空文件追加时绕过检查、写入第二个头导致文件不可读,现统一拒绝并报CANNOT_APPEND_TO_FILE#112839
CREATE OR REPLACE字典替换提交后因CANNOT_DETACH_DICTIONARY_AS_TABLE失败,遗留孤立的_tmp_replace_*#111142

这批修复的价值在于:多数由模糊测试(libFuzzer)或特定畸形输入触发,普通查询路径难以命中,但一旦命中即可能导致服务崩溃,属于典型的"低概率、高影响"风险,建议纳入升级考量。

六、构建、测试与打包改进

  • openssl 升级至 3.5.7(#106844)
  • libarchive 3.8.7 → 3.8.8(#109874)
  • c-ares 1.34.6 → 1.34.8(#109905)
  • krb5 安全修复:CVE-2026-40355 与 CVE-2026-40356(#109910)
  • Apache Thrift 升级至 0.24.0(#111278)
  • aws-c-http 升级至 v0.11.0(#112413)
  • SQLite amalgamation 3.41.2 → 3.53.4(#112599)

依赖升级主要服务于安全(krb5 CVE、openssl)与生态兼容(Thrift、SQLite、aws-c-http、c-ares),涉及网络/对象存储/协议组件的用户应关注。

内部改动(NOT FOR CHANGELOG)还包括:Context 中使用显式标志区分次级 DDL/ON CLUSTER 查询(替代SECONDARY_QUERY)、SchemaProcessor 跳过空 schema 检查、以及 CI 在 address,undefined 组合构建中向 Rust 传递-Zsanitizer=address——后者表明仓库对 Rust 组件(见 rust/ 目录,如 chcache)与 C++ 组件在 sanitizer 覆盖上保持一致。

七、升级与回归建议

结合变更清单与仓库源码,针对 v25.8.29.51-lts 给出以下升级与验证建议:

  1. 优先验证安全相关行为:对loop()(含loop(numbers(...))等表函数组合)、remote()/cluster()指向 localhost 的DESCRIBE、MySQL 协议客户端(COM_FIELD_LIST/COM_INIT_DB)、表函数上的DESCRIBE TABLE/CREATE TABLE AS做权限回归;重点确认行策略、列级授权与SHOW_COLUMNS权限被正确执行。
  2. 校验凭据脱敏:检查system.query_logSHOW CREATEEXPLAIN输出以及服务器日志中不再出现 S3session_tokenextra_credentialsheaders等敏感字段;若依赖http_forbid_headers禁止Authorization等头,可用authorizationAUTHORIZATION变体验证大小写不敏感匹配已生效(实现见 src/Common/HTTPHeaderFilter.cpp)。
  3. 关注数据正确性场景:对使用arrayJoinJOIN ONALTER ... RENAME COLUMN与后台合并并存、轻量级UPDATE、投影 +ADD COLUMN ... DEFAULT、Dynamic 列 mutation、分区参数化 mutation 的表执行针对性校验。
  4. MySQL 握手兼容性:若使用长认证响应或扩展认证插件的 MySQL 客户端/驱动,验证握手正常(解析逻辑见 src/Core/MySQL/PacketsConnection.cpp)。
  5. 依赖升级验证:涉及 Thrift(Hive 等)、SQLite、c-ares(DNS)、aws-c-http(S3)的功能路径建议做冒烟测试;字典源若使用 PostgreSQL/Cassandra/XDBC 且查询中含单引号键,回归验证注入修复后的转义行为。

结语

v25.8.29.51-lts 是一次典型的"补丁密度高、面向生产可靠性"的 LTS 迭代:安全层面封堵了表函数/协议路径上的多项 RBAC 绕过与凭据泄露,正确性层面修复了列重命名竞态等可能静默损坏数据的缺陷,健壮性层面通过输入校验把一批模糊测试发现的崩溃转化为优雅异常。对于运行 25.8 系列的集群,建议在完成上述回归验证后尽快纳入升级队列。

参考:发布记录 docs/changelogs/v25.8.29.51-lts.md;源码佐证 src/TableFunctions/TableFunctionLoop.cpp、src/Common/HTTPHeaderFilter.cpp、src/Core/MySQL/PacketsConnection.cpp、src/Common/tests/gtest_http_header_filter.cpp。

【免费下载链接】ClickHouseClickHouse® is a real-time analytics database management system项目地址: https://gitcode.com/GitHub_Trending/cli/ClickHouse

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询