跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

发布注记

SILO 各个正式版本的详细发布说明,按时间从新到旧排列。

每个 SILO 正式版本均有独立页面,记录发布日期、主要变更、安全修复、依赖更新与相关提交。

1 - Silo Console 2.1.0 发布

双语控制台:零依赖的中英文界面覆盖全部页面,仪表盘迁移到 MinIO Metrics V3 并显式处理零值语义,另有一批正确性修复——包括转义安全的占位符替换,以及不会说谎的全选框。

发布日期: 2026-08-06 · 版本: v2.1.0 · 仓库: pgsty/silo-console

SILO Console 2.1.0 是独立发布 2.0.0 之后的第一个功能版本,做了三件事:

  1. 会说两种语言——全部控制台页面、帮助条目与文档链接都能以中文或英文呈现,切换按钮出现在每一页,且不引入任何新的运行时依赖;
  2. 读对了指标——仪表盘从 MinIO Metrics V2 名称迁移到 V3,并针对 V3 在底层改变的语义逐条做了显式处理;
  3. 在边界情况下不再说谎——全选框与批量操作作用于同一批对象,占位符能扛住包含 $& 的对象名,时间戳带上了时区,空指标显示"无数据"而不是编造出来的 0

这是一个 小版本。环境变量、模块路径、API 契约、二进制名称和数据布局均无变化,升级就是换二进制或换镜像。

说明

同日已发布 2.1.1 补丁

v2.1.1 与本版本同日发布,补全了下文所述的图例加固:图例构造器无法解析的标签占位符会被直接移除,而不是把字面花括号漏进 Traffic 图表的图例;最后一处替换分支也完成了转义加固,标签值中的 $&$1 不会再被当作替换指令;License 页面显示的版本号也从 2.0.0 修正为实际版本。除此之外没有任何变化——直接升级到 2.1.1 即可,本文所有内容照旧适用。

说明

如果你内嵌了这套控制台,请重新生成嵌入资产

2.1.0 修复了 2.0.0 之后 main 分支上的一个打包缺陷:go:embed 负载中仍是 2.0.0 的前端构建产物,因此从中间提交构建出的二进制会提供旧版界面。2.1.0 的正式发布产物基于重新生成的负载构建,不受影响。

双语控制台

这是一套对象存储的管理界面,而它的运维使用者中有相当一部分以中文为第一语言。2.1.0 在不引入 i18n 框架的前提下把界面变成双语——嵌入式交付意味着每一 KB 都要计入二进制体积。这对应 issue #6:该 issue 原本提议使用 i18next,而"零依赖"是本次实现相对它唯一一处有意的偏离。

实现方式

设计约束是:不加新依赖、不加构建步骤、不引入字符串抽取流水线,并且 部分覆盖绝不能让页面出错

  • 英文原文就是字典的 keyt("Create Bucket") 查找对应的中文条目;查不到则原样返回英文。因此覆盖度可以增量生长,写错 key 的后果是退化成英文,而不是暴露 console.bucket.create 这样的裸标识。
  • 三份字典,一次合并zh.ts(165 条界面框架)、zhHelp.ts(247 条帮助内容)、zhScreens.ts(1373 条功能页面)合并时以框架优先,合计约 1785 条。
  • 语言偏好完全复用暗色模式的模式localStoragesystemSlicesetLanguage不做浏览器语言探测,默认英文,选择完全显式。
  • 集中拦截而非逐点改写:页头包装器、确认对话框、帮助条目、路由定义、仪表盘面板渲染器各自在输出的最后一步翻译。这正是 220 个页面文件能够在不触碰业务逻辑的情况下完成本地化的原因。
  • 模块拆分是必要的i18n/lang.ts 只存放纯函数原语(translatelocalizeUrl)且不导入 store——systemSlice 依赖它,反向导入会形成循环依赖。Hooks(useTuseLanguageuseLocalizedLink)与 interpolate() 放在 i18n/index.tsx

切换控件是一个描边风格的 文/A 图标,挂载在所有页面的页头,登录页复用同一控件。

覆盖范围

登录与 SSO 流程、导航与命令面板、仪表盘与全部指标面板、存储桶与完整对象浏览器(上传、预览、分享、版本、回溯)、用户/用户组/策略/访问密钥、配置与事件目标、IDP 与 KMS、日志、健康报告、性能测试、性能剖析、对象检查、跟踪、监视,以及许可证页面。

除可见文本之外:

  • 文档链接会本地化silo.pgsty.com 的链接在中文下加 /zh 前缀;Pigsty 站点做域名对调(pigsty.iopigsty.cc)。GitHub、MinIO、AWS、YouTube 链接保持不变。
  • 帮助面板的博客源按语言区分,中文下拉取 /zh/blog/index.xml,并为每种语言维护独立缓存。
  • 命令面板在两种语言下都能搜到。菜单项显示时翻译,但保留英文原文作为关键词,因此"桶"和 “buckets” 都能命中。
  • 图表图例只翻译静态前缀translateLegend 保留 [server:drive] 这类实例后缀;数据层保留原始图例,所以那些依赖图例做数值匹配(容量求和)的组件继续正常工作。
  • 时间戳做的是统一,而不只是翻译,详见下文。

代价

嵌入负载增加约 61 KB(2.79 MB → 2.85 MB,+2.2%),零新增依赖,字典进入独立的按需加载分块。英文渲染路径字节稳定:使用默认语言时,输出与 2.0.0 完全一致。

仍然是英文的部分

后端错误信息(182 条)由 Go 服务端产生,前端无法翻译。少量硬编码在 vendored mds 组件库内部的字符串——收起态菜单的 “Sign Out” 提示,以及数据表格的 “Columns”、“Loading…” 和 ON/OFF 开关——仍是英文;其中两处(“Sign Out”、“Actions:")通过作用域 CSS 规则做了中文替换,其余需要改动 vendor 才能处理。

Metrics V3 迁移

仪表盘此前查询的是 MinIO Metrics V2 名称,而 SILO 部署抓取的是 V3/minio/metrics/v3)——也就是说,仪表盘依赖的是监控流水线已经不再采集的端点。2.1.0 将全部 26 个部件 重写到 V3 目录——31 条查询,涉及 29 个不同的指标名——并移除三个从未被任何布局引用的部件(51/61/62)。这对应 issue #7,Info 页面的那一半是 #8

这里的决定是 V3 only:不做运行时回退、不做探测、不提供版本选择开关。SILO Console 面向的是 SILO 部署,服务端、抓取流水线与控制台是一同交付的。SILO 服务端继续为外部消费者提供 V2 端点,只是控制台不再使用。回退机制在这里反而有害——保留 15 天 V2 序列的指标库会让 or 回退悄悄读到过期数据。

V3 改变的语义

有三条 V3 特性会让"照名字改写"的迁移出错,每一条都需要明确的应对:

  1. 集群组指标由每个节点重复导出/cluster/* 指标不带 server 标签,也不做 leader 门控,因此 N 节点的抓取会得到 N 条重复序列。查询统一用 max()/min() 聚合——绝不能用 sum(),那会把集群总量乘以节点数。
  2. 零值根本不导出。任何取值 ≤ 0 的指标都会被跳过。离线磁盘数、修复中磁盘数、纠删集健康状态不是报 0,而是直接消失——统计卡片会渲染成空白面板。所有受影响的查询都配了伴随守卫,让面板读出真实的 0
  3. 完全不存在 minio_heal_* 命名空间。V2 的修复活动信号本身就是内存态的:重启即清零,任何扫描都会刷新它。它被两张语义可辩护的卡片取代:纠删健康(以写入法定人数为基线)和 用量数据时效(扫描器用量快照的陈旧程度)。

零值语义

这次迁移经过了一轮对抗性审查,产出 8 项发现,全部在发布前修复。它们共享同一个主题——区分 无数据尚未扫描

  • 容量 的空闲/已用以恒定存在的总量为基线,因此写满的集群显示 0 空闲,而不是整个消失。
  • 在线磁盘 针对全部离线的场景加了守卫——恰恰是最需要看到这个数字的时候,零值跳过会抹掉面板。
  • 桶与对象计数 改用用量组自身的新鲜度指标做守卫,因此尚未完成首次扫描的集群显示 无数据,而不是编造一个 0
  • 空的单值结果 渲染为 ,而不是 0
  • 空的大小分布 不再伪造七个零高度的柱子。
  • 小数速率保持可见parseFloat 轴域、两位小数的 CPU 格式化器),不再被压成 0
  • 不足一秒的用量数据时效 收敛到"1 秒”,而不是渲染成空白。

回归测试套件(api/admin_info_metrics_test.go)现在把每条部件查询钉死在 V3 目录上,校验部件 ID 唯一性,并强制执行逐部件的守卫分类法:健康与流量类需要在线节点数伴随项,用量计数类需要用量组新鲜度伴随项,容量类需要总量基线。完整映射记录在 docs/metrics-v3.md

顺带修复

  • 部件 17 把 sent_bytes 查了两次,部件 11 把 syscall_read 查了两次——两组节点间/系统调用的收发配对都退化成了重复项。
  • 无标签矩阵(max() 聚合的结果)序列化时 完全没有 metric 字段,导致前端的标签提取崩溃,表现为容量环图显示 0 B、用量增长图为空。已加守卫。
  • 一个从未被使用的逐部件 Prometheus label-values 预取请求,让每次部件请求最多多等一秒。已删除。
  • 仪表盘的用量卡片、图表控件以及密集的流量/资源面板按统一语法重建,现在在平板宽度下也能正常重排。

工作中还发现两个 服务端 缺陷,选择上游跟踪而非在此绕过:minio_cluster_usage_buckets_since_last_update_seconds 发出的是纳秒(对象变体是正确的),以及 V3 桶级发送/接收流量被对调。

正确性修复

能扛住真实对象名的占位符

String.prototype.replace 会把 替换值中$&$'$`$1 当作指令解释。而 S3 的 key 合法地允许包含 $。于是一个名为 report$&.csv 的对象不会按原样渲染——它会把匹配到的占位符文本重新注入输出,破坏整条消息。全部 37 处 字典占位符替换现已改为传入函数形式的替换值,函数形式不做任何此类解释。这是原本英文界面里就存在的潜在缺陷,并非 i18n 引入;只是 i18n 审计把它找了出来。

名副其实的全选

vendored 数据表格在缺少 onSelectAll 时会渲染一个无法翻译的纯文本 “Select” 表头——七张可选表格全都如此。更麻烦的是,直觉的修法是错的:直接用可见行替换整个选择集,会 丢掉被当前过滤条件隐藏的行,于是表头复选框与随后的批量操作可能作用于不同的集合。实现只切换当前可见行,并保留被过滤隐藏的选择,因此表头状态不可能再暗示一个与实际操作对象不同的集合。

带时区的时间戳

桶、对象、版本、回溯与访问密钥的时间戳此前混用冗长英文格式,并且有几处使用 不带 AM/PM 的 12 小时制——这根本是歧义的。现在它们在两种语言下统一渲染为 yyyy-MM-dd HH:mm[:ss] (ZZZZ)

扛得住实时数据的翻译运行时

t() 同样会收到运行时字符串:User-Agent、RSS 标题、对象名。由此做了两项加固:

  • 未命中时 无条件原样返回——隐式的 @context 后缀剥离被移除,因为它会悄悄改写恰好含有 @ 的实时数据;
  • 字典查找加上 hasOwnProperty 守卫,因此恶意输入即便命中继承自 Object.prototype 的成员(constructortoString)也无法把函数泄漏到界面上。

交互与可访问性

  • 会话过期后打开深链会在 /login 之间 来回弹跳,不断累积重定向链,而不是干脆落到登录表单上(#1)。
  • 收起态的侧边栏按钮没有可访问名称,屏幕阅读器只能报为未命名控件(#4)。访问密钥输入框现在显式声明 autocomplete 意图,而不是让密码管理器去猜(#5)。
  • 移动端的指标与存储桶面板改为滚动,不再被裁切(#3)。
  • 性能测试的控件行改为换行而不是溢出卡片,时长可填秒或分钟,大小的默认单位改为 MiB 以匹配其自身的单位列表。
  • 侧边栏桶列表的虚拟行距与 44px 的行高对齐,选中与悬停高亮不再互相重叠。
  • 单位标签渲染所选单位的 显示名,而不是原始取值。

没有 SUBNET,没有遥测

上游已移除 Subnet、Registration 与 Call Home,本项目继承了该状态,但仍残留三处痕迹。2.1.0 予以清除:

  • 健康诊断 websocket 的 subnetResponse 字段从来就不指向任何 subnet——它只是一个"报告已生成"的哨兵值——现改为 reportStatus: "ok"
  • 两条帮助文案声称健康报告"会自动上传到 SUBNET"、检查输出"传输到 SILO SUBNET"。两者都不属实。它们现在描述真实行为:报告在部署端生成,由浏览器下载;
  • 删除从未被引用的 CONSOLE_SUBNET_PROXY 常量。

顺带说明,2.1.0 的出网行为没有变化,仍然是:无分析、无遥测、无埋点、无外部脚本与字体silo-console update 依旧禁用。版本目录仅在显式设置 SILO_RELEASE_SERVICE_HOST(或 RELEASE_SERVICE_HOST)时才会连接——没有默认值。浏览器唯一的自动出网请求是帮助面板的博客源,且只在用户打开 Blog 标签页之后发生。

升级指南

没有任何需要迁移的内容。2.0.0 到 2.1.0 之间,环境变量、模块路径、协议字段、systemd 单元、二进制名称与数据布局均无变化。

install -m 0755 silo-console-linux-amd64 /usr/local/bin/silo-console

有两点值得知道:

  • 仪表盘现在要求 Metrics V3。如果你的 Prometheus 只抓取 V2 端点,仪表盘面板会显示无数据。请把抓取目标指向 /minio/metrics/v3;由 Pigsty 管理的部署已经如此。
  • 语言默认为英文,按浏览器选择并存入 localStorage。不存在服务端默认值,也不做浏览器语言探测,因此现有部署升级后外观不会发生变化。

验证范围

打标签之前,完整变更集经过审阅,并针对最终代码树执行了以下门禁:go buildgo vetgolangci-lint(0 问题)、全部 Go 包的单元测试、gofmt、TypeScript 类型检查、前端生产构建、全量 Prettier 检查、字典重复 key 检查,以及对完整 diff 的调试残留扫描。

29 个过程提交通过纯树操作重组为 20 个逻辑提交,重建后的分支顶端与重写前的代码树验证为 逐字节一致。嵌入负载从干净目录重建两次并确认字节一致——这正是发布流水线零差异门禁所依赖的性质。重写前的历史保留在备份引用中。

Metrics V3 迁移另外接受了一轮由独立模型执行的对抗性审查,8 项发现全部修复(见零值语义);其查询在含真实集群数据的线上指标库上做过验证。

已知限制

  • SSO 端到端测试套件依赖外部 OpenLDAP/Dex/MinIO 拓扑,本轮未在该环境中运行;OIDC 代码路径已由单元测试覆盖。
  • 后端错误信息与若干 vendored mds 组件字符串仍为英文(见仍然是英文的部分)。
  • 中文翻译覆盖控制台自身的界面;帮助条目正文已翻译,但它们所链接的文档页面遵循文档站自身的语言覆盖情况。
  • 两个服务端 V3 指标缺陷(桶用量时效的纳秒单位、桶级流量对调)在上游跟踪,控制台侧未做绕过。
  • 自动自更新仍然禁用,升级需要显式执行。

已关闭的 Issue

2.1.0 关闭了针对 2.0.0 提出的全部 issue。每个 issue 在 tracker 上都留有一条评论,说明修复方式、涉及的提交,以及补充的测试覆盖。

Issue 解决方式
#1 — 未认证深链无限递归 /login 改为绝对且感知 base path 的登录目标;补充深链与子路径部署的测试
#2 — Uptime 陈旧、图例畸形、菜单局促 Uptime 取自真实服务器状态,图例改用 V3 的 name 标签解析,图表控件 32 px,弹出菜单设最小宽度
#3 — 390 px 视口裁切内容 指标标签页改为可横向滚动;桶列表在移动端使用明确的列宽预算
#4 — 收起态侧边栏按钮无名称 标签改为视觉隐藏而非从可访问性树中移除;折叠开关具名且可键盘操作
#5 — 访问密钥字段缺少 autocomplete 元数据 在独立的自动填充 section 中声明 username / new-password 字段级 token
#6 — 中英文本地化 手写双语层,零新增依赖,以英文原文为 key 兜底
#7 — 监控查询迁移到 Metrics V3 仅 V3;26 个部件、31 条查询、29 个指标名,配套守卫分类与回归测试
#8 — 用可用的 V3 健康信号替换 N/A Erasure Health 与 Usage Data Age,与高级仪表盘共用同一份部件数据

有三项验收标准如实记为未达成,而不是含糊勾掉:web-app 目前没有单元测试运行器,因此 #6 的 i18n 测试套件与 #2 中针对 constructLabelNames 的专项测试都需要先引入测试工具链;另外 #6 要求的"如何新增翻译 key"的贡献者文档尚未编写。

v2.1.0 的完整变更由以下 20 个逻辑提交构成。v2.1.0 标签另外还带有三个更晚的文档提交,它们重写了仓库 README,不改变任何已交付的行为。

  • 8764f5d — fix(web): stop recursive login redirects
  • 437c56c — fix(ui): make the dashboard and bucket list usable on narrow screens
  • 85fc0c6 — fix(a11y): name collapsed sidebar controls and credential fields
  • e3fed07 — fix(metrics): rebuild dashboard cards, chart controls, and layout
  • fa11576 — feat(login): polish controls and legal attribution
  • 9fc17c1 — feat(i18n): add hand-rolled EN/ZH core, dictionaries, and language toggle
  • 622c02e — feat(i18n): localize login, navigation, and the help system
  • 6a03719 — feat(i18n): localize dashboard and metrics screens
  • 14b1c2d — feat(i18n): localize bucket and object browser screens
  • 0298062 — feat(i18n): localize identity, configuration, and event destinations
  • 41094f6 — feat(i18n): localize observability, admin tools, and shared components
  • e964992 — feat(metrics): migrate the dashboard to MinIO Metrics V3
  • 0b2251f — fix(i18n): harden the translation runtime for live data and chart legends
  • 9b60148 — fix(console): unify timestamps on a timezone-carrying standard format
  • bf110ae — fix(console): give selectable tables a visible-rows select-all
  • 5fc8f22 — fix(i18n): escape-proof all placeholder substitutions
  • fef8fab — fix(console): polish speedtest, sidebar, and help chrome
  • c4911e8 — chore(console): drop SUBNET remnants from health reporting
  • 1d631c4 — docs: record the SILO Console v2.1.0 changelog
  • 912d847 — build: regenerate optimized embedded web assets

相关链接:

2 - Silo Console 2.0.0 发布

SILO Console 首个独立主版本:完成品牌与发布链路迁移,全面重塑登录页与控制台界面,嵌入资产从约 10MB 压缩到 3.5MB,清零已知依赖漏洞,并修复多处上游遗留缺陷。

发布日期: 2026-08-04 · 版本: v2.0.0 · 仓库: pgsty/silo-console

SILO Console 2.0.0 是这套对象存储管理控制台以独立项目身份发布的第一个主版本。它从 georgmangold/console 的 v1.9.1 维护线继续演进,完成了三件事:

  1. 建立独立身份——产品名称、视觉系统、文档入口、源码归属与发布链路全部迁移到 SILO 项目体系,同时刻意保留 Go 模块路径、环境变量等兼容契约;
  2. 重塑用户界面——登录页、主题系统、仪表盘与全站细节按统一的设计语言重新打磨,配套全新的品牌图标集;
  3. 强化工程质量——嵌入式前端资产从约 10MB 压缩到 3.5MB,已知依赖漏洞清零,并修复了包括运行时数据竞争在内的一批上游遗留缺陷。

发布前,本版本经过了两轮独立审查:一轮完整的代码审查与提交历史重组,以及一轮对抗性复核(穷举资产校验、HTTP 语义探测、全站路由回归与发布产物冒烟测试)。

警告

升级前先看兼容边界

2.0.0 的主版本变化发生在 公共身份和交付契约 上,而不是对象数据格式或 S3 协议上。使用旧仓库、旧发布二进制名或旧容器镜像名的安装脚本必须更新;使用 CONSOLE_MINIO_SERVERCONSOLE_MINIO_REGIONgithub.com/minio/console 或 MinIO-compatible Admin API 的现有集成则不应做全局替换。

为什么是 2.0.0

这套控制台最初源自 MinIO Console,随后由 Alevsk/consolegeorgmangold/console 两条社区维护线继续发展。SILO Console 在此基础上由 Pigsty 社区接续维护,为 SILO 提供浏览器管理界面。

版本号从 v1.9.1 提升到 v2.0.0,主要是因为以下对外契约同时发生变化:

  • 产品名称统一为 SILO Console,主仓库迁移到 pgsty/silo-console
  • 正式发布二进制从 console 改为 silo-console,容器镜像迁移到 ghcr.io/pgsty/silo-console
  • 发布资产、校验和、软件包元数据、命令行说明与项目链接全部切换到 SILO;
  • 界面中的项目身份、帮助入口、版权归属、源代码供应与商标说明重新建立。

2.0.0 采取的是"对外身份清晰、对内兼容克制"的迁移策略:需要运维人员明确感知,但不对底层兼容接口做机械式改名。

名称与交付契约

范围 旧名称或旧位置 2.0.0 契约
产品 Console / MinIO Console 的遗留表述 SILO Console
源码仓库 georgmangold/console pgsty/silo-console
正式二进制 console silo-console
容器镜像 ghcr.io/georgmangold/console ghcr.io/pgsty/silo-console
二进制资产 console-<os>-<arch> silo-console-<os>-<arch>
校验和文件 console_<version>_checksums.txt silo-console_<version>_checksums.txt
网站与文档 上游或前维护者入口 silo.pgsty.comsilo.pgsty.com/docs/

命令行程序的作者、用途、帮助文本和项目描述已切换为 Pigsty 与 SILO Console。DEB/RPM/APK 软件包的厂商、维护者、主页、描述与许可证元数据相应更新,可执行文件安装到 /usr/local/bin/silo-console

刻意保留的兼容标识

以下名称虽然包含 minio 或沿用旧的 console,但它们是接口、协议或安装兼容层的一部分,不属于遗漏的品牌文本:

兼容面 2.0.0 中的状态 原因
Go 模块 保持 github.com/minio/console 改动会破坏全部 Go import 与生成代码
服务端地址 保持 CONSOLE_MINIO_SERVER 现有部署广泛使用的环境变量
服务端区域 保持 CONSOLE_MINIO_REGION 现有部署兼容契约
其他配置 既有 CONSOLE_* 变量继续有效 避免无收益的配置迁移
S3/Admin API 名称 保留 MinIO-compatible 字段与枚举 它们描述实际协议和 SDK 接口
源码开发产物 make console 仍生成 ./console 保持开发工作流和脚本兼容
软件包 systemd 单元 保持 minio-console.service 避免升级时出现两个服务或丢失原服务状态
systemd 用户与配置 保持 console-user/etc/default/console 避免不必要的账户和配置文件迁移

因此,升级脚本不能简单执行全仓库或全配置的 minio → siloconsole → silo-console 替换。未来若要迁移这些兼容接口,需要提供别名、弃用周期和明确的双读策略;2.0.0 不做这件事。

全新界面

2.0.0 不是换个 Logo 的品牌迁移,而是对整套界面的重新设计。

登录页

登录页完全重写:左侧品牌面板以纯 Canvas 生成缓慢流动的正弦光网动画(零外部依赖,遵循 prefers-reduced-motion,切至后台标签页时暂停),文案以 “Keep the S3 Interface / Own the Object Store” 呈现项目主张,底部保留完整的 MinIO 商标声明;右侧表单功能与既有自动化测试选择器完全不变。SILO 字标所用的 Chakra Petch 字体以约 20KB 的本地子集打包,不产生任何外部网络请求。

统一主题系统

控制台的全部颜色收敛到一个亮暗两套的主题层:中性灰阶承载正文与边框,品牌钢蓝色承载主操作与选中态,侧边栏在明暗模式下统一使用与登录页同源的深色系。表单控件与卡片采用统一的圆角与过渡,输入框获得键盘焦点光环,模态框有入场动画(同样遵循 reduced-motion)。服务端下发自定义样式(customStyles)的优先级保持不变。

控制台细节

  • 仪表盘(Metrics):统计卡片按统一语法重构——弱化标签、等宽数字、状态圆点对齐;环形图与信息条接入主题;移除了上游实现中的绝对定位布局。
  • 空态统一:Watch、Trace、桶事件/复制/生命周期等所有数据面板的占位文本统一为居中弱化样式,不再是左上角的裸文本。
  • 垂直选项卡:桶详情等页面的选项卡从带边框的灰色矩阵改为安静的药丸列表,并消除了栏底的空白残留格。
  • 许可证页:新增 VERSION 区,同时显示所连接服务端的版本与 Console 自身版本;无 admin:ServerInfo 权限的账号不会发起请求,该行自动隐藏。页面同时集中说明 AGPLv3 授权、AGPL 第 13 节下的源码获取权利、来源谱系与商标边界。
  • 一批交互修复:移动端首次加载即收起侧边栏(原先要等窗口 resize 事件);侧边栏底部导航不再在窗口高度变化时延迟跟随;桶列表手风琴的高亮条铺满整行;仪表盘在窄屏下不再产生隐式横向溢出;帮助面板改为真正的按需加载——登录页不再向任何外部站点发起请求。

品牌图标集

favicon、PWA 与 Apple Touch 图标此前仍是上一代手绘徽标的 PNG 导出。2.0.0 将全部尺寸(ico 16+32、favicon 16/32/96、apple 180、manifest 192/512)从官方 silo.svg 矢量徽标重新光栅化,主屏尺寸带防裁切安全边距;Web App Manifest 裁剪为现代图标集,移除 2014 时代的 legacy density 条目。图标总体积从 473KB 降至 160KB,浏览器标签页图标从此与站内品牌完全一致。

更小、更快

嵌入式交付是这套控制台的核心形态——前端资产通过 go:embed 打进二进制。2.0.0 对这条链路做了系统性优化:

  • 嵌入负载从约 9.6MB 降至 3.5MB。文本资产(JS/CSS/SVG 等)在构建期以确定性 gzip 预压缩后嵌入;仅被现代浏览器忽略的 legacy WOFF 字体(约 1.25MB)、以及一批完全未被引用的孤儿图片资产被移除。
  • 首屏传输从约 5.7MB 降至约 1.7MB。此前静态资产完全未压缩传输;现在预压缩资产直接以 Content-Encoding: gzip 发出(零运行时压缩开销),对极少数不接受 gzip 的客户端动态解压回退。
  • 正确的 HTTP 语义。Accept-Encoding 按 RFC 9110 完整解析 q 值(gzip;q=0 会得到未压缩内容),响应携带 Vary: Accept-Encoding;静态路径与 SPA 入口对非 GET/HEAD 请求返回 405 并带 Allow 头。
  • 可复现构建。压缩使用纯 JS 实现(fflate)以保证跨平台字节级确定性;发布流水线新增强制门禁——在干净环境重建嵌入资产后必须与提交内容零差异。

发布二进制(含全部前端资产、strip 后)约 35–40MB;对下游 SILO 服务端而言,内嵌这套控制台的体积代价从约 10MB 降到约 3.5MB。

安全与依赖

Go 侧:构建基线升级到 Go 1.26.5,golang.org/x 系列全部更新至最新。govulncheck 报告的全部可达漏洞已清零:

依赖 修复版本 公告
google.golang.org/grpc v1.82.1 GO-2026-6061
github.com/prometheus/prometheus v0.311.3 GO-2026-5710 / -5662 / -5381 / -5264(含远程读 DoS)
github.com/klauspost/compress v1.18.7 GO-2026-5841

唯一剩余公告位于 golang.org/x/crypto,官方尚未发布修复且代码路径不可达,作为已知事项记录。

前端侧:生产与开发依赖树的完整审计清零,包括 form-data 的高危 CRLF 注入、DOMPurify 与 qs 的多项公告;React Router 迁移至 7.18.2(保留 v6 兼容的声明式 API,全站路由经过完整回归验证)。唯一被显式豁免的公告仅涉及本项目未使用的 unstable API。

运行时正确性:修复了 HTTP 日志目标在初始化与关闭之间的真实数据竞争,以及测试套件中共享 mock 的竞态;受支持的 Go 包全量通过 -race 检测。作为附带收益,go-m1cpu 升级修复了新版 macOS 上本地 go run 的 cgo 崩溃。

更新检查与默认网络行为

本版本对升级和版本目录功能采取保守默认:

  • silo-console update 的自动自更新被禁用,命令只给出提示,不会下载或替换二进制;
  • 版本目录新增 SILO_RELEASE_SERVICE_HOST 配置,原有 RELEASE_SERVICE_HOST 作为兼容回退;两者均未设置时不连接任何远端版本服务;
  • 帮助面板的 Blog 内容仅在用户打开时按需拉取,跳转链接只接受 https://silo.pgsty.com

自动更新会在发布资产签名与回滚链路稳定后再重新评估。

发布产物与平台矩阵

正式发布包含 16 个资产:

类型 覆盖范围
独立二进制 Linux amd64/arm64/arm、macOS amd64/arm64、Windows amd64
系统软件包 DEB / RPM / APK × amd64/arm64/armv6
校验和 silo-console_2.0.0_checksums.txt(SHA-256)

发布流水线在 tag 推送时触发,工作流的第三方 Action 已固定到具体提交,并在构建前强制执行"干净检出 + 资产重建零差异"门禁。

升级指南

独立二进制

install -m 0755 silo-console-linux-amd64 /usr/local/bin/silo-console
/usr/local/bin/silo-console server

从源码构建时,make console 仍生成 ./console;用于正式服务前按发布名称安装。

DEB/RPM/APK 与 systemd

软件包继续安装 /etc/systemd/system/minio-console.service,单元内部启动 /usr/local/bin/silo-consoleEnvironmentFile=/etc/default/consoleconsole-user 与既有 CONSOLE_* 变量不变。这个保留让软件包升级继续作用于原有服务,而不是平行创建一个新服务。

配置与集成

  • 不要重命名 CONSOLE_MINIO_SERVERCONSOLE_MINIO_REGION
  • 不要修改 Go import 中的 github.com/minio/console
  • 自建版本目录优先迁移到 SILO_RELEASE_SERVICE_HOST
  • 依赖 console update 的脚本改为显式下载、校验并部署发布资产;
  • 按进程路径识别服务的监控更新为 /usr/local/bin/silo-console

本版本不改变对象数据布局,也不要求对存储桶和对象执行迁移。

双重审查与验证范围

2.0.0 在发布前经过两轮独立审查。第一轮完成了全量代码审查、缺陷修复与提交历史重组(13 个过程提交整理为 8 个逻辑提交),并执行了 Go 全包 -racego vetgolangci-lintgovulncheck、前端类型检查、生产构建、Prettier、死代码检查与完整依赖审计。第二轮为对抗性复核,独立重跑核心门禁并补充:

  • 对全部 184 个嵌入文件各发起 gzip 客户端、普通客户端与 HEAD 三种请求,响应体与嵌入源做逐一哈希比对;
  • RFC 语义探测(含 gzip;q=0, *;q=0.5 等组合 q 值)、方法限制、OIDC 回调与 SPA 深链;
  • React Router 7 全站路由回归:深链、客户端导航、桶详情选项卡切换与浏览器历史后退;
  • 移动端首屏侧边栏行为、登录页外部请求监听、明暗主题全站巡回;
  • 下载正式发布资产验证校验和逐字节匹配、二进制版本自报一致,并用发布产物直连真实服务端完成冒烟测试;
  • macOS 与 Linux 双平台的资产重建零差异验证。

改写前的完整历史保留在仓库的备份引用中,可随时回滚。

已知限制

  • 自动自更新暂时禁用,升级需要显式执行;
  • SSO 端到端测试套件依赖外部 OpenLDAP/Dex/MinIO 拓扑,本轮未在该环境中运行(OIDC 代码路径已由单元测试与 HTTP 层验证覆盖);
  • golang.org/x/crypto 存在一条官方尚未发布修复、且代码路径不可达的公告;
  • SILO 尚未维护独立的视频资料库,帮助面板中的视频是明确标注的上游兼容性资料;
  • 管理能力依赖 MinIO-compatible Admin API,不能把 SILO Console 当作适用于任意 S3 服务的通用浏览器;
  • 保留的 Go 模块、环境变量、协议字段和 systemd 服务名仍会在代码、配置和进程管理界面中出现。

v2.0.0 的完整变更由以下 8 个逻辑提交构成:

  • 50797de — feat: establish SILO Console identity and compatibility
  • 23ae6e8 — feat: redesign and harden the SILO Console web app
  • 7a83a77 — build: update Go toolchain and dependencies
  • 1330d25 — fix: eliminate logger shutdown and test mock races
  • 06b3a34 — docs: publish the SILO Console v2.0.0 guide
  • 4b24372 — build: regenerate optimized embedded web assets
  • c38eb64 — ci: package and publish SILO Console v2 releases
  • b952a12 — brand: regenerate the icon set from the official silo.svg emblem

相关链接:

3 - Silo Pkg 3.11.0 发布

本分支的首个定版:恢复被打破的 IAM 桶/对象资源边界——一条只该管对象的授权曾能触及桶级写操作;同时包含策略条件键绕过与三个 LDAP 连接缺陷的修复;并在发现旧标签与上游同号版本撞车后,重新编号到上游的 3.11 线。

发布日期: 2026-08-04 · 版本: v3.11.0 · 提交: d8b1fa7 · 仓库: pgsty/silo-pkg

这是本分支的 第一个定版。它恢复了上游 minio/minio#20449 所报告的 IAM 桶/对象资源边界:策略条件键绕过修复、三个 LDAP 连接缺陷、证书监听器泄漏、有种子 RNG 的缺陷,以及模块真实的最低 Go 版本。

警告

升级前需要确认两件事

  1. 本版本收紧了鉴权。 十二个桶级写操作不再能通过 arn:aws:s3:::bucket/* 这样的对象级资源模式被授权。如果你自己编写桶级策略,请阅读 IAM 桶/对象边界——受影响者只需改一行策略,而 MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 可完整恢复原有行为。
  2. 条件键修复仍需服务端另一半。 本版本的策略解析改动与服务端"保留内部条件键名"的改动各自覆盖问题的一半。服务端配套改动位于 pgsty/minio 提交 2f55347f7,但尚未进入公开的 origin/master,也没有任何已发布的 Silo 服务端版本包含它。请确认后续服务端发布说明明确包含该改动。

这个仓库是什么

silo-pkgminio/pkg 的维护分支,为社区版 MinIO 分支提供上游(现由闭源产品驱动)不会再接纳的修复。仓库于 2026-08-02 由 pgsty/minio-pkg 改名而来。

模块路径刻意保持不变,仍然是 github.com/minio/pkg/v3,因此所有 import "github.com/minio/pkg/v3/..." 无需改动,只有 replace 指令的右侧需要更新:

replace github.com/minio/pkg/v3 => github.com/pgsty/silo-pkg/v3 v3.11.0

/v3 后缀是模块的主版本号,不是目录名,不可省略。这也正是本次发布编号为 v3.11.0 而非 v4.0.0 的原因:Go 要求标签的主版本必须与 go.mod 中声明的主版本后缀一致,因此在一个 .../v3 模块上打 v4.0.0 会被工具链直接拒绝。真要发布 v4,就必须修改模块路径,并改写服务端、mc 与 Console 中约 395 处 import——那等于放弃"保留上游路径"所换来的直接替换能力,而这正是保持上游路径的意义所在。

IAM 桶/对象边界

每一个桶级 S3 操作,鉴权时对象名都是空的。IAM 匹配器把它拼成资源串,而对空对象名的情况补了一个尾斜杠:

resource.WriteString(args.BucketName)
if args.ObjectName != "" {
    // "bucket/object"
} else {
    resource.WriteByte('/') // "bucket/"  <-- 缺陷所在
}

"bucket/" 会被通配模式 "bucket/*" 命中,因为 * 匹配空串。于是一条把 s3:* 授在 arn:aws:s3:::bucket/* 上的策略——读起来是 “任意操作,但只作用于这个桶里的对象”——也连带授予了桶级操作。在多租户集群里,只持有这条授权的租户可以调用 PutBucketPolicy 装上 {"Principal":"*"},把桶变成匿名公网可读或可写,或者给自己授予桶级控制权;它也可以直接把桶删掉,而这正是上游 issue 中的复现步骤。

匿名访问所走的桶策略评估路径从来没有这个斜杠,是正确参照。只有 IAM 这条路径错了,而且只错在一个地方。

为何不修正整条边界

对所有桶级请求都不再补斜杠,是显而易见的修法,上游也试过:那次改动当天就因打破依赖旧行为的策略而被回滚。有两个性质让"完整修正"成为一次迁移,而不是一个补丁。

它会撤销真实部署所依赖的授权。 它撤销的不只是危险的桶写入——通过 bucket/* 授予的 ListBucketGetBucketLocationListBucketMultipartUploads 同样会被撤销。证据就是上游自己的测试套件:11 个 STS 集成测试把 s3:ListBucket 授在 bucket/* 上,然后断言列举能成功。连写服务端的项目都这么写,生产策略里只会更多。

它切的是两个方向。 匹配器对 AllowDeny 拼的是同一套资源串,所以删掉斜杠在收紧过度授予的 Allow同时,也放松了过度阻断的 Deny。一个用 Deny s3:* on bucket/* 锁死某个桶的管理员,会悄无声息地失去那层保护。

保护集合是如何确定的

范围由一个问题决定:够到这个动作,能让调用者拿到它的对象级授权本来就给不了的东西吗?

之所以该问这个问题,取决于缺陷的触发条件。资源匹配发生在动作匹配 之后,所以这个 bug 只有在语句本身已经授予了那个桶级动作时才会咬人——现实中这意味着 s3:*。因此受影响的主体本就对这个桶里的每个对象拥有完整的读、写、删权限。有用的问题不是"这个动作抽象地看有多危险",而是"在一个已经握有全部数据的位置上,够到它还能多拿到什么"。

不再接受对象级授权的十二个动作:

动作 入选理由
PutBucketPolicyDeleteBucketPolicy 能把访问权发给别的主体(包括匿名),也能给调用者自己补上从未授予的桶级动作。自我提权与公开暴露。
PutBucketObjectLockConfigurationPutBucketVersioning 击穿的恰恰是专门用来"防住有写权限的人销毁数据"的保护。
PutReplicationConfigurationPutLifecycleConfiguration 以服务端凭据运行,并在调用者权限被吊销后继续生效。
DeleteBucketForceDeleteBucket 不可逆地销毁桶实体及其配置。上游 issue 的原始复现动作。
PutBucketCorsDeleteBucketCorsPutBucketQOSPutInventoryConfiguration 在今天的服务端没有挂任何行为——要么根本没有 handler,要么 handler 在鉴权之后直接返回 NotImplemented。收走它们不影响任何能用的东西,并且提前覆盖。

刻意不予保护,并且有测试对此做出断言——于是把其中任何一个加回去,都是一次带可见代价的明确决定,而不是往列表里添一行:

  • PutBucketTaggingPutBucketEncryptionPutBucketNotification 它们都是桶级写入,早期草案确实纳入过保护。三者都不给调用者任何它还没有的访问权——受损的是所有者的合规姿态,不是访问边界;而一个拿到 s3:* on bucket/*、并被告知"这个桶归你"的租户,完全合理地会去给它打标签、设默认加密、配事件通知。用很低的安全收益去换实打实的兼容成本,在维护版本里是个错误的交易。
  • CreateBucket 它作用于一个还不存在的桶,没有东西可篡改、可摧毁;而供应流程常用租户自己的 bucket/* 凭据去创建租户的桶。
  • 读/列举族ListBucketGetBucketLocation、各类配置读取)。打破它们正是上游那次完整修复被回滚的原因,它们要等一次带迁移路径的发布。

改动只作用于 Allow 语句。Deny 语句保持历史资源串,因此任何桶级封锁都不会被削弱,NotResource 排除也保持完整覆盖范围。

单调性,以及那个错了两次的论断

上面这一切都建立在一条性质上:这个变更可以收走权限,但绝不能新增权限。 而这条性质被断言过两次,两次都是凭推理而非凭测试,也两次都是错的。把"怎么错的"记录下来,比只记录最终状态更有价值。

第一次尝试让省略的斜杠同样作用在了 NotResource 匹配上——而 NotResource排除Allow s3:* NotResource bucket/* 这样的语句,历史上不会作用于该桶的桶级请求;把排除拿去和裸桶名匹配,排除就不再命中,于是它所限定的那条 Allow 反而变宽了,而且恰恰是在受保护的那些写入上。

第二次尝试修好了这一处,并在发布时写着结论"可证明地单调"。对该版本做的独立对抗性复核给出了反例。省略斜杠并不只是"少了一次匹配"——它改变了 模式所匹配的那个字符串,而一个模式完全可能匹配 "mybucket",却从来匹配不上 "mybucket/"。定长通配是最干净的例子:

Allow s3:PutBucketPolicy on arn:aws:s3:::mybucke?

? 恰好匹配一个字符。对九字符的 "mybucket/" 它匹配不上,所以这条语句从来没有授予过那个桶级写入;而对八字符的 "mybucket" 它匹配上了,于是这次加固 授予了 有缺陷的匹配器都拒绝的东西。

修法不是再加一个特例。在受保护路径上,匹配器现在要求 两种形式同时命中——裸桶名,以及历史的 "bucket/"。结果是与历史判定取交集,于是它 在构造上 就是单调的:不存在任何它能新满足的模式,也不再有下一次会推理错的论证。mybucket* 照旧授予(它本来两种形式都匹配),mybucket/* 照旧被收走,mybucke? 被拒绝——和它一直以来的行为一样。

有两点值得带走。鉴权路径上的正确性修复,绝不能让任何东西变成新允许的——而确认它的唯一办法是把两个方向都测一遍,因为在这两次里,推理给人的感觉都是无懈可击的。以及:当一条安全性质是承重的,就 用一个不可能违反它的操作把它构造出来,而不是用一份你认为已经穷尽的分情况讨论。

证据

这条性质是被验证的,不是被论证的。我们生成了一份 27000 条鉴权判定 的语料——15 种资源模式 × 3 个桶 × 5 种对象名 × 20 个动作 × 6 种语句形式——分别在加固前基线与本版本上执行,并逐条比对:

迁移方向 条数
false → true(变宽) 0
true → false(收窄) 144
不变 26856

那 144 条收窄全部落在设计意图之内,没有一条溢出:动作恰好是受保护的十二个;语句形式只有三种 AllowDenyNotResource 排除与 deny-NotResource 三种形式 零变化;资源模式只有四种对象级模式;请求只有桶级请求,对象级请求完全未被触碰。12 × 4 × 3 = 144,严丝合缝。

两个层次都有回归测试。本仓库有十二条匹配器测试钉死每个方向,其中包括一条不变量测试,确保受保护动作个个都是纯桶级动作——ResetBucketReplicationState 名字唬人,实为对象动作,不入集合。服务端有三条端到端测试驱动真实 handler,分别位于客户端、内联会话策略与 S3 路由三个层次;三条在修复前的构建上全部失败,在本版本上全部通过。

需要改什么

只有当你的存量策略把十二个动作之一(或 s3:*)授在含 / 的资源模式上、且同一个桶没有裸桶 ARN 时,你才会受影响。修法是在对象模式旁边补上裸桶 ARN:

"Resource": ["arn:aws:s3:::bucket", "arn:aws:s3:::bucket/*"]

这种配对写法是惯例形式,也是上游自己的测试所采用的写法,在本版本之前同样有效。内置策略不受影响——readwritereadonlywriteonlydiagnostics 全部使用 Resource: "*"

MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 在启动时读取一次,可完整恢复历史匹配行为——过度授予与过度阻断两个方向一并恢复。它目前是单一的全局开关,按动作粒度的作用域已列入待办

策略条件键解析顺序

getValuesByKey() 此前会先按规范 MIME 拼写(http.CanonicalHeaderKey)查找策略条件键,再尝试原始名称。而它读取的那张表里,混放着服务端为当前请求计算出的值(SourceIpSecureTransportCurrentTimeusername 等,以条件键拼写存储)和请求自带的 HTTP 头(以规范 MIME 拼写存储)。

先查规范拼写,就让客户端的请求头能够覆盖服务端算出来的值。

对 MinIO 服务端而言这是一次策略绕过。最简单的例子是 s3:prefix:一个 Prefix 请求头可以满足家目录前缀条件,而真正的 ?prefix= 查询参数仍然列举整个桶。同一条路径还能触及 aws:SourceIpaws:SecureTransportaws:CurrentTimeaws:EpochTimeaws:usernameaws:useridaws:principaltypeaws:UserAgentaws:groupsldap:usernameldap:groupsjwt:groupss3:versionids3:signatureversions3:signatureAges3:authTypes3:LocationConstraint。匿名桶策略直接暴露。SigV4 也拦不住,因为客户端可以添加不在 SignedHeaders 列表里的头。

还有第二重后果:当服务端以一种拼写存值、而策略键解析到另一种拼写时,错误的条目会胜出。s3:object-lock-mode 可能解析到调用者的 X-Amz-Object-Lock-Mode 请求头,而不是服务端实际会施加的保留模式。

修复反转了查找顺序:先精确匹配条件键本身的名字,只对确实指代请求头的条件键(例如 s3:x-amz-* 家族)才回退到规范拼写。这移植了 minio/pkg#226,并补上了上游那次改动没有携带的回归测试。

在库的原始映射层面,如果生产者把同一个逻辑字段同时以精确条件名和规范 MIME 名存入,现在精确名胜出。这是一条库层查找规则,不是"查询参数优先"的 S3 线缆协议规则。Silo 服务端会先按真实来源规范化条件值。对于存储类别与上传标签这两处 Header 与查询形式都保持兼容的字段,Header 只要出现就胜出,包括空值,查询参数仅作回退。

LDAP 连接路径

connect() 中的三个缺陷,其中两个由本分支自己在 b0c08a7 中引入,随 v3.6.2 与 v3.6.3 发布。使用这两个版本的用户应尽快升级。

ServerInsecure 开启时 StartTLS 被跳过。 上游把 StartTLS 调用放在只由 ServerStartTLS 控制的外层块里,因此同时开启两个选项时,会先建立明文连接再升级。b0c08a7 把该调用移进了 else 分支,导致只要 ServerInsecure 为真,StartTLS 就不可达。连接保持明文,随后的 bind 就在这条连接上发送了凭据。MinIO 的 MINIO_IDENTITY_LDAP_SERVER_INSECUREMINIO_IDENTITY_LDAP_SERVER_STARTTLS 是独立开关,Validate() 不拒绝任何组合,所以这个状态是可达的。

本版本恢复了上游语义:两个开关是 叠加关系,而非互斥ServerInsecure 关闭隐式 ldaps://ServerStartTLS 仍然执行升级。暴露窗口仅限 v3.6.2 与 v3.6.3。

没有 TLS 配置段的 Config 可能在 ldaps:// 路径上 panic。 l.TLS.Clone() 移出 StartTLS 分支之后,普通 ldaps:// 连接也会调用它。Clone() 对 nil 接收者返回 nil,而下一行却给 ServerName 赋值。MinIO 服务端总会提供 TLS 设置,但这是一个库,mc 同样在消费它。现在代码会回退到空的 tls.Config,与 DialURL 本来会构造的一致。

StartTLS 没有超时。 go-ldap 只在 requestTimeout > 0 时才启动请求计时器,而 StartTLS 本身没有超时。一台完成了 TCP 建连、随后对扩展请求不再响应的服务器,可以让连接 goroutine 永久挂住。现在计时器在 StartTLS 之前就已武装。

StartTLS 失败会泄漏连接。 这一条继承自上游。拨号失败不会返回连接,因此 StartTLS 失败是 connect() 里唯一可能同时返回连接与错误的路径。调用方只在错误为 nil 时接管所有权,于是对一台升级功能损坏的服务器,每次登录尝试都会遗留一个 socket。失败路径现在会关闭连接并返回 nil。

其它修复

  • certs:文件监听器从未被停止。 Manager.AddCertificate() 注册了两个 notify.Watch() 却一个都不停:如果第二个失败,第一个就泄漏;而且两个都会在 manager 关闭后一直存活到进程退出。Certificate.Watch()watchFile() 有同样的问题。四条路径现在统一使用 watchDirSafe(),它返回一个在出错与 ctx.Done() 时被调用的停止函数。这移植了 minio/pkg#228certs/ 部分。在 Windows 上该函数用轮询替代文件系统通知,而不是把轮询仅作为失败回退,因此证书重载可能滞后一个 symlinkReloadInterval(10 秒)。本分支没有 Windows CI,该平台仅做了交叉编译。
  • rng:reader 的子密钥取自一个被清零的局部变量。 init() 把 32 字节熵读进 r.tmp,却从一个同名的、已清零的局部变量派生出四个子密钥,把四条按块划分的流坍缩成了一条。随后 Reset()ResetSize() 会逐字节重放上一条流。MinIO 每次 randreader.New() 都创建新的 reader 且从不 reset,因此实际服务端影响有限;这个缺陷是 warp 暴露出来的。这移植了 minio/pkg#230
  • xtime:Duration 实现了 UnmarshalJSON 却没有 MarshalJSON 编码产出的是纳秒整数,而解码无条件剥掉首尾各一个字节并期待带引号的字符串,两个方向都无法往返。现在它使用 time.Duration 的字符串形式编码。这移植了 minio/pkg#242

兼容性影响

  • 十二个桶级写操作不再能通过对象级资源模式获得授权。需要改什么。对象访问、ListBucketCreateBucket、桶标签、默认加密与事件通知均不受影响,Deny 语句与 NotResource 排除同样不受影响。
  • 最低 Go 版本从 1.26.1 降回 1.25.0 go 指令里的补丁号对每一个消费者都是硬性下限,而不是构建该模块所用工具链的记录。惯例做法是 go 行写语言版本、单独的 toolchain 行写开发版本。1.25.0 才是依赖图实际要求的版本,也是上游声明的版本。CI 会在 GOTOOLCHAIN=local 下用 Go 1.25 构建完整测试套件,因此这个下限是被证明的,而不是宣称的。
  • xtime.Duration 的 JSON 线缆格式变更,从纳秒整数改为 "2h""30m" 这样的时长字符串。已持久化的数值形式无法再读回。在 MinIO 与 mc 中未发现此类用法:批处理作业定义以 YAML 持久化,msgp 路径仍为 int64。
  • 同时开启 ServerInsecureServerStartTLS、且 LDAP 服务器不支持 StartTLS 的部署,在 v3.6.2/v3.6.3 上会以明文成功连接,现在则连接失败。这是正确结果,但它暴露在连接阶段而非配置校验阶段。对这类服务器请关闭 ServerStartTLS
  • Policy.IsAllowedActions 对那十二个受保护动作可能与直接判定不一致。 它遍历 SupportedActions,其中包含 s3:* 这个模式本身,因此返回的集合可能包含 s3:*——从而看起来允许某个受保护动作——而直接求值却是拒绝。服务端没有任何地方调用它,Console 调用时传的是空桶名,永远走不到加固分支。此处选择记录而非修改:在维护版本里改变一个公开 API 的输出,风险更大。

与上游 v3.11.0 的差异

版本号跟随上游的线,不声称内容一致。以 policy/ 下的动作字符串常量为口径,实测差异如下:

数量
上游 minio/pkg v3.11.0 291
silo-pkg v3.11.0 270

有 24 个动作只存在于上游: 6 个 s3:*ObjectAnnotation*、5 个 admin: 动作(DistJobStatusGet/SetBucketCompression、两个 TablesReplication*),以及 13 个覆盖函数 CRUD 与打标签的 s3tables: 动作。它们属于本分支刻意不采纳的 AIStor 词表,因为社区版服务端并不实现这些功能。

有 3 个动作在两侧名称不同。 上游对它们做了改名与拆分,本分支保留较早的名称:

silo-pkg v3.11.0 上游 minio/pkg v3.11.0
s3tables:TagResource s3tables:TagTables3tables:TagWarehouse
s3tables:UntagResource s3tables:UntagTables3tables:UntagWarehouse
s3tables:ListTagsForResource s3tables:ListTagsForTables3tables:ListTagsForWarehouse

因此,一条写了这六个动作名之一的策略,在两者之间 只有一个 能通过校验。Silo 服务端、mc 与 Console 都没有引用它们,所以在本生态内没有影响;但从上游 v3.11.0 切换过来的消费者应当知道,动作词表并不可互换。

rng 没有 arm64 汇编。 上游在本分支分叉点之后加入了 rng/xor_arm64.{go,s},本版本在 arm64 上回退到纯 Go 的 xor_noasm.go 路径。结果正确、交叉编译干净,但在该架构上比上游慢。它是未来同步的一个干净候选:纯性能改动,不牵涉词表分歧。

服务端配套行为

  • 本版本的条件键改动 必须 与服务端"保留内部条件键名、按语义来源填充取值"的改动配对,见文首提示。
  • s3:signatureAge 只有在 SigV4 预签名请求校验器算出它之后才会暴露。在其它任何请求类型上,客户端提供的 x-amz-signature-age 头都会被忽略。
  • s3:prefixs3:delimiters3:max-keys 只来自查询参数。内容哈希、拷贝源、元数据指令、SSE 与对象锁条件只来自对应的请求头。校验预签名请求时消费的 X-Amz-Content-Sha256 查询值不会成为策略条件。
  • s3:x-amz-storage-class 保留其兼容的查询形式,PutObjectCreateMultipartUpload 上的请求标签同样保留。这两个字段都是 Header 出现即胜出,只有 Header 缺失时才使用查询参数。
  • s3:ExistingObjectTag/* 只来自从已存储对象加载的标签,因此请求自带的 X-Amz-Tagging 不能再冒充既有对象状态。PutObjectCreateMultipartUploadPutObjectTaggings3:RequestObjectTag/* 绑定到这些 handler 实际消费的标签输入。其余动作路径出于兼容保留了历史的 X-Amz-Tagging 头回退,因此只在 API 确实消费标签的地方,才把请求标签条件当作约束使用。
  • aws:SourceIp 由转发头计算得出。它是否可强制执行,取决于服务端的可信代理配置;参见服务端自己关于 MINIO_API_TRUSTED_PROXIES 的发布说明。

验证

以下全部在打标签的那个提交上执行,工作树干净,标签与 HEAD 一致:

  • make test——golangci-lint 加 go test -race -tags kqueue ./...,全部包通过。
  • go mod tidy -diff 干净;gofmt -l 为空;go vet ./... 干净。
  • linux/amd64linux/arm64darwin/arm64windows/amd64 四个组合的交叉编译。
  • govulncheck ./...——零个可达漏洞。仅剩一条模块级提示 GO-2026-5932(x/crypto/openpgp):该包已停止维护、没有修复版本,且本仓库并未 import 它。
  • 从空模块缓存经公共 proxy 解析,确认发布出去的版本确实可获取。
  • 上文所述的 27000 条鉴权判定语料。

依赖与工具链

依赖更新清除了 govulncheck 此前报告的九项 可达 问题:经 sftp 触达的七个 x/crypto/ssh 问题、经 etcd 触达的 gRPC GO-2026-6061,以及经 oidc 触达的 go-jose GO-2026-4945。

有五个依赖——minio-gominio/muxetcd client/v3go-oidclestrrat-go/jwx——刻意未升级。MinIO 通过 replace 消费本模块,而最小版本选择会取整个依赖图中的最高版本,因此在这里升级它们会连带把服务端也拽着往前走。这五个都没有必须升级的已报告漏洞。

三个工作流此前都向 setup-go 索要低于 go.mod 要求的 Go 版本,并在第一条 Go 命令上失败,现已对齐。linter 此前还从 master 分支拉取安装脚本并每次重装;URL 与版本现已固定到 v2.11.3,且当已安装版本匹配时会跳过下载。

刻意未采纳的上游改动

  • AIStor 策略词表(Memory/cortex、Tables/Iceberg、KMS、压缩与注解)以及带类型的动作常量重构,社区版服务端均不实现。这也是动作词表差异的来源。
  • securityAuditAdmin:它授予 admin:ExportIAM,因而会暴露每一个密钥,与名字给人的印象相反。
  • rng 的 AVX2/NEON 汇编。其中 arm64 那一半已在上文列为未来同步候选。
  • net.BandwidthBytesPerSec(上游声明了却从未读取)、replicationAdminDistJobStatusAction
  • 两项先采纳、复核后又移除的改动:consolereadonly 内置策略与 GetAllGlobalCertificates,两者都没有消费者。一旦运维把内置策略名绑定到用户身上,再撤回就格外危险:策略映射按名字持久化,而无法解析的名字会并入一个拒绝一切的空策略;它继承的 admin:CreateUser Deny 也无法与 iamAdmin 组合使用。那个证书辅助函数清点的是社区版服务端从不填充的缓存。
  • 上游的 golangci-lint tool 指令,它会给每个下游消费者的模块图增加约 200 个 linter 依赖。

刻意推迟的部分

minio/minio#20449 的一般性问题——bucket/* 仍会触及 ListBucketGetBucketLocation、各类配置读取、CreateBucket 以及上述三个租户可能合理使用的写入——在这里 没有 被关闭。彻底关掉它意味着撤销真实部署所依赖的授权,因此它属于一次带迁移路径的发布。

那次发布欠运维的东西,比"一份更长的动作清单"要多,因为没有人能穷举所有部署的存量策略——这给"靠猜来划定保护集合"的做法设了一个硬上限。有三件事能抬高它:

  • 启动时的策略审计:遍历存量策略,逐条点名哪一条的含义会改变,授予与拒绝两个方向都点。它是只读的,甚至可以 先于 强制生效单独发布,从而把"升级后的意外"变成"升级前的清单"。
  • 会自我解释的拒绝:当一个请求因为"只有对象级授权匹配上"而被拒时,就把这句话说出来,并点名那个兼容开关。一次 30 秒能自诊断的破坏,成本比静默破坏低一个数量级。
  • 带作用域的开关MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH 今天是全有全无,只想要回一个动作的运维,被迫连自我提权那条路一起重新打开。
  • d8b1fa7:fix(policy): settle the bucket-write hardening’s scope and monotonicity
  • 1f97549:fix(policy): extend the bucket-write hardening to every bucket-only write
  • 3c24ad1:fix(policy): withhold object-only grants from sensitive bucket writes
  • da6a22a:docs: say what this fork is and how to depend on it
  • 4055b2f:fix(xtime): marshal Duration as a duration string
  • 13c26cd:fix(rng): initialize the reader subkeys from the seeded entropy
  • 88b37ac:fix(certs): stop file watchers on every exit path
  • 74dd36e:fix(ldap): keep StartTLS when ServerInsecure is also set
  • 424c3d0:fix(ldap): close the connection when StartTLS fails
  • 045d10f:fix(ldap): guard a nil TLS config and arm the StartTLS deadline
  • 5c4bf50:fix(policy): prefer the exact key name over the canonical header form
  • 802539f:chore(deps): refresh the dependency set and declare the real minimum Go
  • e4ec64a:ci: build on the Go version go.mod requires, and prove the declared minimum
  • 747d8b8:build: pin the golangci-lint installer and skip a matching install

4 - mcli 20260806 发布

客户端全面切换为 Silo 身份:所有 MinIO SUBNET 外联路径在构建期永久关闭,移除内置的厂商诊断加密公钥,贡献政策改为无 CLA + 强制 DCO 签署。

发布日期: 2026-08-06 · 版本: RELEASE.2026-08-06T00-00-00Z

距离 mcli 20260804 仅两天,本次发布完成了客户端向 Silo 身份的整体切换。这是一次刻意保持「纯品牌与封闭」性质的发布:--version--help 现在以 Silo 客户端的身份呈现,所有残余的 MinIO SUBNET 外联路径在构建期被关闭,诊断工具链中内置的厂商加密公钥被移除,贡献政策改为无 CLA + 强制 DCO 签署。本周期 零依赖变更、零协议变更 —— go.mod 与 20260804 逐字节一致 —— 因此回归面被严格限制在文案、命令门禁与 CI 三个层面。

警告

行为变更

所有原先会连接 MinIO SUBNET 的路径均已在构建期关闭,且无法在运行时重新开启:

  • mcli license registermcli support uploadmcli support proxy setmcli support callhome enable,以及 mcli license update ALIAS 的在线续期形态,均打印稳定的提示信息 —— “MinIO SUBNET services (registration, licensing, uploads) are disabled in this Silo build of mc; diagnostics remain available locally.” —— 并恒定以退出码 1 结束。脚本中如有这些调用应予移除。基于本地文件的 mcli license update ALIAS license.key 仍然可用,许可证使用内置公钥离线验签。
  • mcli support diag / perf / profile / inspect 恒定以本地(airgap)模式运行:诊断报告、性能剖析与 inspect 归档全部写入本地文件,不向任何地方上传。--airgap 参数保留以维持兼容(实际上始终生效),SUBNET 注册不再是任何诊断命令的前置条件。
  • mcli support callhome disable|statusmcli support proxy show|removemcli license infomcli license unregister 照常工作 —— 它们只读取或清除本地与服务端配置。
  • 全新生成的配置不再自动写入指向 MinIO 公共演示集群的 play 别名,默认别名为 locals3gcs。已有配置文件永远不会被修改,旧版配置迁移逻辑仍识别历史条目。
  • mcli --version 增加一行身份说明(“Silo object storage client, based on MinIO technology”)与第二行版权信息。首行的机器可读格式保持不变,解析首行的脚本不受影响。

主要变更

  • CLI 全面切换 Silo 身份:客户端自我介绍改为 “Silo client for object storage and filesystems”。约 220 处帮助文本重写:涉及被管服务器的用法说明改用 “Silo/MinIO server” 措辞,示例别名从 myminio/play 换成 mysilo,LDAP 示例 DN 换成 dc=example,dc=com,示例分层名称换成 SILOTIER-*。事实性表述保持事实:minio 分层 类型、协议头以及第三方互操作提及均未触碰。
  • SUBNET 构建期关闭:连接能力在编译期被单一开关移除,所有 SUBNET 请求汇聚的唯一 HTTP 出口以上述稳定错误拒绝。命令入口提前拦截,诊断命令强制本地模式,mcli license info 显示的 AGPL 许可说明不再附带商业订阅推销。专门的回归测试(cmd/subnet-disabled_test.go)钉住了全部行为,上游合并无法悄悄恢复任何外联。
  • 治理 —— 无 CLA,强制 DCO:贡献按 inbound=outbound 原则以 AGPL-3.0-or-later 接收;贡献者保留自己的版权,维护者不获取项目许可证之外的任何权利。每个提交必须携带 Signed-off-by 尾注,由新增的 CI 工作流强制校验(尾注须与提交作者邮箱匹配,仅豁免 GitHub 官方 bot 地址)。CONTRIBUTING.md、PR 模板与中英文 README 均已写明政策,行为准则的联系方式改为本分支维护者。
  • 双版权署名:运行时输出与帮助信息同时致谢两条脉络 —— Copyright (c) 2015-2025 MinIO, Inc.Copyright (c) 2025-2026 PGSTY,源码构建动态计算截止年份。NOTICE 明确声明分支关系,以及与 MinIO, Inc. 无隶属、无背书关系。
  • 发布线更名为 main:工作流分支过滤器、文档与贡献指引全部指向 main,旧的 master 引用已清除。

安全加固

  • 移除厂商加密公钥:此前 mcli support inspect 在未提供密钥时,会回退到用内置的 MinIO RSA 公钥加密输出 —— 产生只有厂商才能解密的归档。内置公钥现已移除:inspect 改用服务端为每次请求生成并回传给调用方的随机密钥(或运维人员自备的密钥),而任何未配置接收方的加密上传路径都会直接失败,绝不静默借用第三方密钥。运维人员产出的诊断数据,现在始终由其本人掌握解密能力。
  • 品牌政策门禁buildscripts/check-branding.sh 接入 make verifiers 与 CI。一旦命令树中重新出现 MinIO 运营的端点、商业推销 URL、上游产品身份、或任何内嵌的 MII… 公钥,构建即失败 —— 同时显式豁免有意保留的兼容标识(环境变量、协议头、模块路径、旧配置迁移默认值与原始版权头)。

工程与交付

  • CI 迁移到 Node 24 Actions 运行时actions/checkout v7、actions/setup-go v7、goreleaser-action v7 及 Docker 系列 Actions —— 全部继续钉在 commit SHA 上,由 dependabot 保持更新。
  • 功能测试只针对受控服务器:测试套件默认连接本地服务器(localhost:9000)而非 MinIO 公共演示集群;CI 从 pgsty/silo 下载钉死的 SILO 服务端版本 RELEASE.2026-08-04T00-00-00Z(经 SHA-256 校验)后再运行套件。
  • 零依赖变更:本周期没有任何模块升级;20260804 建立的安全基线(Go 1.26.5、零个可达已知漏洞)原样延续。
  • 打标签前经过审计:本次发布以一轮独立的对抗性审查作为门禁 —— 通读 245 个文件的全量 diff、品牌/兼容分类的 grep 全集扫描、沿调用图验证任何命令与参数组合都无法触达 subnet.min.io / play.min.io / dl.min.io,并以冒烟测试确认每条被禁用路径都返回稳定错误与退出码 1

兼容性

脚本与集成所依赖的一切均有意保持不变:mc 命令名与 mcli 包名/二进制名;~/.mc / ~/.mcli 配置目录(由调用名派生);github.com/minio/mc 模块路径及全部 import 路径;MC_* 环境变量;协议头(x-minio-*)与 minio-go SDK 的 User-Agent 前缀;minio 分层类型;.part.minio 断点传输后缀;Prometheus 抓取任务名 minio-job;以及软件包格式、发布资产命名与 YYYYMMDDHHMMSS.0.0 版本方案。客户端与 MinIO 服务器及其他 S3 兼容端点保持完全兼容。

说明

已知问题

20260804 发布说明中标记的 mcli watch 回归已在服务端解决:修复随 SILO 20260804 交付,本客户端的 CI 现在正是针对该版本运行包括 watch 在内的功能测试套件。将 mcli 与 SILO 服务端 20260804 或更新版本搭配即可正常接收桶事件;更早的已发布服务端版本仍受影响。

上游未修复的历史缺陷继续适用,其中最严重的是 minio/mc#5139mirror --remove --watch 在源端删除对象的 非当前版本 时,可能误删目标端的现存对象。在版本化桶上组合使用 --remove --watch 时请务必谨慎。

  • 8a883ca:ci: move the branch filters to main and fetch the server from pgsty/silo
  • 8c304dd:ci: move the pinned actions onto the Node 24 runtime
  • 02b1c11:docs: name the release line main, not master
  • 810bbd2:ci: pin the functional-test server to a release whose watch API works
  • d145647:fix: disable SUBNET connectivity and licensing upsell paths
  • 5061c4f:rebrand: adopt Silo identity in CLI help and examples
  • c7f7706:docs: align governance files and package metadata with the fork
  • 65c71b2:test: default functional tests to a local server and add brand gate
  • c62a64d:fix: credit both MinIO and PGSTY in copyright notices
  • d205f88:docs: adopt no-CLA plus DCO contribution policy
  • 95326ce:docs: add related-projects table and polish contribution wording
  • d2c0db7:fix: remove the vendor encryption key and close the proxy-set path
  • 0c6704d:fix: repair a link and help text damaged by the brand sweep

5 - Silo 20260806 发布

首个以 Silo 之名发布的版本:品牌切换完成而兼容面原样保留、原生健康检查、Distroless 镜像试点、捆绑 mcli 20260806、完整的许可合规材料,以及以构建溯源为门禁的发布管线。

版本: RELEASE.2026-08-06T00-00-00Z · 提交: 3be10fcc1a44f6620ded0bd303461f9d688cca23

SILO 20260806 是 首个以 Silo 之名发布的版本。上一个版本 20260804 是以 pgsty/minio 名义交付的最后一版;本版本完成了向 github.com/pgsty/silo 的切换,重命名了每一个交付表面——二进制、软件包、容器镜像、systemd 服务、Helm chart——同时刻意原样保留了 MinIO 部署所依赖的每一个线上协议与配置表面。在改名之外,本版本新增了原生健康检查(silo healthcheck)、单二进制的 Distroless 容器镜像试点、装入每个交付物的完整许可合规材料,以及以兼容性快照与构建溯源为门禁的发布管线。

本版本覆盖 RELEASE.2026-08-04T00-00-00Z 之后的 28 个提交,变更 396 个文件新增 27,188 行、删除 19,561 行。发布前通过了六阶段验收,包括一次真实的四节点 TLS 集群从 MinIO 到 Silo 的迁移——数据逐字节校验、维护闸门滚动重启、故障注入,以及完整的回滚彩排。

亮点

  • 品牌切换完成,兼容性即契约。 仓库、二进制(/usr/bin/silo)、软件包(silo rpm/deb/apk)、镜像(docker.io/pgsty/silo)、服务(silo.service)全部改名;S3 与管理 API、/minio/* 路由、MINIO_* 环境变量、x-minio-* 响应头、磁盘上的 .minio.sys 格式、Go 模块路径全部保留,并由 CI 兼容性守卫冻结。
  • 原生健康检查:silo healthcheck [live|ready|cluster|cluster-read] 探测服务器自己的健康 API——正确的退出码、解码后的 quorum 诊断、TLS 自动探测、--maintenance 下线前闸门——容器内无需 shell、curlmc
  • Distroless 镜像试点:pgsty/silo:<RELEASE>-distroless 基于 gcr.io/distroless/static,恰好装载一个程序——silo 二进制——内置 exec 形式 HEALTHCHECK/data 在镜像层内以可写方式创建。
  • 经典镜像行为不变: 同样的入口脚本、同样的捆绑工具,mc ready local 继续可用,也没有给它添加 HEALTHCHECK。捆绑客户端升级为 mcli 20260806
  • 合规补齐: LICENSE 与 NOTICE 装入每个软件包与镜像,CREDITS 按实际链接的模块集合(291 个模块)重新生成并纳入 CI 守卫,项目采用无 CLA、基于 DCO 的贡献政策。
  • 组件刷新: 内嵌 SILO Console 2.1.1、silo-pkg 3.11.0mcli 20260806、Go 1.26.5。
  • 以溯源为门禁的发布: 容器镜像只从已发布、校验和与 attestation 双重验证过的发布产物构建;镜像 SBOM 与溯源 attestation 现在同样覆盖 Distroless 变体。

改名

改了什么,与刻意没改什么:

已重命名(交付表面) 已保留(兼容表面)
仓库:github.com/pgsty/silo(main 分支) S3 API、管理 API 与请求签名行为
二进制:/usr/bin/silo /minio/* 路由,含 /minio/health/* 与指标端点
软件包:silo-*.rpmsilo_*.debsilo_*.apk MINIO_* 环境变量与 x-minio-* 响应头
镜像:docker.io/pgsty/silo(另有 -distroless 磁盘格式(.minio.sys)、纠删码、版本控制
服务:silo.service(与 minio.service 冲突并取而代之) Go 模块与导入路径(github.com/minio/...
默认配置目录:~/.silo(存在旧 ~/.minio 时回退兼容) 捆绑 mclimc 兼容别名

服务器呈现自己的身份——silo --version 输出 AGPL-3.0 许可、MinIO 2015-2025 版权、PGSTY 修改版权与 “based on MinIO technology” 归属——所有继承自上游的 MinIO 运营服务连接(更新源及其验签密钥、SUBNET、遥测)被切断而非重定向。容器入口脚本翻译 legacy minio argv 词元,因此 docker run pgsty/silo minio server /data 继续可用。

CI 中运行快照式 rebrand 守卫:对 334 个路由字面量、437 个环境变量词元、84 个响应头与 9,014 个导出符号的任意双向漂移直接判失败。

原生健康检查

服务器二进制现在可以探测自己的健康端点,使容器健康检查不再需要第二个二进制——这也是 Distroless 镜像的依赖所在:

silo healthcheck [FLAGS] [live|ready|cluster|cluster-read]
  • 检查词汇与 /minio/health/<path> 一一对应;live(默认)回答"这个进程是否在服务",ready 在配置了 KMS/etcd 时追加其可达性,cluster 一对评估每个纠删集的写/读 quorum。
  • 退出码只有 0(健康)与 1(其余一切)——绝不使用 Docker 保留的 2。单行诊断解码服务端的 x-minio-server-status 与 quorum 响应头供 docker inspect 采集;--json 输出机器可读判定。
  • 探测目标按服务器推导自身监听地址的方式推导:--address / MINIO_ADDRESS,HTTPS 由 certs 目录中 public.crt + private.key 的存在自动判定,或用 --url / MINIO_HEALTHCHECK_URL 整体覆盖。环境变量形式的存在是因为探针进程看不到服务器的命令行——当服务器地址或 TLS 来自 CLI 参数时,一个环境变量即可矫正内置探针。
  • silo healthcheck --maintenance cluster 回答下线前的问题:退出 0 表示此节点可安全下线而不失去高可用;HTTP 412(退出 1)表示不可以。
  • 跳过证书校验,与 kubelet 对 HTTPS 探针的文档行为一致;传输层忽略 HTTP_PROXY,环回探测永不进代理。

Kubernetes 完全不需要这些——kubelet 的 httpGet 探针从容器外打 /minio/health/live/minio/health/ready——且 cluster 检查不应进入单容器探针:它反映的是全集群 quorum,不是单个进程。完整设计依据(含源码核实的端点语义)记录于健康检查设计笔记

Distroless 镜像试点

在经典镜像之外,本版本发布 Distroless 变体pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distroless,另有滚动 distroless 标签。

  • 基底为 gcr.io/distroless/static-debian12:CA 证书、tzdata、/tmp、含 nonroot(65532)条目的 /etc/passwd——没有 shell、没有包管理器、没有 libc。之上恰好一个程序:/usr/bin/silo(外加 /licenses/ 下的许可三件套)。镜像 128 MB,对比经典镜像 199 MB。
  • 二进制即 ENTRYPOINT;内置 exec 形式 HEALTHCHECK 运行 silo healthcheck ready(interval 30s、timeout 10s、start-period 2m、retries 3),Compose 用户零配置即获得可用的 depends_on: condition: service_healthy
  • /data 在镜像层内以全员可写方式创建——运行时已没有入口脚本可以修补卷属主,而这正是让所有权限模式(含 --user)都能工作的原因。这在 Distroless 变体中修复了 #55 记录的非 root 失败。
  • 此变体不支持:已弃用的 MINIO_USERNAME/MINIO_GROUPNAME 降权路径(改用 --user 或 Kubernetes runAsUser)、docker exec <c> sh 式调试(改用临时容器工具)、镜像内 mc(改用已发布的 mcli 或客户端镜像)。
  • TLS:把证书挂到 /tmp/.silo/certs(容器内默认 certs 目录),服务器与内置探针会从同一位置各自推导出 HTTPS;CLI 参数配置的服务器则设置 MINIO_HEALTHCHECK_URL

经典镜像仍是默认且保持不变。试点验证充分后,Distroless 变体将成为推荐镜像;决策记录见上述设计笔记。

容器镜像

经典镜像与 pgsty/minio:RELEASE.2026-08-04T00-00-00Z 做了逐字段对照:入口、暴露端口、卷、工作目录、用户与(不存在的)健康检查配置完全一致。差异恰好三处且均为刻意变更:Cmd["minio"] 改为 ["silo"];移除上游更新验签密钥变量 MINIO_UPDATE_MINISIGN_PUBKEY(上游渠道更新永久关闭);声明 HOME=/tmp 以与入口脚本的可写 home 保证一致。

捆绑客户端升级为 mcli RELEASE.2026-08-06T00-00-00Z(保留 mc 别名),按架构以 SHA-256 摘要钉版并在构建期对照发布校验和验证。已发布的 mcli 20260806 与本服务器的互操作性——分段上传、版本控制、预签名 URL、metadata/tags、用户与策略管理——已在发布验收中验证。

Helm chart

Chart 以 silo 7.0.1 发布,经迁移守卫验证在模拟升级中与旧 chart 的 7 个渲染资源身份保持稳定。默认镜像标签现在指向本版本——docker.io/pgsty/silo 是全新仓库,继承的旧默认值本不可能拉取成功。Chart 仍未附带 liveness/readiness/startup 探针;按设计笔记的后续阶段规划补齐。

打包与迁移

RPM、DEB、APK 软件包恰好安装六个文件:/usr/bin/silosilo.service、sysusers 定义(创建 silo 系统用户)、/etc/default/silo(config/noreplace)、LICENSE 与 NOTICE。RPM 以 PGSTY 维护者密钥 GPG 签名(9592A7BC 7A682E73 33376E09 E7935D8D B9BD8B20)。RPM 与 DEB 现在统一携带 PGDG 风格的 1PGSTY release 段——silo-<版本>-1PGSTY.<架构>.rpmsilo_<版本>-1PGSTY_<架构>.deb——取代此前 RPM 继承的裸 -1 与 DEB 缺失的 revision;APK 命名保持不变,因为 Alpine pkgrel 只接受 -r<整数>

silo.service 为接管而设计:Type=notify(就绪由服务器自己发信号)、Conflicts=minio.service + After=minio.service(启动 Silo 会停掉运行中的 MinIO 服务)、以及 两个 环境文件——先读 /etc/default/minio、后以 /etc/default/silo 覆盖——现有 MinIO 配置无需编辑即被继承。对数据属主为 minio 用户的既有部署,用文档规定的 drop-in 保持属主不动:

# /etc/systemd/system/silo.service.d/10-legacy-user.conf
[Service]
User=minio
Group=minio
警告

分布式迁移必须全体节点一起切换。

集群引导会(按校验和)验证每个节点运行相同的二进制。混合集群——部分节点 Silo、部分仍是 MinIO——无法组网:新节点停在 activating,无限期记录 Expected Silo binary checksum ... seen: ...Waiting for at least 1 remote servers with valid configuration。请在 所有 节点上停止 MinIO,然后(近同时地)在所有节点上启动 Silo。全部节点运行 Silo 之后,滚动重启一切正常——每台重启前用 silo healthcheck --maintenance cluster 做闸门。

来自验收实测的迁移排障提示:若 Silo 以软件包默认的 silo 用户启动,而部署的 TLS 证书位于 minio 用户家目录之下,会以 HTTPS specified in endpoints, but no TLS certificate is found 失败并连续重启直至 systemd 启动限制生效——上面的 legacy-user drop-in 即是解法。迁移窗口期间保留 MinIO 软件包与服务(处于 disabled):回滚路径——停 Silo、起 MinIO——已经彩排,且能读取 Silo 窗口期写入的全部数据,因为迁移既不动数据属主也不动数据格式。

组件与依赖

  • SILO Console 2.1.1 —— 内嵌控制台,取自 pgsty/silo-console,保留 github.com/minio/console 导入路径。
  • silo-pkg 3.11.0 —— 保留策略/LDAP/证书修复,含 #15 跟踪的 LDAP-over-TLS 修复。
  • mcli 20260806 —— 镜像内捆绑并已单独发布;见其发布说明
  • Go 1.26.5 —— 工具链与 20260804 一致。

构建、CI 与发布管线

  • 兼容性即 CI 门禁: rebrand 守卫对路由、环境变量词元、响应头、指标、存储/策略标识符与导出符号做快照,任何未经评审的漂移直接失败;配套脚本断言交付表面(二进制路径、unit 内容、镜像布局),并确保运行时代码中不再存在任何上游在线端点。
  • 发布镜像门禁: 发布管线的每次运行都构建两个容器镜像并断言(除其他外):Distroless 的 HEALTHCHECK 存活于镜像配置(它是 OCI 规范之外的 Docker 扩展)、/data 以全员可写交付、不存在 shell 与 /usr/bin/minio、Docker 健康状态仅凭内置探针即转 healthy、SIGTERM 在 root 与 --user 1001:1001 双路径下均优雅停机。
  • 溯源链: 镜像从已发布的发布产物构建,先经校验和验证与对确切 tag 的 gh attestation verify;经典与 Distroless 镜像均推送分架构 SBOM 与溯源 attestation;Distroless 健康检查门禁在多架构 manifest 提升之前运行。
  • 工作流运行时 全面迁移到 Node 24。

兼容性与升级注意

  1. 软件包升级是接管而非原地更新。 安装 silo,保持 /etc/default/minio 原样(会被继承),启用 silo.service;启动它会经冲突关系停掉 minio.service。数据不动。
  2. 用上述 legacy-user drop-in 保持数据属主稳定;迁移期间不要 chown 存储、不要移动证书。
  3. 分布式集群:只能全停切换。 见上方警告——Silo/MinIO 混合节点无法组网。
  4. 容器用户: 镜像现为 docker.io/pgsty/silodocker.io/pgsty/minio 冻结在 20260804 作为存档。经典镜像行为不变——包括 mc ready local 健康检查——Distroless 变体严格自愿选用。
  5. Distroless 的差异是刻意的: 无 shell、无镜像内 mc、无 MINIO_USERNAME 路径;健康检查原生;CLI 参数配置的服务器需为内置探针设置 MINIO_HEALTHCHECK_URL
  6. Helm 用户: chart 7.0.1 的默认值现在能拉取本版本;若钉版本请显式覆盖 image.tag
  7. 已知且未变: 经典镜像仍不在层内创建 /data,因此完全非 root 的 docker run 配 Docker 管理卷会一如既往失败(#55,Distroless 变体已修复);20260804 说明中继承的 Postgres/MySQL 遗留通知迁移限制仍然适用(#53)。
  8. 客户端配套使用 mcli 20260806;旧客户端在未变的线上协议下继续可用。

验证

本版本分阶段验证,每一步留有证据记录:

  • 健康检查命令的单元与端到端矩阵:目标推导与优先级链(flag/env/派生)、真实 TLS 自动探测、退出码契约、JSON schema、超时有界性、用法错误;
  • 四节点集群上的语义验证:停掉 4 节点中的 2 个后,cluster 报告 503 且 write-quorum=5,而 cluster-readlive 保持 200——写/读 quorum 分野现场观测,与纠删码推演一致;
  • 镜像验收:经典镜像与 20260804 基线逐字段对照;Distroless 镜像断言至文件清单、精确健康检查配置,及 root/非 root/TLS/环境变量覆盖四个运行场景;
  • 对新增代码的对抗性模型评审,全部确认发现均已修复并复验;
  • 以真实迁移收尾的六阶段发布前验收:Pigsty 部署的四节点 TLS MinIO 20260804 集群(16 盘、EC:4)经软件包接管路径迁移至 Silo——参考数据(分段、多版本、带标签对象)逐字节读回一致、四轮维护闸门滚动重启、kill -9 故障注入下负载均衡持续 IO 24 轮成功 23 轮(唯一失败恰在击杀当秒)、Prometheus 指标连续,以及完整的回滚至 MinIO 再切回——证明迁移可逆。

验证边界

以下内容本版本未予证明,亦不应据此推断:外部 LDAP/OIDC/KMS/etcd 服务(readylive 分叉的唯一情形未对真实 KMS 演练);amd64 软件包做了交叉构建与 payload 检查但未在物理 x86-64 主机上安装;改名后的 Docker 发布工作流(含新增的 SBOM/attestation 通道)在本版本发布时才有首次生产运行;Windows 与 Intel macOS 未测试。

交付物

  • pgsty/silo 的 GitHub Release RELEASE.2026-08-06T00-00-00Z:带校验和的平台归档、溯源 attestation、RPM/DEB/APK 软件包(RPM 带 GPG 签名);
  • docker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Zlatestdocker.io/pgsty/silo:RELEASE.2026-08-06T00-00-00Z-distrolessdistroless——从完成的 Release 按需发布;
  • 配套发布:mcli 20260806silo-pkg 3.11.0、内嵌 SILO Console 2.1.1;
  • 设计记录:原生健康检查与 Distroless 镜像

选定变更

  • 15def34dc77bdc4c0c:清除上游交付残留;呈现 Silo 身份并关闭继承的上游服务
  • 15ab10833:交付物改名为 silo 并补全软件包载荷
  • 30749911b:镜像装载 silo 二进制并翻译 legacy argv 命令
  • e071bb77e:以保持身份的 silo chart 替换 minio chart
  • bd8df5166:以兼容性、打包与溯源证据为 rebrand 设门禁
  • 6613c2a3c:钉住外部测试固件并针对 silo 二进制运行套件
  • fd2ca1c6dc46b16ec6c47733abcf1c77d5a2:切换到 pgsty/silo 与 main;记录归档分支
  • 6740e6978:工作流迁移到 Node 24 运行时
  • b57275be3:采用无 CLA + DCO 政策并修正版权条款
  • 62717d7bfa6d6d9b02:内嵌 Console 升级到 2.1.0、再到 2.1.1
  • 6bd9cf77e:按实际链接模块集合重新生成 CREDITS 并纳入 CI 守卫
  • 219670d31:LICENSE 与 NOTICE 装入每个软件包与镜像
  • 2ff594f4b:新增原生 silo healthcheck 子命令
  • 4c34d2309:新增 Distroless 镜像变体试点
  • b6d47b7399462cce16:按对抗性评审加固;lint 清理
  • 16b78eb4e:捆绑 mcli 20260806 并将 Helm 默认值指向本版本
  • 062a91bee:将 CREDITS 模块闭包钉定到实际发布的 linux 目标
  • 467931455:统一 rpm 与 deb 的 release 段为 1PGSTY
  • b14ea22aa:镜像发布通道精确匹配校验和清单条目
  • 3be10fcc1:新增手动 finalize 通道,为已签名的 Draft 软件包刷新 SBOM 与校验和

致谢

已有四位贡献者的代码合入本分支,Git 历史中保留着他们的署名:@ZouhairCharef 修复了 go-jose 中的 CVE-2026-34986(#18),@mfredenhagen 修复了 OpenTelemetry 中的 CVE-2026-39883(#19),@pinginfotrackingResponseWriter 实现了 Flush,修好了桶通知的流式输出(#34),@waterkip 将文档链接指向了 Silo 门户(#41)。

以新名字发布的第一个版本,也正是感谢所有为这个分支提交过 issue 的人的时刻——缺陷报告、兼容性发现与提案,无论已解决还是仍在处理:

@mosesdd(#1)、@Xavier-777(#2、#17)、@jiadzh(#3)、@TLINDEN(#4)、@AntonOfTheWoods(#5)、@zylpsrs(#6)、@nsanitate(#7)、@makinikm(#9)、@magicxor(#10)、@spaceg00se-r(#11、#14)、@heroes1412(#13)、@vampywiz17(#15)、@davinkevin(#20)、@chalukyaj(#30)、@cbornet(#31、#32)、@jvasile(#33)、@Kesavaambati(#35)、@redfoxfox(#38)、@kuldeep-link11(#39、#40)、@meesudzu(#42)、@pmezhuev(#43)、@kh0mka(#51)。

本版本的多项核心内容可以直接追溯到这些报告:内置客户端的保证来自 #4#9,LDAP-over-TLS 修复来自 #15,软件包载荷补全来自 #33,RPM GPG 签名来自 #43,迁移指南来自 #42,distroless 的 /data 修复来自 #55

仍在处理中的 PR 同样值得一提。@davinkevin 的 distroless 镜像 PR(#21)比本版本的试点早了数月——最终交付的变体以内置原生健康检查取代了该 PR,但方向是在那里首先提出的。@magicxor#12)与 @ycjlin#37)的一致性修复 PR 将在本版本发布后立即进入评审。

所有为本分支做出贡献的人都记录在 CONTRIBUTORS.md 中。GitHub 不为 fork 仓库生成贡献者图表,该文件即本项目的署名记录。

6 - Silo 20260804 发布

节点间存储边界加固、S3/IAM 策略修复、分片上传正确性、流式响应可靠性、通知修复、Go 1.26.5,以及重建并签名的发布流水线。

版本: 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/compress 1.18.7、Apache Thrift 0.24.0、SILO Console 2.0.0、silo-pkg 3.11.0 与 mcli 20260804。

安全加固

节点间 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:prefixs3:delimiters3: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 语句上,将这十二项敏感写操作从该模式中排除:

PutBucketPolicyDeleteBucketPolicyPutBucketObjectLockConfigurationPutBucketVersioningPutReplicationConfigurationPutBucketLifecycleDeleteBucketForceDeleteBucketPutBucketCorsDeleteBucketCorsPutBucketQOSPutInventoryConfiguration

DenyNotResource 行为不变。读取/列举操作、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_PROXIESaws: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_credentialsnkey_seedtls_handshake_first 键;
  • 将旧 NATS 环境变量拼写与存储的配置键分离;
  • 修复 NATS 迁移往返与 AMQP immediate/internal 映射;
  • 增加一项机械审计,把通知代码读写的键与各子系统注册的 schema 做比对;
  • 引用 libpq 连接串参数,使空白、引号与反斜杠保持其预期取值;
  • 阻止非法键诊断回显 secret 值。

通知键空间注册

警告

已知的旧迁移限制

继承的 Postgres 与 MySQL 旧迁移函数仍然写入未注册的 hostportusernamepassworddatabase 字段。因此迁移后的配置可能在下次加载时校验失败,而通知目标加载是跨子系统 fail-fast 的。此问题早于 20260804,但从连接串之前的数据库通知配置升级时,必须在重启前审查并转换。存储的 password 字段可能包含明文数据库密码。

组件与依赖

  • Go 1.26.5: 包含 crypto/tlsos 的安全修复,以及编译器、运行时、网络与 syscall 的修正。
  • klauspost/compress 1.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-pkg 3.11.0: 提供配套的策略、LDAP、证书、RNG 与时间格式修复,同时保留 github.com/minio/pkg/v3 模块路径。
  • mcli 20260804: 嵌入式客户端来自 pgsty/mc;发布镜像将其暴露为 mcli 并保留 mc 兼容别名。

配套发布说明见 silo-pkg 3.11.0mcli 20260804SILO 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 产出平台归档、校验和与软件包;多架构镜像从完成的发布按需发布。本地快照不能证明公开发布或镜像已存在。

兼容性与升级说明

  1. 集群滚动升级期间保持所有节点在同一发布版本。 节点间校验在 storage-REST 与 Grid 面上发生了改变;混合二进制未经生产测试。
  2. 审查自定义 IAM 策略。 为这十二项受保护的 bucket 写操作补上裸 bucket ARN。仅将 MINIO_API_LEGACY_BUCKET_RESOURCE_MATCH=on 作为临时迁移控制。
  3. 有意识地配置客户端地址信任。 如果 aws:SourceIp 或审计归属重要,请设置 MINIO_API_TRUSTED_PROXIES 并封闭代理周围的直连网络路径。
  4. 审查旧的数据库通知设置。 在重启前把 Postgres/MySQL 的 host/user/password 字段转换为受支持的连接串格式。
  5. 预期重复的 multipart 补全条目会失败。 多次发送同一分片编号的客户端现在会收到 InvalidPartOrder,而不是一个损坏但成功的对象。
  6. 使用匹配的 mcli 20260804 客户端禁用了自更新,必须通过软件包或 GitHub Releases 升级;mcli update 保留为兼容命令但以非零码退出。
  7. 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.0silo-pkg 3.11.0mcli 20260804 引用。

重点提交

  • ca7baa67080e8eaa42b6f70ab08:校验节点间路径、纠删元数据与分配大小
  • a36fd8fff:遏制 deadline-bounded 存储任务中的 panic
  • 2f55347f7:将 S3/IAM 策略条件绑定到真实请求值
  • 744a9dcd7:将 s3:versionid 绑定到有效对象版本
  • 97b7d2804:强制 bucket/object 资源边界
  • fe6dc4780:新增可信代理客户端地址边界
  • 22c1e41fd:拒绝重复的 multipart 分片编号
  • c8590413f3e14733f1:恢复完整对象与零长度 multipart 校验和行为
  • 8069a32ac65795ee1f:恢复响应提交与流式 flush 语义
  • 162ded3430c14d8151:修复通知键注册与 libpq 引用
  • 92471792689d346bf5:恢复安全的 buffer 池化与返回 buffer 所有权
  • 3b8a55dee:exec 进入降权进程使信号抵达服务端
  • 2ca4971d9:停止把构建机路径烧入二进制
  • 4c185d5a6e064b5555:加固发布工作流并移除影子配置
  • aa5139369:将 systemd unit 安装到 /usr/lib
  • 11d79fddcca674a696021110b45d88f46cce:对构建、vet、测试、lint、生成、race 与交叉编译把关,并对发布镜像做烟测

7 - mcli 20260804 发布

禁用自更新、修复 SUBNET 调试日志泄密、容器改用分支源码构建、打包体系迁移到 nFPM 并启用 RPM 签名。

发布日期: 2026-08-04 · 版本: RELEASE.2026-08-04T00-00-00Z

这是 pgsty/mc 社区分支自 20260417 以来的首次发布。本次更新修复了一处调试日志泄密问题,彻底切断了客户端与上游发布渠道之间的所有连接,将容器与软件包完全改由本分支自建,并把打包体系从 MinIO 的 pkger 迁移到标准 nFPM,同时首次为 RPM 包提供 GPG 签名。

上游 minio/mc 仓库已于 2026 年 7 月归档。其最后一个提交 77f82e18 正是本分支的基线,而上游从未发布过包含该提交的版本 —— 因此本次构建比历史上任何官方 mc 二进制都要新。

警告

行为变更

mcli update 自更新功能在本分支中 已被禁用。命令本身保留(接受原有参数以维持脚本兼容),但不再联网检查、也不会替换自身二进制,执行时会打印明确的提示信息,并恒定以退出码 1 结束。上游 mc update 在已是最新版时返回 0,脚本中如有依赖其退出码的调用应予移除。请通过 Pigsty 软件仓库或 GitHub Releases 升级。

同时,每次执行命令时向上游发布源发起的 自动版本检查已完全移除MC_UPDATE / MINIO_UPDATE 环境变量不再被读取。

主要变更

  • 禁用自更新,切断上游发布渠道:移除 minio/selfupdateaead.dev/minisign 依赖及全部二进制替换逻辑,删除更新通知器与 FIPS/非 FIPS 更新分支。update 命令保留为兼容壳,运行时辅助函数(Docker / DCOS / Kubernetes / 源码构建检测)迁移至独立的 cmd/runtime-info.go。此前该客户端会在每次执行时静默访问上游发布源并提示升级,现已不再有任何出站发布探测。
  • 容器与制品全部本地化:默认镜像改为从检出的分支源码构建,hotfix 二进制从本地构建上下文拷贝,不再下载任何上游预编译产物。移除上游发布用的 Dockerfile.releaseDockerfile.release.old_cpudocker-buildx.sh,并禁用已失效的 MinIO hotfix 上传目标。
  • 打包体系迁移至 nFPM:从 MinIO 的 pkger 迁移到标准 nFPM。产物结构与安装路径保持完全一致(/usr/local/bin/mcli、包名 mcli、版本方案 YYYYMMDDHHMMSS.0.0),但供应商信息改为 PGSTY,许可证改用 SPDX 标识 AGPL-3.0-or-later,Debian Section 由空值改为 utils
  • RPM 包首次提供 GPG 签名:RPM 由维护者主密钥在本地离线签名(密钥指纹 9592A7BC7A682E7333376E09E7935D8DB9BD8B20),签名前校验全部包元数据,签名后复验并重新生成校验和。DEB 与 APK 不做包级签名,其信任锚位于软件仓库层。
  • 构建溯源加固:此前所有已发布二进制都被 Go 工具链标记为「来自被修改的工作树」(vcs.modified=true),导致产物无法与其 Git 标签对应。本次修复该问题,并在发布与测试流水线中加入强制校验,确保每个二进制都能追溯到确切的提交。

安全修复

  • SUBNET 调试日志凭据脱敏:启用 --debug 时,SUBNET 相关的 HTTP 请求会打印完整报文。此前 api-key / api_key 查询参数、认证头以及响应体均以明文进入日志,而 SUBNET 的认证与注册端点会在响应中返回 API Key、License 与 Token。本次修复对两种参数拼写、重复参数值统一脱敏,屏蔽敏感响应头,并将 SUBNET 响应体整体排除在调试转储之外。该泄漏继承自上游,存在于包括上游 mc 在内的所有历史版本中:如果你曾对外分享过 SUBNET 相关命令(mcli license ... / mcli support ...)的 --debug 输出,请将其中的 API Key 与 License 视为已泄露并及时轮换。
  • 调试脱敏与调用方状态隔离:调试追踪改为转储请求与响应的 副本,确保脱敏动作不会污染调用方持有的对象;覆盖零长度、定长与未知长度三种响应体形态,且不影响调用方正常读取响应内容。

依赖更新

本周期的依赖工作属于安全维护而非例行升级:除 term / mod / sync / tools 四项例行刷新外,以下每一项升级都至少关闭一个 Go 漏洞数据库中已发布的安全公告;govulncheck 对本次发布的代码报告 零个可达的已知漏洞minio/mcminio-gomadmin-gominio/pkg 四个包本身从未有过任何安全公告。

  • Go 构建基线由 1.26.2 升级至 1.26.5(截至发布时 1.26 线最新版),纳入 1.26.3–1.26.5 各批安全修复,包括 GO-2026-4970os 包符号链接根逃逸)与 GO-2026-5856crypto/tls ECH 隐私泄漏)—— 对一个通过 TLS 下载对象并写入本地文件的 S3 客户端而言最直接相关的两项。
  • github.com/klauspost/compressv1.18.5 升级至 v1.18.7(关闭 GO-2026-5841)。
  • github.com/prometheus/prometheusv0.310.0 升级至 v0.311.3(关闭 GO-2026-5264、GO-2026-5381、GO-2026-5710)。
  • google.golang.org/grpcv1.79.3 升级至 v1.82.1(关闭 GO-2026-6061),同步刷新 genproto 系列。
  • golang.org/x/* 系列整体刷新:crypto v0.49.0v0.53.0(GO-2026-5005…5033 共 14 项公告)、net v0.52.0v0.56.0(GO-2026-5025…5030 及 GO-2026-5942)、sys v0.42.0v0.46.0(GO-2026-5024)、text v0.35.0v0.39.0(GO-2026-5970),termmodsynctools 同步升级。
  • 移除 aead.dev/minisigngithub.com/minio/selfupdate,并同步更新第三方致谢清单。

工程与交付

  • 集成测试依赖钉死:CI 不再从上游可变地址下载 MinIO 服务端,改用带 SHA-256 校验的 pgsty/minio 版本化发布归档,Go 版本钉在 1.26.5
  • 发布流水线校验:新增打包验证工作流,逐字节比对三种包格式内的二进制与构建产物是否一致,并校验包名、校验和、架构字段与全部元数据。RPM 元数据的期望值以签名脚本为唯一事实源,避免配置漂移导致发布中途签名失败。
  • CI 供应链加固:全部 GitHub Actions 钉到 commit SHA 并接入 dependabot,工作流权限收敛为只读,移除指向上游组织项目板的失效工作流。
  • 文档更新:README 中英文版本明确本分支的分发渠道与自更新策略,移除会导致误装上游 mc 的安装指引。
说明

已知问题

mcli watch(桶事件监听)在对接 任何已发布的 pgsty/minio 服务端版本时都无法收到事件。根因是服务端侧一处继承自上游的静默流式 flush 回归,与客户端无关,上一个 mcli 版本受影响的程度完全相同;修复已于 2026-07-29 合入服务端 master,但尚未随公开服务端版本交付。详见 SILO 20260618 发布说明PR #34

另外,本分支继承了上游未修复的历史缺陷;上游仓库已归档,这些问题今后只可能在本分支修复。其中最严重的是 minio/mc#5139mirror --remove --watch 在源端删除对象的 非当前版本 时,可能误删目标端的现存对象。在版本化桶上组合使用 --remove --watch 时请务必谨慎。

  • 9603ee3:fix: redact SUBNET secrets in HTTP debug logs
  • f6ae2b0:fix: disable self-update in Pigsty builds
  • c05a6e4:build: update Go deps and toolchain to 1.26.5
  • 1f105aa:build: use local fork artifacts for containers
  • 1182da5:ci: pin fork integration test dependencies
  • 9ee207f:docs: clarify Pigsty fork distribution channels
  • 0686cd8:fix: isolate SUBNET debug redaction
  • ad10a2a:build: complete local Docker context isolation
  • 5f54221:docs: update mc README and cn version
  • 02c0305:build: migrate release packaging to nFPM
  • 4c4dcc4:build: harden release provenance and package metadata

8 - Silo 20260618 发布

加固 LDAP STS、补齐 S3 Select 记录限制、移除 ReadMultiple、升级 Go 1.26.4 并刷新安全依赖。

发布日期: 2026-06-18 · 版本: RELEASE.2026-06-18T00-00-00Z

这是 pgsty/minio 社区分支的一次例行安全与依赖维护更新。该版本加固 LDAP STS 限流,补齐 S3 Select 超大记录限制,移除废弃的 ReadMultiple 节点间 storage-REST API,将 Go 构建基线升级到 1.26.4,并刷新 Go 模块依赖以吸收第三方安全修复。

说明

说明

已知问题:本版本与自 RELEASE.2025-12-03T12-00-00Z 以来的所有早期社区版本一样,带有一个继承自上游的静默流式 flush 回归,会导致 mc watch / 桶事件通知监听以及 S3 Select keepalive 失效。该问题没有 workaround。修复已于 2026-07-29 合入 master,但尚未随公开服务端版本交付;实现见 PR #34

主要变更

  • 移除废弃的 ReadMultiple storage-REST API:旧的节点间 /rmpl 端点不再保留兼容路径,而是连同 route、handler、client wrapper、storage interface、xlStorage 方法、生成数据类型和相关 metric 一并移除。上游 multipart 处理迁移到 ReadParts 之后不应再有生产调用者,但滚动升级时仍应让集群运行一致版本。
  • 补齐 S3 Select 超大记录限制:JSON Lines 输入现在走有界 reader 路径,因此在支持 SIMD 的 CPU 上也会一致拒绝超大记录,不再绕过限制。S3 Select stream error 现在会保留预期错误码,并将 JSON parser 错误包装为 JSONParsingError
  • 加固 LDAP STS 限流源地址分桶:限流现在仅按源 IP 分桶,避免按用户名共享的 bucket 被单一客户端耗尽并锁定合法用户。受信代理处理现在从右到左解析 X-Forwarded-For,拒绝全网段 trusted-proxy CIDR,忽略 RFC 7239 Forwarded,并明确记录 X-Real-IP 的部署约定。
  • 刷新 Go 运行时与模块基线:release、hotfix、goreleaser 与 old-CPU Docker 构建现在都使用 golang:1.26.4-alpinego.mod 更新到 Go 1.26.4;依赖刷新覆盖 NATS、Prometheus、Azure SDK、Apache Thrift、gRPC、OpenTelemetry、Google API/auth、Go x/* 以及相关间接依赖。

直接安全修复

  • CVE-2026-42600:移除废弃的 ReadMultiple storage-REST API,关闭 /rmpl 暴露的旧节点间文件读取路径。
  • CVE-2026-39414:补齐 JSON Lines 输入的 S3 Select 超大记录限制,并保留正确的 S3 Select 错误语义。
  • CVE-2026-33419:进一步强化 LDAP STS 限流记账与 trusted-proxy 源 IP 处理。

依赖安全更新

  • github.com/Azure/go-ntlmsspv0.1.0 升级到 v0.1.1,修复 CVE-2026-32952,避免畸形 NTLM challenge 触发 Go 进程 panic。
  • github.com/apache/thriftv0.22.0 升级到 v0.23.0,修复 Go TFramedTransport 实现中的 CVE-2026-41602
  • github.com/nats-io/nats-server/v2v2.11.1 升级到 v2.11.15,吸收 NATS 2.11.x 安全补丁线。重点覆盖 pre-auth WebSocket 与 leafnode 拒绝服务、MQTT 授权、JetStream 管理 API 授权、凭据暴露和请求身份伪造等问题,包括 CVE-2026-27889CVE-2026-29785CVE-2026-33217CVE-2026-33218CVE-2026-33222CVE-2026-33247
  • github.com/prometheus/prometheusv0.310.0 升级到 v0.311.3,吸收 Prometheus 关于 remote-read 拒绝服务、Web UI 存储型 XSS、remote-write 配置 secret 暴露等安全修复,包括 CVE-2026-42154CVE-2026-44903CVE-2026-42151CVE-2026-40179
  • 将发布构建基线升级到 Go 1.26.4,并刷新 golang.org/x/cryptogolang.org/x/netgolang.org/x/sysgolang.org/x/textgoogle.golang.org/grpc 与 OpenTelemetry 等模块族。即便此前锁定版本已经越过特定公开 advisory 的修复范围,这些更新仍让社区分支继续贴近上游已修复依赖基线。
  • 5e40665:fix: harden LDAP STS rate-limit source bucketing
  • fd69c89:fix: complete CVE-2026-39414 S3 Select record limit enforcement
  • 73ac524:fix: CVE-2026-42600 remove ReadMultiple storage-REST API
  • df627ff:fix: bump Go toolchain to 1.26.4
  • 3e61b1d:chore: update Go module dependencies

9 - Silo 20260417 发布

针对 OIDC、LDAP STS、S3 Select、复制元数据、unsigned-trailer 与 Go 工具链的集中安全加固。

发布日期: 2026-04-17 · 版本: RELEASE.2026-04-17T00-00-00Z

本次版本聚焦安全加固与兼容性收敛,集中修复了 OIDC、LDAP STS、S3 Select、对象复制元数据、unsigned-trailer、Snowball 上传链路,以及依赖与 Go 工具链相关的多项安全问题,并同步完成 LDAP TLS 回归修复与社区分叉文档整理。

主要变更

  • 身份认证链路收紧:OIDC / WebIdentity 现在只接受来自 IdP JWKS 的非对称签名 ID TokenHS256 等对称签名 token 不再被接受;LDAP STS 统一隐藏“未知用户”和“密码错误”的区别,降低用户名枚举风险。
  • LDAP STS 限流行为更新:限流现在同时按源 IP 与归一化用户名生效,成功请求不再错误消耗额度;默认仅使用 socket peer address 作为源地址,不再信任 X-Forwarded-ForX-Real-IPForwarded,如需按真实客户端 IP 限流,需显式配置 MINIO_IDENTITY_LDAP_STS_TRUSTED_PROXIES
  • 上传与写入路径更严格:presigned query 参数不能再与 unsigned-trailerPUT / multipart 上传组合使用;Snowball auto-extract 在 unsigned-trailer 路径下也会执行完整签名校验,匿名或伪造签名请求将被拒绝。
  • 复制元数据不再可伪造:普通 PUT / COPY 请求夹带的 X-Minio-Replication-* 内部复制头现在会被拒绝或忽略,只有可信复制链路才能写入相关内部元数据。
  • S3 Select 错误语义更明确:CSV 和 line-delimited JSON 遇到超大记录时会直接返回 OverMaxRecordSize,不再笼统返回 InternalError;依赖旧错误码的客户端或告警规则需要同步调整。
  • 运行时与依赖基线升级:修复 ldaps:// 未正确应用 TLS 配置的回归问题,替换 minio/pkg/v3pgsty/minio-pkg/v3,并锁定若干易引入 breaking changes 的关键依赖;同时升级 go-josego.opentelemetry.io 与 Go 1.26.2,统一构建与发布基线。
  • 文档与安全说明同步更新:刷新 SECURITY.mdVULNERABILITY_REPORT.mddocs/sts/ldap.md 等文档,新增安全通告索引,并将安全说明中的上游 minio/minio 引用统一切换为 pgsty/minio

修复的 CVE

  • CVE-2026-34986:升级 go-josev4.1.4,修复 JWT / JOSE 依赖中的已知安全问题。
  • CVE-2026-39883:升级 go.opentelemetry.io 依赖栈,修复 PATH hijacking 风险。
  • CVE-2026-33322:恢复严格的 JWKS-only OIDC JWT 验证路径,阻断 keyring 注入与算法混淆风险。
  • CVE-2026-33419:系统性强化 LDAP STS 认证、限流、源地址识别与记账逻辑,涉及 4 个后续修复提交。
  • CVE-2026-34204:拒绝不可信请求注入 X-Minio-Replication-* 元数据,防止对象被写入异常复制状态。
  • CVE-2026-39414:提前拒绝超大 S3 Select 记录,避免异常数据持续缓冲和解析。
  • GHSA-hv4r-mvr4-25vw:封堵 unsigned-trailer query auth 绕过。
  • GHSA-9c4q-hq6p-c237:加固 Snowball auto-extract 场景中的 unsigned-trailer 认证与签名校验。
  • CVE-2026-32280CVE-2026-32281CVE-2026-32283:升级 Go 到 1.26.2,吸收上游工具链与标准库安全修复。
  • c878ca0:fix: pin deps with breaking changes and fix LDAP TLS regression (#15)
  • e970ec5:fix: upgrade go-jose to v4.1.4 to patch CVE-2026-34986
  • a206510:fix: CVE-2026-39883 upgrade go.opentelemetry.io
  • fd65f11:merge: PR #18 upgrade go-jose to v4.1.4 for CVE-2026-34986
  • bc087e4:merge: PR #19 upgrade go.opentelemetry.io for CVE-2026-39883
  • f1f2239:fix: CVE-2026-33322 restore JWKS-only OIDC JWT verification
  • 6619d0c:fix: CVE-2026-33419 harden LDAP STS auth
  • fcb8f24:fix: CVE-2026-34204 reject untrusted replication metadata
  • c5765dc:fix: CVE-2026-39414 reject oversized S3 Select records
  • fa7c579:fix: GHSA-hv4r-mvr4-25vw block unsigned-trailer query auth bypass
  • b50ab58:fix: GHSA-9c4q-hq6p-c237 harden Snowball unsigned-trailer auth
  • 9a4b3cd:fix: CVE-2026-32280/CVE-2026-32281/CVE-2026-32283 upgrade Go to 1.26.2
  • c55b52c:fix: CVE-2026-33419 preserve LDAP STS rate limits on success
  • 817a457:fix: CVE-2026-33419 harden LDAP STS rate-limit source IP
  • 084a154:fix: CVE-2026-33419 tighten LDAP STS rate-limit accounting
  • 16e34f9:docs: refresh security guidance and fork references

10 - Silo 20260325 发布

围绕打包、稳定性、LDAP TLS、Docker 镜像与依赖安全的维护版本。

发布日期: 2026-03-25 · 版本: RELEASE.2026-03-25T00-00-00Z

这是一个以打包、稳定性与安全公告为主的维护版本,重点是完善交付镜像、修复 LDAP TLS 回归,并把已经锁定到安全版本的依赖明确纳入发布说明。

主要变更

  • mcli/mc 打入 Docker 镜像并增加校验流程,改善镜像开箱体验。
  • 修复 ldaps:// 场景中的 LDAP TLS 回归,确保 TLS 配置能够正确透传。
  • 移除从上游继承但社区分支不再使用的 CI/CD 工作流,减轻维护负担。
  • 固定若干关键依赖,避免上游 breaking changes 继续向下游扩散。

修复的 CVE

  • CVE-2026-24051:发布说明明确将 go.opentelemetry.io/otel/sdk 锁定在安全版本 v1.42.0,规避 macOS 上因 PATH hijacking 导致的任意代码执行风险。
  • CVE-2025-10543:发布说明明确交付了 github.com/eclipse/paho.mqtt.golang v1.5.1,修复超长 UTF-8 字符串编码错误导致的 MQTT 数据包内容异常。
  • CVE-2025-58181:发布说明明确交付了 golang.org/x/crypto v0.49.0,修复 ssh GSSAPI 认证请求可触发的无界内存消耗问题。
  • f2f9a40:add mcli/mc from pgsty/mc to Docker image
  • ce1c537:fix: pin deps with breaking changes and fix LDAP TLS regression (#15)
  • ee55e53:remove upstream CI/CD workflows inherited from minio/minio

11 - Silo 20260321 发布

升级 Go 1.26.1、适配更严格的编译与 lint 检查,并完成大范围安全依赖刷新。

发布日期: 2026-03-21 · 版本: RELEASE.2026-03-21T00-00-00Z

这是一次围绕 Go 1.26.1 与依赖收敛展开的维护版。除了适配更严格的编译与 lint 检查外,这个版本也完成了本轮最关键的一次安全依赖刷新。

主要变更

  • 将构建环境从 Go 1.26.0 升级到 Go 1.26.1
  • 全面刷新直接与间接依赖,收敛新工具链下的兼容性问题。
  • 修正 Go 1.26.1 更严格检查暴露出来的一批 lint 与测试问题。

修复的 CVE

  • CVE-2026-27137:Go stdlib 从 1.26.0 升级到 1.26.1,修复 crypto/x509 对邮箱约束校验不完整的问题。
  • CVE-2026-27138:Go stdlib 从 1.26.0 升级到 1.26.1,修复畸形证书触发 crypto/x509 panic 的问题。
  • CVE-2026-25679:Go stdlib 从 1.26.0 升级到 1.26.1,修复 net/url 对 IPv6 host literal 解析不严格的问题。
  • CVE-2026-27139:Go stdlib 从 1.26.0 升级到 1.26.1,修复 osFileInfo 可逃逸 Root 边界的问题。
  • CVE-2026-27142:Go stdlib 从 1.26.0 升级到 1.26.1,修复 html/templatemeta refresh 场景下 URL 未正确转义的 XSS 风险。
  • CVE-2026-26958filippo.io/edwards25519v1.1.0 升级到 v1.2.0,修复 MultiScalarMult 可能产生错误结果或未定义行为的问题。
  • CVE-2025-10543github.com/eclipse/paho.mqtt.golangv1.5.0 升级到 v1.5.1,修复超长 UTF-8 字符串编码错误导致的 MQTT 报文异常。
  • CVE-2026-24051go.opentelemetry.io/otel/sdkv1.38.0 升级到 v1.42.0,修复 macOS 上通过 PATH hijacking 触发任意代码执行的风险。
  • CVE-2026-33186google.golang.org/grpcv1.77.0 升级到 v1.79.3,修复 HTTP/2 :path 缺少前导斜杠时的授权绕过问题。
  • 5abd9a8:bump golang to 1.26.1 and update deps
  • 377fc61:fix: satisfy stricter Go 1.26.1 linter checks

12 - Silo 20260314 发布

切换到社区维护的 Console 分支,并完成大范围兼容性与依赖刷新。

发布日期: 2026-03-14 · 版本: RELEASE.2026-03-14T12-00-00Z

这个版本完成了向社区维护 Console 分支的切换,并在切换过程中做了一轮较大幅度的依赖更新,为后续 Go 1.26.x 维护版打下基础。

主要变更

  • 切换到社区维护的 georgmangold/console v1.9.1,替换不可持续维护的上游 Console 依赖。
  • 大幅更新 go.mod 中的直接与间接依赖,使 Console 与新工具链组合能够稳定构建。
  • 修复 grid_test.gogo vet 格式化指令问题,并调整部分测试以适配 Go 1.26 的 HTTP 行为变化。

修复的 CVE

  • CVE-2025-47913golang.org/x/cryptov0.37.0 升级到 v0.46.0,修复 ssh/agent 在处理异常响应时可能导致客户端 panic 的问题。
  • CVE-2025-58181golang.org/x/cryptov0.37.0 升级到 v0.46.0,修复 ssh GSSAPI 认证请求可触发无界内存消耗的问题。
  • CVE-2025-47914golang.org/x/cryptov0.37.0 升级到 v0.46.0,修复 ssh/agent 对畸形身份消息缺乏边界校验导致的 panic 问题。
  • CVE-2025-47911golang.org/x/netv0.39.0 升级到 v0.48.0,修复 html.Parse 在特制输入下的二次复杂度解析问题。
  • CVE-2025-58190golang.org/x/netv0.39.0 升级到 v0.48.0,修复 golang.org/x/net/html 可能陷入无限解析循环的问题。
  • 68521b3:add github ci/cd pipeline
  • 00f3cf7:RELEASE.2026-03-14T12-00-00Z with go 1.26.0

13 - Silo 20260214 发布

恢复内嵌 Console,建立 GitHub CI/CD,升级 Go 1.26.0,并补齐社区交付入口。

发布日期: 2026-02-14 · 版本: RELEASE.2026-02-14T12-00-00Z

这是社区分支早期的一个基础设施版本,除了恢复内嵌 Console 与建立 GitHub CI/CD 之外,也把 Go 运行时基线提升到 1.26.0,因此一并消化了上一代工具链中的一批安全问题。

主要变更

  • 恢复内嵌 Console,并更新 README 以明确社区维护分支的定位。
  • 新增 GitHub CI/CD 流水线,为后续自动构建和多平台分发建立基础。
  • 补充文档、Docker、GitHub 仓库与 pig 包管理器安装入口,完善发布入口。

修复的 CVE

这些问题随着 Go 从 1.25.5 升级到 1.26.0 一并被修复,包括:

  • CVE-2025-68121crypto/tls 在会话恢复时可能错误接受已变更 CA 配置。
  • CVE-2025-61730:TLS 1.3 在跨加密级别 record 中可能错误处理握手消息。
  • CVE-2025-61726net/url 查询参数解析可导致内存耗尽。
  • CVE-2025-61728archive/zip 构建索引时可能触发过高 CPU 消耗。
  • CVE-2025-68119cmd/go 在调用外部 VCS 工具链时可能触发意外代码执行。
  • CVE-2025-61731#cgo pkg-config: 指令可导致任意文件写入。
  • CVE-2025-61732cmd/cgo 文档注释解析差异可能导致代码走私。
  • 8630937:Restore embedded console and update README for community fork
  • 5d57938:add github ci/cd pipeline

14 - Silo 20251203 发布

首个社区打包与分发基线,提供 APK、DEB 与 RPM 制品。

发布日期: 2025-12-15 · 版本: RELEASE.2025-12-03T12-00-00Z

这是目前可追溯到的首个社区版发布,主要目标是建立社区维护分支的打包与分发基线,而不是在此前社区版本之上做增量修复。

主要变更

  • 基于 minio/pkger 建立社区版打包流程。
  • 选择 MinIO 进入 maintenance mode 后的一版上游基线作为社区分支起点。
  • 首次产出 apkdebrpm 等多种平台包,为后续持续发布建立基础。

修复的 CVE

  • 这是首个社区版发布,GitHub Release 未单独声明相对更早社区版本的安全修复清单;本页不追溯其相对上游维护模式基线的全部历史 CVE 差异。
  • d4cd4b4:RELEASE.2025-12-03T12-00-00Z with go 1.25.5