这是一个针对 dasel v3.3.1 的 melange 包和 apko 容器镜像,包含针对 CVE-2026-33320(无限制的 YAML 别名扩展)的构建时补丁。该镜像完全由本地生成的 APK 构建——不使用任何预构建的上游镜像。
| 工具 | 已测试版本 | 用途 |
|---|---|---|
| Docker | 29.3.1 | 容器运行时,通过 compose.yaml 运行 melange/apko |
| melange | 0.50.5 (Docker image cgr.dev/chainguard/melange@sha256:b6f11bb45a6090c182986028fd2249fb1a18dcb6e173c4ce001dd3fb4cb1dd71) | APK 包构建器 |
| apko | 1.2.10 (Docker image cgr.dev/chainguard/apko@sha256:20dfc1f5e3461b5eaf3279f762cd4bf86c7f3635d2a9642f905cf583525f9ee6) | OCI 镜像构建器 |
所有构建和加载命令都可以在任何终端(PowerShell、CMD 或 bash)中运行。但有一个步骤仍需要 Unix shell:
bash tests/test.sh — 该测试脚本使用 bash 和 coreutils(timeout、grep、sed)在运行镜像测试之前,请安装 Git Bash(随 Git for Windows 一起提供)。
.
├── .github/
├── melange/
│ ├── dasel.yaml
│ └── CVE-2026-33320.patch
├── apko/
│ └── dasel.yaml
├── tests/
│ └── test.sh
├── Makefile
├── compose.yaml
├── keys/ # Generated, gitignored
│ ├── melange.rsa
│ └── melange.rsa.pub
├── sbom/ # Generated, gitignored
│ ├── sbom-x86_64.spdx.json
│ └── sbom-index.spdx.json
├── packages/ # Generated, gitignored
│ └── x86_64/
│ ├── dasel-3.3.1-r0.apk
│ └── APKINDEX.tar.gz
└── README.md
make build # keygen (if needed) + package + image
make test # package tests + image tests
make all # build + test
make clean # remove all generated artifacts
make help # list all targets and variables
# 1. Generate signing keys (one-time)
docker compose run --rm melange keygen keys/melange.rsa
# 2. Build the APK package (fetches source, applies CVE patch, compiles)
docker compose run --rm melange build melange/dasel.yaml --arch x86_64 --signing-key keys/melange.rsa
# 3. Build the OCI image (consumes the local APK)
docker compose run --rm apko build apko/dasel.yaml dasel:3.3.1 dasel.tar --arch x86_64 --sbom-path sbom/
第 2 步会自动生成并签名 packages/x86_64/APKINDEX.tar.gz。
加载镜像后,运行 dasel:
docker load --input dasel.tar
# Example: query a JSON file
echo '{"name": "dasel"}' | docker run --rm \
--read-only \
--cap-drop=ALL \
--security-opt=no-new-privileges \
-i dasel:3.3.1-amd64 \
-i json 'name'
这些标志强制执行 镜像加固 中描述的纵深防御策略的运行时层:不可变的根文件系统、零 Linux capabilities 以及无权限提升路径。
make test # all tests (package + image)
make package-test # melange package tests only
make image-test # image tests only (requires bash)
# Package tests
docker compose run --rm melange test melange/dasel.yaml --arch x86_64
# Image tests (requires Git Bash on Windows)
docker load --input dasel.tar
bash tests/test.sh
测试脚本验证以下内容:
dasel version 报告 v3.3.1-i json 'test')-i json -o yaml --root)"yaml expansion budget exceeded",而不是挂起该漏洞允许通过指数级嵌套的 YAML 别名(billion laughs 攻击)造成无限制的 CPU/内存消耗。melange/CVE-2026-33320.patch 中的补丁为 dasel 的 YAML 读取器添加了两项保护措施:扩展深度限制(32),用于限制递归别名嵌套;以及扩展预算(1000),用于限制每个文档的别名解引用总数。当任一限制被触发时,解码会立即返回错误。
-trimpath 构建,以剥离本地构建路径该镜像在最小化打包之外还应用了纵深防御:
使用行业标准工具对构建的镜像(dasel.tar)进行了扫描,以验证除 CVE 补丁本身之外的安全态势。
Syft 通过检查 Go 二进制的模块元数据,从镜像中提取了 36 个软件包:
wolfi-baselayout 20230201-r29、ca-certificates-bundle 20260413-r0、dasel 3.3.1-r0go.yaml.in/yaml/v4、github.com/hashicorp/hcl/v2、github.com/pelletier/go-toml/v2、github.com/goccy/go-json、github.com/charmbracelet/bubbletea、golang.org/x/sys、golang.org/x/text、stdlib go1.25.9,以及另外 25 个/usr/bin/dasel、/etc/ssl/certs/ca-certificates.crt、APK 数据库、各软件包的 SBOM 以及 baselayout 配置文件我生成的 SBOM 已使用 Grype 进行了检查,在全部 32 个 Go 模块或 3 个 APK 软件包中没有发现其他漏洞。
--arch 参数busybox、go、ca-certificates-bundle)。如果这些上游软件包中的任何一个被发现漏洞,也会影响此镜像。在生产环境中,需要保持 Wolfi 软件包更新或订阅其安全公告。compose.yaml 作为 Docker 容器运行。这是在 Kali 2025.3 上开发的,并在装有 Docker Desktop 29.3.1 的 Windows 10 上验证通过。tests/test.sh 使用 timeout(coreutils)和 Docker CLI。所有其他命令都是纯 docker 命令,可以在 PowerShell 或 CMD 中运行。在 Windows 上,请从 Git Bash 运行测试脚本(参见 Windows 要求)。apko 会在构建时自动生成 SPDX SBOM 到 sbom/ 文件夹(sbom/sbom-x86_64.spdx.json、sbom/sbom-index.spdx.json)。这些 SBOM 记录 3 个已安装的 APK 软件包,包括版本、CPE、来源出处和 Melange 构建定义引用。但是,它们不包含编译进 dasel 二进制的 Go 模块依赖。我决定对它们进行扫描,并使用 Syft 通过提取二进制内嵌元数据中的全部 32 个 Go 模块来填补这一缺口。
对于生产环境,应该有某种 SBOM 提取的自动化,定期轮询。然后可以用类似我用 Golang 编写的 https://github.com/nedlir/CVEnotifier 的工具附加 SBOM 结果,以发现供应链中的新型漏洞。
多架构构建 - 支持构建此容器的多种架构。
CI/CD 流水线 - 在 GitHub Actions 中使用 melange/apko 容器操作自动化构建和测试
在 melange 中生成 Go 级 SBOM - 在 melange 构建流水线期间运行 syft,并将 Go 模块 SBOM 与 APK 一起嵌入
| 层 | 措施 | 效果 |
|---|
| 构建 | 非 root 用户(UID 65532) | 容器进程永远不会以 root 身份运行 |
| 构建 | -s -w ldflags + 自动 -trimpath | 剥离的二进制文件,无本地路径泄漏 |
| 构建 | 仅 3 个软件包 | 最小的攻击面,无 shell 或包管理器 |
| 运行时 | --read-only | 不可变的根文件系统 |
| 运行时 | --cap-drop=ALL | 零 Linux capabilities |
| 运行时 | --no-new-privileges | 阻止通过 setuid/setgid 进行权限提升 |
| 命令 | 结果 |
|---|
docker compose run --rm melange keygen keys/melange.rsa | 通过 |
docker compose run --rm melange build melange/dasel.yaml --arch x86_64 --signing-key keys/melange.rsa | 通过 - 补丁已应用(7/7 个 hunk),已生成 APK |
docker compose run --rm melange test melange/dasel.yaml --arch x86_64 | 通过 - 版本检查、JSON 键提取、JSON 数组访问 |
docker compose run --rm apko build apko/dasel.yaml dasel:3.3.1 dasel.tar --arch x86_64 --sbom-path sbom/ | 通过 - 已安装 3 个软件包,已生成 OCI tarball |
docker load --input dasel.tar | 通过 - 已加载 dasel:3.3.1-amd64 |
bash tests/test.sh | 通过 - 所有测试(版本、键提取、格式转换、YAML 别名、CVE 补丁) |
docker run --rm -v ... anchore/grype:latest /work/dasel.tar | 通过 - 1 个发现(已修补 CVE 的预期误报) |
docker run --rm -v ... anchore/syft:latest /work/dasel.tar | 通过 - 已编录 36 个软件包(3 个 APK + 32 个 Go + 1 个 stdlib) |