Files
qinglong/docs/operations/ql3-image-os-vulnerability-gate.md
T

104 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# QingLong 3.0 镜像 OS 漏洞门
本流程覆盖 `control|control-ai|admin|local|worker × amd64|arm64` 十个 release candidate 的 OS/base image package,不替代 npm
production dependency audit、CycloneDX、BuildKit SBOM/provenance、Cosign 或 GitHub attestation。
## 日常检查
```sh
pnpm audit:image-os-vulnerability-policy:ql3
pnpm audit:image-release:ql3
pnpm audit:cluster-deployment:ql3
```
默认 exception policy 位于 `deploy/containers/ql3-os-vulnerability-exceptions.json`,当前必须返回:
```json
{"schemaVersion":1,"fixture":"qinglong/image-os-vulnerability-exceptions@v1","compatible":true,"exceptionCount":0,"imageExceptionCounts":{"admin":0,"control":0,"local":0}}
```
真实 scan 在 QL3 CI 已有十个 native build 后执行;受保护 release 的十个 native job 各自只构建一次 OCI layout tar
Trivy 直接扫描该 tar。扫描成功后才解包、审计并上传同一 OCI graphpublisher 只合并 amd64/arm64 graph,不再 build。
只有六份 artifact 和 D-236 私密 evidence job 全部成功,publisher 才会启动。scanner/DB 网络故障与漏洞命中使用相同
的失败关闭结果,但日志会区分下载错误和 finding。
## Build-once 发布链
每个 `control|admin|local × amd64|arm64` native job 固定执行:
1. Buildx 用 exact Dockerfile、source revision、SBOM 与 provenance 生成
`${RUNNER_TEMP}/ql3-native/image.oci.tar`
2. Trivy 以 `input` 扫描该 tar,禁止 daemon/candidate tag
3. 扫描成功后解包到 `layout/`repository recorder 复验 platform、source、SBOM/provenance 和全部 digest,写入
`evidence.json`,随后删除 tar
4.`run_id/run_attempt/image/arch` 唯一命名上传 `layout + evidence`,保留 1 天且禁止 overwrite。
publisher 的固定顺序是:下载同一 run attempt 的两份 native artifact → 本地重验并确定性 merge → 生成最终 OS
vulnerability predicate → checksum 验证 regctl → 登录 GHCR → `IMAGE@DIGEST` import → 读取远端 digest 比对 →
Cosign/SLSA/CycloneDX/OS-vulnerability attest 与 verify → manifest/rollout verify → 最后创建 version 与完整 commit tag。
publisher 不得安装 Buildx/QEMU、运行 Dockerfile 或在 tag promotion 后追加 step。
## 创建短期例外
优先升级 digest-pinned Node base。只有当前没有可部署修复且风险被明确接受时,才能在 central JSON 的
`exceptions` 中增加一项:
```json
{
"id": "CVE-2026-12345",
"images": ["admin", "control"],
"purls": ["pkg:deb/debian/libssl3@3.0.0-1"],
"owner": "security/platform",
"ticket": "QLSEC-123",
"expiresOn": "2026-08-15",
"rationale": "Temporary exposure accepted while the fixed base image is qualified."
}
```
约束:
- entries 按 `id` 严格升序,ID 唯一;images/purls 各自唯一且升序;
- 只接受 `CVE-*``pkg:apk|deb|rpm`,不能屏蔽 npm/library finding
- `expiresOn` 必须晚于 UTC 当天且最多 30 天,到期当天自动失败;
- owner、ticket、rationale 缺一不可;ticket 必须先完成独立安全复核;
- 不得使用 `ignore-unfixed=true`、裸 `.trivyignore`、skip path、allow-all Rego 或无期限 VEX 代替本策略。
提交前执行:
```sh
node --test test/back/ql3ImageOsVulnerabilityPolicy.test.cjs
node --test test/back/ql3ClusterImageReleaseAudit.test.cjs
pnpm audit:image-os-vulnerability-policy:ql3
pnpm audit:image-release:ql3
```
策略生成器会为每个 image 创建临时 `.trivyignore.yaml`Trivy action 会把该低敏 exception view 显示在 job log。
不得在 rationale、owner 或 ticket 中写 credential、内部 URL、个人数据或 Secret。
## 升级 scanner 或基础镜像
1. 阅读 Trivy 官方 release 与 security advisory,确认目标版本不在已知暴露窗口;
2. 解析 signed/immutable action release 到完整 commit SHA,审查 composite action 的所有 nested action pin
3. 固定 scanner exact version,禁止 `latest`;保持 cache false、OS-only、unfixed 不忽略;
4. 对 Node base 的多架构 manifest digest 执行签名/来源核验;四个 production Dockerfile 的 runtime stage 必须同步更新 exact digest
5. 更新 ADR、静态审计 expectation 与 mutation tests;执行十个 native scan 后才能发布;
6. 修复后删除已不需要的 exceptions,不等待 `expiresOn`
## 失败恢复
- native job 失败或 artifact 未生成:重新运行整个 release;不要手工上传 artifact 或把旧 run artifact 改名复用;
- artifact/evidence/layout digest 不一致:视为供应链完整性失败,从 native build 重新开始,不通过重新打 tar 修复;
- regctl checksum 或下载失败:禁止回退到未固定 binary、`docker push` 或先推 candidate tag
- exact digest 已导入但证明/验证失败:不要创建 tag。保留 digest 用于调查,修复后由新 run 重建;
- tag promotion 失败:确认目标 tag 没有指向其他 digest;不得覆盖不一致 tag来“完成”发布;
- 清理 runner 时只删除该 job 的 `${RUNNER_TEMP}/ql3-native``${RUNNER_TEMP}/native` 和 merge 输出,不能删除
workspace、D-236 owner-private source 或共享 Docker/Kind 资源。
## 当前证据边界
仓库已证明 policy、workflow、base pin、build-once/scanned-digest merge 和 fail-closed mutation contract。本机尝试
真实 OCI attested build 时,Docker container driver 获取 BuildKit SBOM scanner 遇到网络超时并已中止,临时目录已
删除,因此没有本地 live CVE clean 结论。首次 GitHub-hosted 六矩阵成功记录和首个 evidence-backed GHCR exact-digest
publish 仍属于外部 Release Gate。control/admin 的 exact Dockerfile 已在本机 arm64 成功构建并确认 `10001:10001`
对应临时 image 随后已删除;这只证明 build/base pin,不替代漏洞数据库扫描。