
mise packslip forget解除项目签名者固定安全应对签名身份轮换【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise导读mise packslip forget是 mise 中用于**解除某个 packslip 项目已固定的签名者pinned signer**的命令。当通过packslip:后端安装工具时mise 会像 SSH 记住主机那样记住首次接受的签名身份后续凡是签名者变化、签名方案变弱、厂商变重打包者或丢失构建出处provenance的发布都会被拒绝直到用户明确表态。本文围绕 docs/cli/packslip/forget.md 这一命令文档深入讲解它的使用场景、参数与输出并结合 src/cli/packslip/forget.rs、src/packslip_pins.rs 等源码与 e2e 测试讲清固定—校验—解除—重新固定的完整信任模型。读完你将掌握何时必须执行forget、项目名如何书写、命令背后的数据落盘位置与降级拒绝逻辑以及如何用mise packslip pins验证操作结果。命令概览用法mise packslip forget PROJECT效果修改状态write源码位置src/cli/packslip/forget.rs所属命令组docs/cli/packslip.md另有子命令 docs/cli/packslip/pins.md该命令的作用是忘记某个项目固定的签名者使下一次被接受的发布重新设定它。也就是说forget只清除本机记住的信任记忆不会改变 vendor 的签名事实也不会让未经验证的发布自动通过——下一次安装依然要经历完整的签名校验只是不再与旧的固定记录做连续性比对。命令定义源码 src/cli/packslip/forget.rs 中有明确注释/// Forget a projects pinned signer, so the next release accepted sets it again /// /// Do this when the vendor has announced a new signing identity or key.即当 vendor 官方宣布新的签名身份identity或密钥key时执行。参数PROJECT— 要解除固定的项目名。项目名必须按 packslip 后端命名规则书写支持以下形式均可带或不带packslip:前缀形式示例说明完整仓库地址github.com/owner/repoGitHub 仓库全名简写仓库owner/repogithub.com被隐含补全独立域名主机tool.example.com使用.well-known/packslip.json签名发布列表的项目带前缀packslip:github.com/owner/repo前缀会被剥离后解析从实现看src/cli/packslip/forget.rs 会先剥离packslip:前缀再调用project_name归一化项目名pub(super) fn run(self) - Result() { let name self .project .strip_prefix(packslip:) .unwrap_or(self.project); let project project_name(name)?; if packslip_pins::forget(project)? { miseprintln!(forgot the pinned signer of packslip:{project}); } else { miseprintln!(packslip:{project} had no pinned signer); } Ok(()) }project_name的归一化规则定义在 src/backend/packslip.rs先去掉首尾的/若第一段不含.则补全为github.com/…若项目既不在已知 forge 上、又没有仓库路径则报错提示使用github.com/owner/repo、owner/repo或诸如tool.example.com的主机名。因此mise packslip forget jdx/packslip与mise packslip forget github.com/jdx/packslip指向同一个项目。标志-h --help— 打印帮助信息。forget不接受其他标志。它只是提交单个项目名行为是确定性的要么忘记了要么本来就没有固定记录。适用场景何时需要 forget命令文档给出的核心场景只有一句话当 vendor 宣布了新的签名身份或密钥时。结合 src/packslip_pins.rs 的降级拒绝逻辑可以展开为以下几类具体情形签名者更换signer change项目从 GitHub Actions 工作流 A 切到工作流 B 签名工作流路径不同即视为不同签名者或者从无密钥签名keyless切换到显式公钥key。签名方案变弱weaker scheme例如从sigstore-oidc切到sigstore-key代码中把方案变更与签名者变更同等对待见 src/packslip_pins.rs。厂商直签变成重打包者vendor → repackager当已接受过 vendor 直签的发布后来者却是 repackager 签的会被拒绝。丢失构建出处provenance之前每个构件都链接了构建出处后来的发布不再链接会被拒绝。撤销误伤后的恢复vendor 曾撤回某版本、或补充分发列表消失被拦截见 src/packslip_pins.rs在确认信任策略后需要重新初始化。这些拒绝都来自连续性校验check_againstsrc/packslip_pins.rsif pin.scheme ! observed.scheme || pin.signer ! signer { problems.push(format!( is signed by {signer} ({}), but {} ({}) signed what mise accepted before, observed.scheme, pin.signer, pin.scheme )); } if pin.attested_by vendor observed.attested_by repackager { problems.push( is attested by a repackager, but the vendors own packslip was accepted before.into(), ); } if pin.provenance !observed.provenance { problems.push(drops the build provenance every artifact linked before.into()); }当上述任一情况被触发时错误信息会直接提示补救命令src/packslip_pins.rspackslip:{project}: this release {问题列表}. If the vendor announced the change, run mise packslip forget {project} and install again; the next release accepted sets the pin.这正是forget命令在真实故障场景中的入口。固定pin与像 SSH 记住主机的信任模型要理解forget的价值先理解它删除的是什么。命令组文档 docs/cli/packslip.md 阐述了整体模型通过packslip:后端安装的工具会按项目名所隐含的身份进行验证mise 随后记住它接受的签名者就像 SSH 记住主机一样。之后来自另一个签名者、更弱方案、厂商曾直签过的重打包者、或丢失构建出处的发布都会被拒绝直到有人明确表态。从源码看每次成功校验并接受一个发布后mise 会调用recordsrc/packslip_pins.rs写入固定记录内容包括字段含义备注scheme签名方案sigstore-oidc或sigstore-keysigner签名者标识工作流路径去掉 ref或密钥 idissuerOIDC 签发者可选attested_by认证方vendor或repackagerprovenance是否链接构建出处布尔unlogged是否接受过无透明日志条目的 bundle布尔pinned_at固定时间RFC 3339这些记录保存在状态目录下的packslip/pins.toml中src/packslip_pins.rspub(crate) fn pins_file() - PathBuf { dirs::STATE.join(packslip).join(pins.toml) }文件内容大致如下[pins.github.com/owner/repo] scheme sigstore-oidc signer https://github.com/owner/repo/.github/workflows/release.yml issuer https://token.actions.githubusercontent.com attested_by vendor provenance true unlogged false pinned_at 2026-09-01T12:00:00Z [sequences.github.com/owner/repo] # 该机器见过的最高发布列表序号注意几个关键设计均可从 src/packslip_pins.rs 注释确认keyless 签名者取去 ref 的工作流路径signer_ofsrc/packslip_pins.rs对sigstore-oidc且以https://开头的身份会切掉最后一个之后的 ref。因此同一工作流的新 tag 视为同一签名者而邮箱、SPIFFE URI 等身份会保留全部字符避免aliceexample.com与aliceexample.invalid被合并。降级被拒、升级被记住record在已有 pin 时只允许更强的方向变化——例如 provenance 从无到有会被记住为新基线反之则被拒src/packslip_pins.rs。并发安全读改写全程持有pins.toml旁边的.lock文件锁避免两个安装进程互相覆盖src/packslip_pins.rs。拒绝的发布不落盘check是只读的只有发布整体通过后才record被拒的安装不会留下 pin 痕迹src/packslip_pins.rs。forget删除的正是以上整套记忆既包括项目的 pin也包括其sequences发布列表序号见 src/packslip_pins.rs/// Drop a projects pin and sequence, so the next release accepted sets /// them again. Returns whether there was one. pub(crate) fn forget(project: str) - Resultbool { forget_at(pins_file(), project) } pub(crate) fn forget_at(path: Path, project: str) - Resultbool { let _lock locked(path)?; let mut pins load(path)?; let had pins.pins.remove(project).is_some() | pins.sequences.remove(project).is_some(); if had { save(path, pins)?; } Ok(had) }forget_at返回的布尔值正好对应命令输出返回true打印forgot the pinned signer of packslip:{project}返回false打印packslip:{project} had no pinned signer。也就是说重复对同一项目执行 forget 是无害的——第二次只是提示本来就没有固定记录。操作示例典型轮换流程假设厂商宣布更换签名工作流你安装新版时收到类似错误packslip:github.com/owner/repo: this release is signed by 新工作流 (sigstore-oidc), but 旧工作流 (sigstore-oidc) signed what mise accepted before. If the vendor announced the change, run mise packslip forget github.com/owner/repo and install again; the next release accepted sets the pin.执行mise packslip forget github.com/owner/repo预期输出forgot the pinned signer of packslip:github.com/owner/repo再次安装mise install packslip:github.com/owner/repo最新版本这一次校验通过后新签名者会被记录为新 pin后续连续性检查从新基线开始。简写与前缀以下写法等价github.com被隐含补全、packslip:前缀被剥离mise packslip forget jdx/packslip mise packslip forget github.com/jdx/packslip mise packslip forget packslip:jdx/packslip mise packslip forget packslip:github.com/jdx/packslip对无记录的项目的操作mise packslip forget tool.example.com如果该项目从未被固定过输出packslip:tool.example.com had no pinned signer验证操作结果forget之后用只读命令 docs/cli/packslip/pins.md 检查剩余固定记录mise packslip pins # 人类可读列表 mise packslip pins --json # JSON 格式便于脚本处理当所有记录都被清除时pins会提示no packslip signers pinned。端到端测试验证仓库 e2e 测试 e2e/backend/test_packslip 完整演示了固定 → 检查 → 忘记 → 再检查的闭环# The signer is pinned, the way SSH remembers a host, and can be forgotten. assert_contains mise packslip pins https://github.com/jdx/packslip/.github/workflows/release.yml assert_contains mise packslip forget jdx/packslip forgot the pinned signer assert_contains mise packslip pins no packslip signers pinned该测试还展示了其他相关行为安装packslip:github.com/jdx/packslip0.2.0后packslip pins能列出其签名工作流keyless 签名的https://github.com/jdx/packslip/.github/workflows/release.yml用简写jdx/packslip执行 forget 同样生效印证了项目名归一化forget 后 pins 输出变为no packslip signers pinned印证了删除语义该测试也验证了packslip子命令组默认行为是pinssrc/cli/packslip/mod.rs。单元测试层面src/packslip_pins.rs 验证了 forget 的幂等性与解除后新签名者可进入一次// Forgetting lets a new signer in, once. assert!(forget_at(path, project).unwrap()); assert!(!forget_at(path, project).unwrap()); record_at(path, project, keyed).unwrap(); assert_eq!(load(path).unwrap().pins[project].scheme, sigstore-key);第一次 forget 返回true确有记录第二次返回false已无记录随后原本被拒的密钥签名发布可以重新被接受并写入新 pin。另一个测试 src/packslip_pins.rs 则验证了已接受的发布列表在 forget 之前不允许消失——即 forget 也是解除列表连续性拦截的途径之一。与锁文件承诺的关系需要特别强调forget 只清除本机状态目录下的pins.toml不会修改项目锁文件mise.lock中的签名者承诺。锁文件会记录每个平台构件的 URL、校验和以及签名者与认证方承诺见 docs/dev-tools/packslip-verification.mdmise.lock— 记录项目签名者与认证方承诺以及每个平台的构件 URL 和校验和包括在另一台机器上首次安装时。因此完整的签名轮换流程应为确认 vendor 官方公告的新签名身份或密钥mise packslip forget PROJECT清除本机固定记录更新/重新生成mise.lock例如重新mise install让新签名者写入锁文件或让锁文件随新安装更新用mise packslip pins确认新 pin 已写入。另外文档明确警告直接删除pins.toml会重置所有项目的本地连续性这不是常规故障修复手段且不会移除锁文件中的签名者承诺docs/dev-tools/packslip-verification.md。相比之下mise packslip forget PROJECT是精准的、单项目的、可审计的官方操作。注意事项与最佳实践先确认厂商公告再 forget连续性检查存在的意义是防止静默的信任漂移。只有当 vendor 官方宣布更换签名身份或密钥时才应解除固定否则一个被劫持或重打包的发布可能借此混入。forget 不是绕过验证的手段解除固定后下一次安装仍会执行完整的签名验证bundle 签名、透明日志、项目/版本一致性、构件摘要与大小只是不再与旧 pin 比较。错误信息中不同阶段的问题要用不同手段修复同样适用forget 不能修复摘要不匹配、签名无效或主机要求不满足docs/dev-tools/packslip-verification.md。幂等安全对无记录的项目的 forget 会输出had no pinned signer不会报错、不会修改任何文件。善用pins做变更前快照执行 forget 前先运行mise packslip pins --json记录旧 pin签名者、方案、时间戳便于事后审计与对比。注意列表连续性联动forget同时删除项目的序列号记录sequences因此它也能解除已接受的签名发布列表消失这一拦截src/packslip_pins.rs 中的错误提示正是建议恢复列表或显式 forget 该项目的 pin。参考文档mise packslip forget 命令文档mise packslip 命令组文档mise packslip pins 命令文档Packslip 验证与策略指南packslip 后端实现签名者固定记录与校验逻辑packslip 后端 e2e 测试【免费下载链接】misedev tools, env vars, task runner项目地址: https://gitcode.com/GitHub_Trending/mi/mise创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考