Silo 20260903 正式发布
分片列表最新决策 · Latest multipart-listing decision (2026-10-18)
中文: 2026-10-18 决定定向撤回默认持久扫描,恢复缓存/精确 key 列表;保留身份、安全和清理修复,不恢复 strict 开关。参见最新决策。回退实现见 4733e1423,尚未正式发布。旧章节保留对应版本的历史契约,不改变已安装二进制,也不替代其他主题的升级要求。
English: The October 18 decision withdraws default persistent scanning, restores cache/exact-key listing, retains identity, safety and cleanup repairs, and does not restore the strict switch. See the latest decision. The rollback is implemented in 4733e1423 and remains unreleased. Historical sections retain their named releases’ contracts; installed binaries and unrelated upgrade requirements do not change.
2026-09-17 后续版本: Server 20260916 已发布,补充签名、IAM、多池、复制与内嵌 Console 修复,并说明协调升级要求。本文保留 20260903 发布时的组件和验证范围。
2026-09-13 状态: 这仍是最新已发布 Server,发布依赖未改变。后续安全、存储与依赖修复目前在 main,包括尚未发布的 SN-2026-011 修复。独立 mcli/pkg 的新版不替换本制品内容;见组件矩阵。
版本日期: 2026-09-03 · 正式发布: 2026-09-04 · 版本: RELEASE.2026-09-03T13-18-01Z · 上一版本: RELEASE.2026-08-06T00-00-00Z
SILO 20260903 是首个完整使用 Silo 品牌的版本之后的一次安全与正确性发布。它的主线不是新的交付外观,而是一组更严格的服务端不变量:客户端 header 不能凭空获得复制权限;浏览器 Origin 不能在鉴权前触发桶元数据 I/O;并发桶配置写入不能彼此静默覆盖;授权与校验和行为进一步对齐 AWS S3。
本文有意只把 20260806 作为发布基线。中间组件构建仍可在各源码仓库中辨认,但下面的公开文档统一汇总 2026-09-03 交付的服务端、Console、共享包与客户端最终结果。
亮点
- 复制信任来自授权。
X-Minio-Source-Replication-Request与相关内部字段只有在签名验证、精确 marker 校验以及s3:ReplicateObject/s3:ReplicateDelete授权后才获得复制语义。不可信字段在鉴权后清洗,因此不会破坏 SigV4。 - 桶级 CORS 完整落地。
PUT、GET、DELETE ?cors持久化真实桶策略,覆盖服务端全局 fallback,并通过站点复制收敛。预鉴权查找只读驻留元数据;启动期与已知元数据加载失败状态都保持 fail-closed。 - 桶元数据更新串行化。 共享
metadata.lock覆盖所有整记录配置写入、迁移、导入、站点 adoption 与 healing。ForceCreate不再擦除既有配置;存在 Object Lock 文档的桶始终使用纯Enabled版本控制。 - 授权与请求动作一致。 显式删除版本需要
s3:DeleteObjectVersion;用户和组的启用/禁用按目标状态检查对应 action;策略写入拒绝空的 ARN namespace。 - 校验和进一步对齐 AWS S3。 UploadPart 可由服务端计算校验和;联邦
UploadPartCopy返回校验和;multipart completion 返回ChecksumType;非法断言使用 AWS 兼容错误;CRC64NVME与COMPOSITE的无效组合被拒绝。 - SSE-C 读取与复制统一校验密钥。 零字节对象和
GetObjectAttributes不再绕过密钥认证;null-version 改写与原地换钥不会再留下不可读密文或不一致的 checksum metadata。 - 发布前主动减法。 删除死代码与过期 lint 例外;兼容快照只追踪真实对外服务面;依赖锁定到已审 revision;timeout 测试改用私有随机源。
- 客户端版本归入同一基线。 mcli 20260903 新增只读 checksum verify,完成 fail-closed 凭据脱敏,修复 Metrics JSON 与 S3 Select,严格校验策略写入,并提供签名软件包、溯源证明与验证过的 amd64/arm64 镜像。
安全修复
仓库安全台账为五个没有 CVE 的发现分配了稳定的本地编号。SN- 不是 CVE。完整威胁模型、兼容影响与运维动作集中记录在 SILO 20260903 安全说明。
| 编号 | 影响面 | 修复后的不变量 | 运维影响 |
|---|---|---|---|
SN-2026-006 |
SSE-C 零字节对象的读取与复制 | 即使没有 payload block 可解密,也必须认证客户密钥 | 错误密钥返回 403 AccessDenied;正确密钥不变 |
SN-2026-007 |
SSE-C 对象的 GetObjectAttributes |
获取属性需要客户密钥,除非请求确实来自已授权复制对端 | 裸 replication marker 不能跳过密钥认证 |
SN-2026-008 |
读、写、multipart、删除、Snowball、事件中的内部复制字段 | 复制语义需要鉴权与对应复制权限 | 普通客户端携带内部样式 header 时仍按普通 S3 语义处理 |
SN-2026-009 |
管理 API 的用户与组状态变更 | 启用与禁用分别校验不同 action | 过去只授予一个 action 却依赖双向操作的自定义管理策略需要拆分 |
SN-2026-010 |
带 versionId 的 DeleteObject / DeleteObjects |
显式删除版本需要 s3:DeleteObjectVersion |
检查 grant;原本用 Deny s3:DeleteObject 阻止永久删除的策略还需显式 Deny 新 action |
五个缺陷都继承自已归档的上游服务端代码,影响此前所有 SILO 版本。SN-2026-008 是对 CVE-2026-34204 接收端全链路修复的补全。
内嵌 Console v2.3.0 线还包含可信代理边界、TLS 校验修复、响应与日志脱敏、WebSocket 转发上限。Console 独立发布与服务端内嵌仍是可分别核验的制品。
S3 正确性与互操作
Multipart 校验和
本版本关闭了 #46、#47、#48、#50 报告的 multipart 互操作问题组:
- 客户端在创建上传时选择算法、但没有为每个 part 提供 checksum header 时,
UploadPart由服务端计算所选校验和; - 旧版联邦后端的
UploadPartCopy不再丢掉远端返回的 checksum; CompleteMultipartUpload返回ChecksumType,缺失、畸形、矛盾或不支持的 checksum 使用 AWS 兼容错误;- 未知算法以及无效的
CRC64NVME+COMPOSITE组合直接拒绝,不再静默 canonicalize。
实现刻意分层:wire parser 拒绝非法声明,multipart state 记录所选算法和类型,完成阶段再将最终断言与状态比对。没有显式启用额外 checksum 的普通客户端不受影响。
独立证据记录见服务端计算 UploadPart 校验和、multipart completion 错误语义与 ChecksumType 传递。
CopyObject 与 SSE-C
CopyObject 现在会:
- 在可选压缩前对逻辑对象计算 checksum;
- 在响应中返回 checksum 字段;
- metadata-only copy 保留 transform state;
- 用源密钥解密源 checksum metadata,并为目标密钥重写;
- null-version 在任意 pool 方向复制时都不会丢失 current-version metadata;
- 对象层必须改写数据时,正确完成原地 SSE-C 换钥与重加密。
零字节对象与 attributes 修复消除了两个彼此独立的错误假设:“没有数据被解密”曾被等同于“密钥已经认证”。新规则是显式的:访问 SSE-C metadata 或 ciphertext 必须成功解封对象密钥,除非请求已经跨过授权 replica 边界。
CopyObject 状态矩阵与真实互操作证据记录在 CopyObject 的 SSE-C、checksum 与响应正确性。
列举与联邦
- ListObjects 快捷路径在 bucket 不存在且带 prefix 时也返回
NoSuchBucket(#32、PR #37)。 - 联邦
UploadPartCopy在公开响应中保留后端 checksum(PR #72)。 - 站点复制状态按站点计算 metadata 操作,不再把组级结果重复相乘,并将 CORS 作为独立配置字段校验。
missing-bucket shortcut 的完整记录见 ListObjects 必须先证明桶存在,再做优化。
桶级 CORS 与请求信任
桶级 CORS 不是只补 handler,而是端到端实现:
- S3 XML 类型与 rule matcher 校验协议 grammar 和多规则 preflight;
- bucket metadata 保存原始配置,
GET ?cors原样返回; - 外层 middleware 优先使用桶策略,不存在时才回落全局 origin 配置;
- 站点复制用带 tombstone 的 LWW register 单独承载 CORS;
- 预鉴权查找不加载 metadata、不创建 cache entry;
- 启动、已知桶元数据加载失败、删除、refresh 与按需重载都会显式维护 fail-closed 状态。
load-failure 状态是必要复杂度。预签名 URL 用自身签名完成鉴权,不需要 bucket policy;如果服务器忘记“真实桶的 CORS 文档加载失败”这一位信息,再回落宽松全局策略,就会丢掉这个已授权浏览器请求唯一的 origin 边界。
复制请求加固遵循同一原则。服务端先认证原始请求——内部 header 可能属于 SigV4 签名内容——再根据身份与权限得到一个私有 trust decision,最后清洗不可信的 request clone。clone 与原请求共享 trailer map,streaming checksum 不会丢失。Snowball worker 按 entry 推导信任,不继承 request-wide privilege bit。
完整设计与被否决方案记录在 鉴权前不做 I/O,Header 不产生权限。
桶元数据与 Object Lock
桶配置存放在同一个 .metadata.bin 记录中,但此前 policy、lifecycle、encryption、tags、quota、replication、Object Lock 与 CORS 使用彼此独立的锁更新。两个正确的 read-modify-write 因此可能都返回成功,后保存的一方却静默覆盖先前字段。
本版本用一个有界的 metadata.lock transaction 串行化所有整记录 mutation,同一把锁覆盖:
- 常规配置保存与删除;
- 旧元数据 migration 与 import;
- bucket 创建、
ForceCreate与站点 adoption; - healing 与 inconsistent-version repair;
- 只合并变化字段的 replication receive path。
实现没有把元数据系统改造成通用事务框架:既有 record 与 parser 保持不变,只集中 serialization boundary,并将复制导入限制为真正发生变化的字段。
Object Lock 还有第二条不变量:有效 lock 配置解析为 enabled 后,versioning 一律归一化为纯 Enabled;prefix exclusion 与 suspended 状态不能保留。判定依据是解析后的配置,不是与最小 XML 文档做字节比较,因此带 Default Retention Rule 的合法文档也无法绕过。测试覆盖 Update、读回、磁盘重载,以及两种畸形旧 versioning 状态。
IAM、策略与配置行为
- 显式版本删除按 AWS 的
s3:DeleteObjectVersion授权;复制删除保留s3:ReplicateDelete合同。 SetUserStatus与SetGroupStatus按目标状态授权,不再统一检查 enable action。- 新建或更新 named policy 与 service-account policy 时,拒绝空的 S3、S3 Tables、KMS ARN namespace、它们的历史序列化形式,以及同时含
Resource与NotResource的 statement;已存 policy 仍可加载。 - 已启用的旧 PostgreSQL/MySQL notification target 必须给出 connection string;启动现在以不含凭据的诊断失败,而不是静默丢掉所有 target。
MINIO_CONFIG_ENV_FILEparser 保留 named target、引号值与受支持的 shell-like assignment,但不会把文件当 shell 执行。
这些属于兼容性收紧,不是格式迁移。部署前必须阅读升级检查。
详细记录分别覆盖按目标状态授权用户/组操作、安全解析配置环境文件与旧数据库通知迁移的 fail-fast 设计。
组件
20260903 的依赖与配套发布线固定如下:
- Go 1.27.1
minio-go/v7: 上游兼容 pseudo-version,revision 结尾为0e78d3f18efe;临时silo-go分叉从服务端依赖图退役madmin-go/v3:v3.0.110silo-pkg/v3:v3.13.2,使用自有github.com/pgsty/silo-pkg/v3模块路径- 内嵌 Console:
v2.3.0,包含可信代理、TLS、脱敏与 WebSocket 安全修复 - 捆绑 mcli:
RELEASE.2026-09-03T07-13-05Z,保留mc兼容 alias - Helm Chart:
7.0.2;请使用正式发布的 Server 镜像pgsty/silo:RELEASE.2026-09-03T13-18-01Z与 mcli 镜像pgsty/mc:RELEASE.2026-09-03T07-13-05Z
tag 源码中的 Helm 提示: 签名 Server tag 的
helm/silo仍保留临时值RELEASE.2026-09-03T00-00-00Z。发布后提交4c164907f已把当前main上的 Chart 修正到正式 tag。若直接从 tag 源码归档渲染 Chart 7.0.2,请显式设置image.tag=RELEASE.2026-09-03T13-18-01Z;二进制与软件包不受影响。
服务端有意保留 MinIO 兼容的 Go module 与 wire identifier。替换 import target 不会改名公开 S3/Admin API、MINIO_* 配置、x-minio-* header、/minio/* route 或磁盘 metadata。
工程清理
最终发布审查删除了不保护兼容性或正确性边界的复杂度:
- 删除废弃 encryption helper、旧 handler path 与未使用 event-target function;
- 用更小的真实服务 route 兼容基线替代源码级 exported-symbol inventory;
- 删除
wait_pipelint exclusion,迁移到gomodguard_v2; - 用两个 helper 收口 CORS load-failure 生命周期,不在六条路径里分别 open-code set 操作;
- 站点复制 import 只更新发生变化的 metadata 字段;
- dynamic-timeout 测试使用私有随机源,不再修改 package-global seed;
- 保留共享 metadata lock、CORS tombstone、两级 replication trust 与对抗性测试,因为每一项都保护了已复现故障,而不是假设性的抽象。
完整对抗性复审——包括第一次“已就绪”结论之后继续发现并修复的问题——记录在 SILO Server 20260903 发布前复审。
升级检查
生产切换前请阅读从 RELEASE.2026-08-06 升级。至少完成:
- 给确实需要删除显式版本的身份授予
s3:DeleteObjectVersion;凡是用Deny s3:DeleteObject防止永久删除的策略,都要同时 Deny 新 action; - 拆分自定义管理策略中的 enable 与 disable grant;
- 重新提交 policy 前修正裸 ARN prefix;
- 给启用的旧 PostgreSQL/MySQL notification target 增加 connection string;
- 核对显式选择 checksum algorithm/type 的应用;
- 站点复制组所有成员全部升级后,再创建或修改桶级 CORS;
- 回滚前导出 CORS 配置,因为 20260806 不理解该字段;
- 分布式集群在一个维护窗口切换所有节点,混合 Silo 二进制无法成组。
对象与纠删码磁盘格式不变,但这不代表混合版本集群受支持。
已知问题与明确延期
以下事项不在本版本修复范围内:
- 条件删除(#10、PR #12)。
DeleteObject忽略 HTTPIf-Match,DeleteObjects忽略每个<Object><ETag>,都会执行无条件删除。经复审的单对象修复存在于本版本之外,但批量语义和原 PR 都不完整;发布半套 condition contract 比明确延期风险更大。 - 非 CORS 的多站点配置删除(#77)。 一个站点删除 policy、SSE、tag 或 quota 后,仍持有配置的对端可能把它恢复。单站点不受影响;CORS 使用 tombstone-aware register,也不受此缺陷影响。依赖这些复制删除的部署必须逐站核对。
ListMultipartUploads过滤(#79)。prefix类似精确 key 匹配,max-uploads、key-marker与delimiter尚未完整生效,详见兼容性分析。- 旧联邦后端
CopyObject(#99、#100)。 旧联邦后端可能忽略请求的 checksum algorithm,并拒绝 inline source object;不使用该后端的部署不受影响。 - 混合版本站点复制。 20260806 对端会接受但忽略桶级 CORS,并持续报告 mismatch;所有站点升级前不要配置 CORS。
- 回滚桶级 CORS。 20260806 重写 bucket record 时会丢掉未知 CORS 字段;先导出,重新升级后再恢复。
ILM relocation(PR #60)、更广泛的 SSE 支持(#61)、operator 发现(#30)、NATS target 热重载(#40)、Renovate(#20)等开放 enhancement 不属于本版本的生产安全边界。
验证与证据边界
完整本地验收运行在 ebac0ca73bbf251b070bb6df4d8005015841f901:
- 完整
cmd与internal测试套件; go test -race ./cmd,365.448 秒通过;- lint 0 issue、rebrand/compatibility guard、生成文件检查与
govulncheck; make verify覆盖 FS、erasure、分布式 erasure、erasure sets、多池、IPv6 多池:174 PASS / 0 FAIL。
之后只有一行代码修复 84e1580a4:GetConfig 按需重载成功后清除 CORS load-failure bit。后续依赖工作把工具链推进到 Go 1.27.1、把 x/crypto 推进到 0.56.0。在精确发布源码 9b11dc9469e650815b775cb47b039610644f5da4 上,git diff --check、完整 cmd 与 internal 测试、完整 cmd race、rebrand 与生成文件 guard、lint、govulncheck,以及远端 Go CI、VulnCheck、Test Release、Release workflow 全部通过。
最终功能验收使用四台 Ubuntu 24.04 arm64 虚拟机,每台四块 XFS 数据盘。测试覆盖 20260806 → 20260903 协调升级、回滚与再次升级;TLS 上的完整 mcli 功能脚本;1,004 个对象上传/下载 checksum 对比;单节点与 quorum loss;单盘重建;以及对象、版本、CORS、tag、quota、ILM、Object Lock、IAM、delete marker 与离线补传的双站点复制。结束时 16 块盘全部在线,没有未恢复的数据不一致。
binary/package Release 公开后,容器发布发现一处只影响交付的 pin 错误:首次 Docker workflow 在推送任何镜像前停止,因为 tag 中的 Dockerfile 已选择 mcli 20260903,却仍保留两条 20260901 归档摘要。提交 ce2326c94 与 9936a69d8 修正 pin,并新增一个收窄的恢复模式,从不可变且带 attestation 的 mcli checksum manifest 解析摘要。恢复运行 33847571968 随后使用原始 Server release 归档构建、运行、生成 SBOM attestation,并发布两个架构。classic 的 release/latest manifest 为 sha256:b616a0cf8cb281e7e6bb3c9b1fb53875b4016a2878223925541c18f82d6c5ca3;distroless 为 sha256:2711cdc5bce0ada353a4871dcda60f48f46414fdd69a45c36c71f6b7ebe1aead。
交付证据保持独立可核验,而不是从这些源码测试推断。正式发布的服务端 GitHub Release 标识精确标签源码,以及经过验证的归档、软件包、checksum、SBOM 与 provenance;classic 与 distroless 镜像均发布一致的 amd64/arm64 manifest。独立发布的 mcli Release 不可变,包含 19 个已验证资产,并发布一致的 amd64/arm64 版本镜像与 latest;共享包 v3.13.2 与 Console v2.3.0 各自保留独立发布证据。
已解决事项台账
发布准备期间已经完成 tracker 收口:核心问题关闭,刻意排除的工作留在独立 open issue 中:
| 跟踪项 | 解决方案 |
|---|---|
| #102 | 已由合并的 PR #103 关闭:共享 metadata.lock,完整覆盖 writer、migration、adoption;需要先复现的残余审计拆到 #105 |
| #58 | 已由合并的 PR #104 关闭:显式版本授权、multi-delete auth/audit context 与 least-privilege replication;PR #59 作为被替代实现关闭 |
| #46、#47、#48、#50 | Multipart checksum 选择、计算、响应、校验与错误 |
| #32、PR #37 | missing-bucket listing shortcut 返回 NoSuchBucket |
| PR #57 | 所选 client/server stack 已提供 CompleteMultipartUploadResult.ChecksumType |
代表性变更
1c9a2431f至13e6458d9:实现桶级 CORS 与站点复制938603458至04b097fd9及 Snowball follow-up:认证复制语义,消除预鉴权 metadata I/Of9f9fa6c9至32a1b81e4:复现并串行化跨类型桶元数据更新3b5de82f5、21646eebd:保证 Object Lock 的 versioning 不变量,覆盖 retention-rule 文档f8b598f1d至d2d47a41f:对齐显式版本删除授权b73581b05、474cd5801、74c97d005:认证 SSE-C 零字节与 attributes 读取7fea6d5a5、5d152416d、7e079ff05、d28885d0e:对齐 multipart checksum 行为c0e715977、e73436c99、ffb70eb37:修复 CopyObject transform、checksum 与 SSE-C rotation84e1580a4:metadata 按需重载成功后解除 load-failure guard
致谢
本版本吸收了社区贡献者提交的问题与修复方案,也包含分叉自身的安全与兼容性审计。checksum、missing-bucket listing 与显式版本授权等工作都从公开 issue/PR 开始。最终形态还经过对抗性复审:先复现再修复;把继承限制与本轮回归分开;并在与声明对应的树上重跑验证。
完整作者记录见 CONTRIBUTORS.md。