跳转到内容
GitHub

供应链安全

了解 Depsilo v0.9.4 的恶意包封锁、制品篡改检测与安全停用的最小发布年龄边界。

Depsilo 把供应链策略放在包管理器与上游之间。v0.9.4 提供三个相互独立的控制:

控制 新安装默认值 结果 主要边界
最低发布年龄 暂不可用 启用状态下的正阈值会在启动时被拒绝 等待制品来源与发布时间证明完成绑定
已知恶意包封锁 开启,每 6 小时同步 以 HTTP 451 MALICIOUS_BLOCKED 拒绝匹配版本 只覆盖当前已确认身份的 OSV MAL-* 记录
篡改检测 开启 保留首见哈希并发出严重告警;不返回 451 被动、首见信任,不验证第一次获取的来源真实性

这三个控制彼此独立。最小发布年龄不可用不会关闭恶意包封锁或篡改检测。

历史配置中的阈值只可按对应版本的发布说明解释。当前版本请保持默认的零阈值,并使用人工 Package Rule 或已知恶意包列表处理明确的安全决策。该规则不会改变缓存、上游或其他策略。

恶意包封锁默认开启:

[supply_chain.blocklist]
enabled = true
sync_interval = "6h"
# mirror_url = "https://osv-vulnerabilities.storage.googleapis.com"
# proxy = "http://127.0.0.1:7890"

v0.9.4 从 OSV malicious-packages 数据集中同步 npm、Cargo、Composer、NuGet、Go 和 Maven 的 MAL-* 记录。它导入明确版本列表和“所有版本”通告;没有明确 版本列表的有界范围会被跳过,因为此版本不对这种范围作推导。

匹配发生在发布年龄和 allow 规则之前。已在缓存中的匹配制品也不会通过该门继续提供, 但字节会留在存储中,直到 LRU 或管理员清理。确认误报时,管理员可创建最长 24 小时的 审计覆盖;覆盖不能原地延期,继续使用必须重新作出有记录的决定。

同步失败采用降级策略:

  • 本地已有数据时,继续使用最后一次成功的数据集。
  • 本地没有任何数据时,不会阻断任何版本。
  • 同步错误本身不会让整个代理停止提供包。
[supply_chain.tamper_detection]
enabled = true

对于被视为不可变的制品,Depsilo 在第一次流式获取时记录 SHA-256。后台自然刷新若在 同一版本下收到不同字节,它会拒绝把替换内容写入缓存,继续保留首见缓存副本,并记录 严重 tamper_detected 事件;配置了 webhook 时也可发送通知。如果首见副本已经被 LRU 淘汰,之后的 cache miss 会先存储并返回重新获取的字节,再与保留的哈希基线比较并告警; 此时旧副本已经无法恢复。

必须同时理解以下限制:

  • 检测是被动的,只在正常后台刷新或淘汰后的再次获取中比较,不主动探测上游。
  • 它是告警机制,不会返回 451,也不是通用的阻断策略。
  • “首见”是本地基线,不是签名或透明日志证明;第一次获取已经被污染时,哈希也会记录 被污染的字节。
  • 如果 LRU 已删除原始缓存副本,不一致的新字节在验证前已经被存储并可能提供给客户端; Depsilo 仍会使用旧哈希告警,但无法恢复旧字节。

常见的绕过路径包括:

  • pip 的额外直连 index;不要让 --extra-index-url 指向不受控上游。
  • Go 的 GOPROXY 使用 |direct 等会在错误后直连的 fallback。
  • Composer 在镜像 dist 被拒绝时可能回退到原始 dist URL。要硬性阻断,必须限制客户端 对原始下载地址的直接访问。

Depsilo 可转发生态自身的校验和或签名,但不会把未签名制品变成有来源证明的制品,也不 替代上游签名、构建来源证明、锁文件和 SBOM。最小发布年龄当前不可用;恶意列表阻断已知 项目;篡改检测识别同版本字节变化。这些控制都不是对包安全性的完整证明。

隔离阻断、allow 绕过、批准与撤销、恶意包阻断与临时覆盖、篡改事件都会写入数据库中的 审计事件。可在 Admin 中按生态、动作和包查看。配置 webhook 后,隔离和恶意包阻断可 立即通知,篡改不匹配使用严重级别。

上线前至少验证一次:

  1. 配置正的最小发布年龄阈值会在启动时被拒绝。
  2. 一个已审核的 Package Rule 能阻断请求并留下审计记录。
  3. blocklist 同步状态和最近成功时间可见。
  4. 客户端没有可绕过代理的备用 registry 或直连出口。
  5. 审计记录和 webhook 到达预期的值班通道。