SILO 20260804 发布说明
版本: RELEASE.2026-08-04T00-00-00Z · 提交: d88f46ccee345a9c2fabe2d221d9a9e56bc11aec
SILO 20260804 是 pgsty/minio 社区分支的一次安全、正确性与发布工程更新。该版本完成 CVE-2026-42600 所开启的节点间存储边界治理,阻止客户端输入冒充服务端计算出的 S3/IAM 策略条件值,恢复流式响应 flush 语义,修复多项 multipart 与版本控制边界问题,加固通知配置迁移,将构建基线升级到 Go 1.26.5,并接入由 SILO 维护的 Console、共享包与 mcli 版本。发布流水线经过重建,产出可复现的二进制与 GPG 签名的软件包。
本次发布覆盖 2026-06-18 前基线之后的 50 个提交,共修改 155 个文件,新增 9,241 行、删除 981 行。每一处改动都针对已打标签的提交进行审查,并在 macOS ARM64 与 Linux AMD64 上验证,GitHub CI 在已发布 HEAD 上全部通过。
版本亮点
- 节点间边界收尾: 在存储边界校验 storage-REST 消息体、storage Grid 帧与 peer-S3 Grid 请求,关闭移除
ReadMultiple后残留的路径、卷、纠删元数据、panic 与无界分配缺陷。 - S3/IAM 决策使用真实有效值: 客户端输入不再能遮蔽内部条件值;请求标签与既有对象标签被分离;
s3:signatureAge被限制在经过验证的预签名请求内;s3:versionid跟随服务端实际操作的版本。 - Bucket 与 Object 资源分离: 十二项敏感的 bucket 级写操作不再能通过仅对象的
bucket/*资源模式被授权。提供一个有文档记录的兼容开关用于迁移。 - Multipart 兼容性与正确性改进: 协议允许时,完整对象校验和补全无需逐分片校验和即可工作;零长度 multipart 对象的校验和被保留;重复的分片编号被拒绝,而不是拼装出重复数据。
- 流式可靠性恢复:
trackingResponseWriter现在正确实现Flush并记录隐式 HTTP 200 响应,修复了 20260618 发布中记录的继承回归所影响的mcli watch、bucket 通知监听器与 S3 Select keep-alive。 - 通知配置加固: 解析器与旧迁移读取的 NATS、AMQP 键被注册并正确往返;libpq 连接参数被安全引用;非法键错误不再回显 secret 值。
- 可复现、已签名的发布流水线: 二进制不再嵌入构建机路径,软件包安装到规范的 systemd 路径,RPM 经过 GPG 签名。容器入口现在在每条权限路径上都能优雅退出。
- 发布基线刷新: Go 1.26.5、
klauspost/compress1.18.7、Apache Thrift 0.24.0、SILO Console 2.0.0、silo-pkg3.11.0 与mcli20260804。
安全加固
节点间 storage 与 Grid 边界 — SN-2026-002
20260618 移除过时的 ReadMultiple 端点关闭了一条可达路径,但并未关闭底层缺陷类别。storage-REST 请求体与 Grid RPC 帧不经过 HTTP 查询校验中间件,而 peer-S3 RPC 可以完全绕过 storage-REST 包装层。
本次发布把边界收敛到存储层,在使用前校验每一个调用方可控的路径、卷、纠删参数、分片大小、shard 长度与分配长度。修复包括:
- 在路径与卷两个维度拒绝穿越,包括 Windows 卷根别名;
- 覆盖那些不经 storage-REST 包装层就触达磁盘的 peer-S3 bucket RPC;
- 在 shard 运算之前拒绝为零或不可用的 data/parity/block-size 组合;
- 拒绝负的分片大小与被截断的 shard,而不是把它们报告为健康;
- 将 storage-REST
ReadFile的分配上限设为 5 GiB; - 约束其他源自节点间声明的分配;
- 在不阻塞调用方的前提下遏制 deadline-bounded 存储任务中的 panic;
- 在 keep-alive 响应间保留
ReadParts错误,并避免空分片列表的 trace panic。
这些路由需要集群 root 或节点间凭据,且仅在分布式纠删部署中注册。单节点 S3 行为不变。协议面分析见 节点间路径边界审计。
策略条件绑定真实有效值 — SN-2026-003
策略条件映射历史上把服务端计算的值与原始请求条目混在一起。因此一个客户端可控的拼写可以遮蔽或合成一个内部条件值。SILO 20260804 将 silo-pkg 3.11.0 的精确键查找规则与服务端来源归一化配对:
- 内部条件名不能作为任意客户端值提供;
s3:prefix、s3:delimiter、s3:max-keys取自各自的有效查询输入;- 基于 Header 的
x-amz-*条件不接受无关的查询替代值; - 当存储类别或上传标签同时支持两种形式时,显式存在的 Header 胜出,包括空 Header;
s3:ExistingObjectTag/*仅来自已存储的对象元数据;s3:RequestObjectTag/*绑定到相关操作实际消费的标签输入;s3:signatureAge只在经过验证的 SigV4 预签名认证计算出它之后才暴露;s3:versionid在未指定版本时缺席,并在DeleteObjects中按条目重新绑定到实际解析出的有效版本。
版本 ID 行为关闭了一个"简单省略空值"式修复本会为 Multi-Delete 制造的 fail-open 陷阱。见 缺席不等于为空。
Bucket/Object 资源边界 — SN-2026-004
IAM 匹配器过去会给 bucket 级请求追加一个斜杠,使得像 arn:aws:s3:::bucket/* 这样仅对象的资源能授权部分 bucket 级操作。本次发布在 Allow 语句上,将这十二项敏感写操作从该模式中排除:
PutBucketPolicy、DeleteBucketPolicy、PutBucketObjectLockConfiguration、PutBucketVersioning、PutReplicationConfiguration、PutBucketLifecycle、DeleteBucket、ForceDeleteBucket、PutBucketCors、DeleteBucketCors、PutBucketQOS 与 PutInventoryConfiguration。
Deny 与 NotResource 行为不变。读取/列举操作、CreateBucket、bucket 标签、默认加密与通知配置保持兼容。内置策略使用 Resource: "*",不受影响。
自定义 bucket 授权需要迁移策略
如果某个自定义策略仅用 arn:aws:s3:::bucket/*(常常通过 s3:*)授予这十二项操作之一,请补上裸 bucket ARN:
"Resource": ["arn:aws:s3:::bucket", "arn:aws:s3:::bucket/*"]
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 在策略迁移期间恢复历史匹配器。它同时也恢复了历史上的过度授权,因此只应作为临时回滚控制使用。
可信客户端地址边界
MINIO_API_TRUSTED_PROXIES 为 aws:SourceIp、审计 remotehost、事件通知 Host 以及 mcli admin trace 显示的客户端地址提供了一个可强制执行、按需启用的边界:
- 设为地址/CIDR 列表,则仅信任来自这些对端的转发头,并从右向左遍历转发链;
- 设为
none,则忽略所有转发头; - 保持未设置,则完全维持历史行为。
旧的 _MINIO_API_XFF_HEADER=off 开关仍然只抑制 X-Forwarded-For,它不防护 X-Real-IP 或 RFC 7239 Forwarded。如果基于 IP 的策略是你安全边界的一部分,请显式配置可信代理,并阻止对 S3 API 端口的直接访问。多节点部署应当允许自己的节点地址。见 客户端源地址信任。
S3 与存储正确性
Multipart Upload
- 当补全请求不提供逐分片校验和、且上传元数据不要求它们时,CompleteMultipartUpload 接受 S3 完整对象校验和模式。
- 零长度 multipart 对象的校验和被保留,而不是作为空元数据丢弃。
- 分片编号必须严格递增。像
[1,1]这样的重复条目现在返回InvalidPartOrder,而不是消费掉上传并把同一分片拼装两次。带间隙或非 1 起始的合法分片列表仍被接受。见 重复分片编号。
对象读取与 Buffer 所有权
- 纠删读取仅在所有权允许复用时才池化 buffer;
- 更新下载返回调用方拥有的 buffer,而不是暴露返回后可能被覆盖的数据;
- 移除
ReadMultiple后遗留的旧 HTTP 流式辅助函数,在引用与平台 tag 检查后被删除。
HTTP Response Tracking 与 S3 Select
trackingResponseWriter.Flush()委托给底层 flusher 并正确提交响应状态;- 第一次隐式写入记录 HTTP 200,保持审计与指标准确;
- S3 Select 测试不再让客户端解析器与响应体所有权竞争;
- CSV、JSON、Parquet 选择路径保持覆盖,包括 range/错误与 keep-alive 行为。
因此 SILO 20260618 中指出的继承性静默 flush 回归在本次发布中得到修复。
IAM、版本控制与审计行为
- DeleteObject 以及 DeleteObjects 中的每个条目,都针对服务端选定的有效版本评估
s3:versionid。 - 请求标签在策略评估期间不再能冒充既有对象标签。
- 在发出悬垂对象删除记录时恢复
merrs标签,保持预期的审计分类。 - Bucket-policy 与 IAM 路径共享加固后的条件来源规则,同时保留各自既定的 S3 路由与错误行为。
通知配置
- 注册解析器读取的 NATS
user_credentials、nkey_seed、tls_handshake_first键; - 将旧 NATS 环境变量拼写与存储的配置键分离;
- 修复 NATS 迁移往返与 AMQP
immediate/internal映射; - 增加一项机械审计,把通知代码读写的键与各子系统注册的 schema 做比对;
- 引用 libpq 连接串参数,使空白、引号与反斜杠保持其预期取值;
- 阻止非法键诊断回显 secret 值。
见 通知键空间注册。
已知的旧迁移限制
继承的 Postgres 与 MySQL 旧迁移函数仍然写入未注册的 host、port、username、password、database 字段。因此迁移后的配置可能在下次加载时校验失败,而通知目标加载是跨子系统 fail-fast 的。此问题早于 20260804,但从连接串之前的数据库通知配置升级时,必须在重启前审查并转换。存储的 password 字段可能包含明文数据库密码。
组件与依赖
- Go 1.26.5: 包含
crypto/tls与os的安全修复,以及编译器、运行时、网络与 syscall 的修正。 klauspost/compress1.18.7: 刷新对象与归档路径使用的压缩栈。- Apache Thrift 0.24.0: 更新经由 Parquet 支持编译进来的依赖。
- go-systemd 22.6.0: 有意保留而非升级到 22.7.0,因为后者引入了与受支持交叉构建矩阵不兼容的 NetBSD 时钟依赖。
- SILO Console 2.0.0: 嵌入式 console 选自
pgsty/silo-console,同时保留兼容的github.com/minio/console导入路径。 silo-pkg3.11.0: 提供配套的策略、LDAP、证书、RNG 与时间格式修复,同时保留github.com/minio/pkg/v3模块路径。mcli20260804: 嵌入式客户端来自pgsty/mc;发布镜像将其暴露为mcli并保留mc兼容别名。
配套发布说明见 silo-pkg 3.11.0、mcli 20260804 与 SILO Console 2.0.0。
构建、CI 与软件包
本次发布为可复现性与供应链完整性重建了发布流水线:
- 每条路径都优雅退出。 入口脚本的自定义 UID/GID 分支现在
exec进入服务端,使其以 PID 1 运行并直接接收SIGTERM;此前这些分支把一个中间 shell 留作 PID 1,服务端会在容器停止超时后被强杀。一个 CI 烟测会构建发布运行时镜像,并在默认路径与降权路径上断言优雅退出。 - 可复现二进制。 发布二进制不再嵌入构建机的
GOPATH/GOROOT,因此-trimpath生效,第三方从标签重建可得到一致的字节。已发布的 Linux 二进制不含任何构建机路径。 - 加固的发布工作流。 发布标签通过环境传入并做白名单校验,而不是拼接进 shell;构建检出的是正在发布的那个标签;一个可能越过流程发布或移动
latest的、未跟踪的影子 GoReleaser 配置被移除。 - 诚实的门禁。 CI 对构建、vet、单元测试、lint、生成漂移、race 测试与交叉编译把关;交叉编译矩阵对齐到实际发布目标的精确集合;lint 与依赖安装步骤现在会在真实错误上失败,而不是掩盖它们。
- 签名的规范软件包。 RPM、DEB、APK 软件包以 PGSTY 身份用 nFPM 产出,systemd unit 安装到
/usr/lib/systemd/system/minio.service并使用Type=notify,RPM 由 PGSTY 维护者密钥离线 GPG 签名(指纹9592A7BC 7A682E73 33376E09 E7935D8D B9BD8B20)。 - 发布与容器发布仍是分离的门禁。 GoReleaser 产出平台归档、校验和与软件包;多架构镜像从完成的发布按需发布。本地快照不能证明公开发布或镜像已存在。
兼容性与升级说明
- 集群滚动升级期间保持所有节点在同一发布版本。 节点间校验在 storage-REST 与 Grid 面上发生了改变;混合二进制未经生产测试。
- 审查自定义 IAM 策略。 为这十二项受保护的 bucket 写操作补上裸 bucket ARN。仅将
MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on作为临时迁移控制。 - 有意识地配置客户端地址信任。 如果
aws:SourceIp或审计归属重要,请设置MINIO_API_TRUSTED_PROXIES并封闭代理周围的直连网络路径。 - 审查旧的数据库通知设置。 在重启前把 Postgres/MySQL 的 host/user/password 字段转换为受支持的连接串格式。
- 预期重复的 multipart 补全条目会失败。 多次发送同一分片编号的客户端现在会收到
InvalidPartOrder,而不是一个损坏但成功的对象。 - 使用匹配的
mcli。 20260804 客户端禁用了自更新,必须通过软件包或 GitHub Releases 升级;mcli update保留为兼容命令但以非零码退出。 - RPM 用户可启用签名校验。 软件包用上述维护者密钥签名;在为 SILO 软件包启用
gpgcheck之前先导入该密钥。
已执行验证
改动针对已打标签的提交进行审查并重新验证,而非信任既有报告:
git diff --check、gofmt、模块校验以及 YAML/shell 语法;go build ./...、go vet ./...、项目 lint 与govulncheck ./...;- 完整的
go test ./...、完整 race 套件,以及针对存储、策略、通知、HTTP tracking 与 S3 Select 改动的重复 race 测试; - 生成器幂等性,加上刻意构造的陈旧源与未跟踪产物反例;
- 对每个发布目标的交叉编译;
- Linux AMD64 原生全量测试、定向 race 测试、真实 S3/
mcli冒烟测试(创建/上传/下载/复制、range、版本控制、删除标记、健康检查、优雅退出、重启持久化)与 systemd notify 行为; - 发布产物验证:GitHub CI 在已发布 HEAD 上全绿、可复现二进制不含构建机路径、systemd unit 安装到
/usr/lib/systemd/system、RPM 签名以rpmkeys --checksig校验通过。
govulncheck 未发现可从 Server 或 mcli 代码到达的漏洞。对无人维护的 golang.org/x/crypto/openpgp 包仍有一条模块级提示(GO-2026-5932);该包未被编译进这些二进制。
验证边界
以下内容未被本次发布证明,也不应从交叉编译或单元测试推断:
- 原生 Windows 执行与 Windows 文件系统语义;
- Intel macOS 与物理 Linux ARM64 主机;
- 生产环境的多节点滚动升级、站点复制或生命周期过期运行;
- 真实的反向代理链与直连入口隔离;
- 外部 LDAP、OIDC、KMS、STS、Postgres、MySQL、NATS、AMQP 服务;
- 在真实 systemd 主机上安装并升级签名软件包。
发布产物
- GitHub release
RELEASE.2026-08-04T00-00-00Z,含 Linux、Darwin、Windows 在 amd64 与 arm64 上带校验和的平台归档; - PGSTY 身份下的 RPM、DEB、APK 软件包,其中 RPM 经 GPG 签名;
docker.io/pgsty/minio:RELEASE.2026-08-04T00-00-00Z以及发布选定的latest标签,从发布按需产出;- 配套的 SILO Console 2.0.0、
silo-pkg3.11.0 与mcli20260804 引用。
重点提交
ca7baa670、80e8eaa42、b6f70ab08:校验节点间路径、纠删元数据与分配大小a36fd8fff:遏制 deadline-bounded 存储任务中的 panic2f55347f7:将 S3/IAM 策略条件绑定到真实请求值744a9dcd7:将s3:versionid绑定到有效对象版本97b7d2804:强制 bucket/object 资源边界fe6dc4780:新增可信代理客户端地址边界22c1e41fd:拒绝重复的 multipart 分片编号c8590413f、3e14733f1:恢复完整对象与零长度 multipart 校验和行为8069a32ac、65795ee1f:恢复响应提交与流式 flush 语义162ded343、0c14d8151:修复通知键注册与 libpq 引用924717926、89d346bf5:恢复安全的 buffer 池化与返回 buffer 所有权3b8a55dee:exec 进入降权进程使信号抵达服务端2ca4971d9:停止把构建机路径烧入二进制4c185d5a6、e064b5555:加固发布工作流并移除影子配置aa5139369:将 systemd unit 安装到/usr/lib11d79fddc、ca674a696、021110b45、d88f46cce:对构建、vet、测试、lint、生成、race 与交叉编译把关,并对发布镜像做烟测