Skip to content

Releases

release 1.4.1

Choose a tag to compare

@unixsec unixsec released this 04 Nov 12:27

安全修复

本版本修复的问题来自 v1.4.0 的从零安装端到端验证:在全新环境中安装后,扫描了 skillhub 下载量前 200 的真实 skill。

  • auditor 可以提交扫描,并抢注 skill 的归属(高):按权限矩阵,auditor 不能提交扫描,但 POST /v1/scans 放行了。skill 的 owner 在首次提交时登记,所以 auditor 能抢先注册别人的 skill_id。现在纯 auditor 提交返回 403;同时持有 approver 或 admin 的不受影响。控制台对纯 auditor 不再显示提交表单。
  • 市场接口是另一个入口(高):OIDC 登录的人类会话,scopes 直接取自 IdP 签发的 token。如果 IdP 给人签发了 scan:submit,auditor 可以经 POST /v1/market/scans 绕过上面的限制。现在 /v1/market 只接受机器身份,即 client-credentials、账号密码和 mTLS 三种;人类会话返回 403 only available to service accounts,并且在限流计数之前就被拒绝。
  • 带命名空间的 skill 无法隔离(高):inventory 的单 skill 路由(详情、quarantine、restore、retire、owner、baseline)不接受带 / 的 skill_id,比如 @acme/deploy-helper,一律返回 404。实测环境中 262 个 skill 里有 251 个带 /,也就是说隔离这个应急手段对大多数 skill 用不了。现在原样写法和 URL 编码写法都能用。

新增两个守卫测试:

  • 凡是会创建扫描的路由,都必须拒绝纯 auditor;新增的提交接口会自动被覆盖。
  • 应用里不能出现不带 :path 的 {skill_id} 路由。

部署修复

  • 开启动态沙箱执行器、只按 chart 安装时,monolith 连不上 MySQL:chart 渲染的出站策略只放行了 apiserver。现在它带上了 deploy/networkpolicy/monolith-egress-allowlist.yaml 中的全部规则,scripts/check_chart_render.py 会检查两者是否一致。
  • 沙箱因隔离证明失败被跳过时,没有任何日志:现在每次状态变化(拒绝执行、恢复)记一条 warning,状态不变时不重复记。部署指南 §6.1⑥ 补上了 Kyverno 渲染漏写的 -s <沙箱命名空间>,并新增 §6.14「启用动态沙箱执行器」。
  • 离线包:build_offline_bundle.sh 新增三个选项。打出的镜像里写入构建提交,/healthz 不再显示 build: unknown。
    • --mtu N / --network NAME:用于路径 MTU 小于 1500 的网络。
    • --with-sandbox:打入沙箱的 runner 和 dnstrap 镜像,并把执行器需要的 digest pin 写进 manifest。

文档

  • README 的扫描示例改为真实输出:curl … | sh 命中 NET-07,等级 MEDIUM,判 REVIEW。这个等级是有意设定的。另外,API 返回的 severity 是数字(0–4)。
  • 部署指南修正了过期的离线包 tag(以前写的是 0.1.0)。市场接入指南的排错表补充了上面那个新的 403。

升级须知

  • 客户端可见的变化:用浏览器或 OIDC 人类会话调用 /v1/market 的,现在返回 403。按设计,市场接口只给服务账号用。
  • 没有新增配置项,缓存身份不变,升级后不会重新判定。
  • 改配置的方式:仍然用 helm get values 取出线上真值,合并后再 helm upgrade。

所有测试都跑在真实的 k3s、MySQL 和 Redis 上:全量 4407 passed,另有 2 个已知的 vendor pin 用例需要 .git 才能跑。修复也在线上复测过:auditor 提交被拒;200 个带 / 的 skill id 全部能打开;沙箱执行正常,判定与修复前一致。市场接口的修复由集成测试和守卫测试覆盖。

release 1.4.0

Choose a tag to compare

@unixsec unixsec released this 31 Oct 16:55

Highlights

  • 扫描管线存活性 — 必需的消费组集中在 airlock.REQUIRED_GROUPS 一处声明。消费组被删除后,
    整个拓扑 1 秒内自愈;此前 monolith 的 workers 组不会自动恢复,实测零吞吐持续了 26 分钟,
    而健康面板始终显示 ok。新增事件循环停摆探测器;解包改在线程里执行,突发负载下
    /healthz 的最大延迟从 30016ms 降到 41ms。
  • 进度、准入与沉默引擎 — GET /v1/scans/{id} 现在总会带 progress 对象,能区分"卡住"和
    "忙"。管线超过阈值时,两条提交路径都返回 429 和 Retry-After。持续不交付结果的顾问型引擎
    会被移出等待集,并在判定里写明 advisory_engine_silent:<engines>;按扫描是否真的等过它来判定,
    并设有时效上限,引擎恢复后会自动回到等待集。
  • 13 个自研引擎与评分方案 p4 — 检测引擎加固,评分新增 SC1–SC6 守卫和降级分类。
    在 186 个包上与旧版逐包零差异;在 60 个混合语料上,判定只收紧、没有放宽。
  • 动态沙箱执行器(gVisor + Kubernetes) — 在隔离的 Job 里真正执行技能包,v1 只放行 DNS 陷阱,
    其余网络一律拒绝。执行在 monolith 内的异步通道中进行,不再拖住 worker tick。通道按积压
    弹性决定宽度,沙箱 ResourceQuota 由 maxConcurrency 推导。因容量不足而证据不全的扫描,
    会在通道空闲时自动补全重扫,最多 2 次。默认关闭,节点上必须先装好 gVisor RuntimeClass。
  • 吞吐 — 同一批 60 个真实包、判定逐包不变的前提下:181s(4 核)→ 140s → 88s(8 核)。
    其中一处是存在已久的缺陷:engine-runner 的内联引擎在事件循环上阻塞执行,配置的"宽度"
    从未让它们真正并行。
  • 结果收集与重投 — 收集器每个 tick 按时间预算排空结果流;sweep 在 workers 组或结果流有积压时
    不再重投扫描。执行器开启时,重投从 156 次降到 0,用时从 848s 降到 230s。

升级须知

  • 缓存身份变化:评分方案升到 p4,执行器配置也计入缓存身份,所以升级后同样内容的包会重新判定,
    不会沿用旧结果。
  • 客户端可见的变化:管线过载时提交接口返回 429 并带 Retry-After,调用方需要按它退避重试。
  • 新增配置项:
    • engineRunner.maxConcurrency:默认 3,engine-runner 沙箱层的宽度上限。加核后要连同
      limits.cpu 一起调高,否则加的核用不上。
    • dynamicSandbox.executor.laneDrainTargetS:默认 30,决定积压清空过程中通道保持多宽。
      它不会抬高峰值,峰值仍由 maxConcurrency 和 quota 限定。
    • SKILLSCAN_ENGINE_SILENCE_WINDOW:默认 20,判定引擎沉默的样本窗口。
    • 沉默排除的时效 max_age_s:默认 900s。
  • 改配置的方式:用 helm get values 取出线上真值,合并新键后再 helm upgrade。
    不要只带新键升级,否则其余值会回落到默认值。

所有结论都来自在真实 k3s、MySQL 和 Redis 上的测试:全量 4393 passed,2 个已知的 vendor pin 用例
需要 .git 才能跑。

release 1.2.0

Choose a tag to compare

@unixsec unixsec released this 12 Aug 13:41

Highlights

  • 管线健康面 — 一次调用 GET /v1/admin/pipeline 读到队列深度、消费组 lag/PEL、
    worker 存活、任务状态分布与死信量。任一分区读不到时呈现 unknown 而非默认健康。
  • 有界流保留 — 系统内第一条 Redis 流裁剪:只删除每个消费组都已确认消费、且超过
    24 小时取证地板的历史条目,分批执行,PEL 与未投递条目一概不动。
  • 阈值告警接线 — 五个维度(流积压、投递停滞、超龄排队、最老等待、死信率)经日志与
    SIEM CEF 输出,含级别迁移去重与量级再发射。
  • 企业事故修复 — worker tick 步骤结构性隔离(单步故障不再拖垮整轮)、DSN 凭据
    URL 转义、连接池主动回收、可选 Redis Sentinel 发现、镜像构建指纹经 /healthz 自证。
  • 共享内容多归属 — 多个团队可各自注册同一份技能包,判定共享而归属独立;豁免、
    复审授权、信任层级与信息披露四处做了跨租户封口。
  • 市场接口可用性 — M2M 契约终于能从 Helm chart 启用(此前三个变量在 chart、
    VM 清单与 compose 中均无出口,任何 Helm 部署下调用均返回 401)。

Release 1.1.0

Choose a tag to compare

@unixsec unixsec released this 12 Aug 13:39

Highlights

  • LLM gateway — a single egress point for every LLM-backed engine. Translates
    each provider's dialect (model naming, token-limit field, Anthropic's top-level
    system, paired-field integrity) and classifies every outcome with a stable
    code, so a refused request shape is distinguishable from a slow one.
  • CPU-aware sandbox scheduling — concurrency is chosen from queue depth and
    bounded by the container's cgroup CPU quota, not by host cores.
  • Threat intel — signature-verified offline IOC import enables the intel
    matcher tier (domain / IP / hash).
  • Pagination — reviews, inventory and reeval listings are windowed at 50 rows
    and return a total.
  • Engine console — split into control (enable/disable) and status (last
    result, duration, window counts).

Correctness

  • Cache identity now covers the sandbox tier: a refreshed vulnerability database,
    an edited rule, a bumped vendor pin or a different LLM model all re-judge
    previously scanned packages instead of serving a stale verdict.
  • Verdict monotonicity — adding a confident finding can no longer relax a verdict.
  • A Vault failure between scoring and signing no longer strands a scan.
  • Least-privilege database grants are verified by authenticating as each module
    account, not by asking whether the account exists.

Notes

Malicious-package advisories from OSV are now classified CRITICAL and titled
distinctly from CVEs. The aig adapter no longer records "no risk found"
placeholders as findings.

Full changelog: v1.0...v1.1.0