nedlir/dasel-hardened-container
GitHub: nedlir/dasel-hardened-container
基于 melange/apko 构建的 dasel v3.3.1 加固容器镜像,修补了 YAML 别名展开漏洞并提供极简、可复现、纵深防御的运行时环境。
Stars: 0 | Forks: 0
# dasel v3.3.1 加固容器
这是一个针对 [dasel v3.3.1](https://github.com/TomWright/dasel/releases/tag/v3.3.1) 的 melange 软件包和 apko 容器镜像,包含针对 [CVE-2026-33320](https://github.com/TomWright/dasel/security/advisories/GHSA-4fcp-jxh7-23x8)(无限制 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 镜像构建器 |
- 架构:仅限 **x86_64**
- 初始构建需要互联网访问(获取源码压缩包、Go 模块、Wolfi 软件包)
### Windows 要求
所有构建和加载命令均可在任何终端(PowerShell、CMD 或 bash)下运行。仍有一个步骤需要 Unix shell:
- `bash tests/test.sh` — 测试脚本使用了 bash 和 coreutils(`timeout`、`grep`、`sed`)
在运行镜像测试之前,请安装 **Git Bash**(随 [Git for Windows](https://git-scm.com/download/win) 附带提供)。
## 项目结构
```
.
├── melange/
│ ├── dasel.yaml
│ └── CVE-2026-33320.patch
├── apko/
│ └── dasel.yaml
├── tests/
│ └── test.sh
├── 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
```
## 构建
```
# 1. 生成签名密钥(一次性)
docker compose run --rm melange keygen keys/melange.rsa
# 2. 构建 APK 包(拉取源代码,应用 CVE 补丁,编译)
docker compose run --rm melange build melange/dasel.yaml --arch x86_64 --signing-key keys/melange.rsa
# 3. 构建 OCI 镜像(使用本地 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
# 示例:查询 JSON 文件
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'
```
这些标志强制执行了 [镜像加固](#image-hardening) 中描述的纵深防御策略的运行时层:不可变的根文件系统、零 Linux capabilities,以及无特权升级路径。
## 测试
```
docker compose run --rm melange test melange/dasel.yaml --arch x86_64
```
**镜像测试:**
```
# 加载镜像(适用于 PowerShell、CMD 或 bash)
docker load --input dasel.tar
# 运行测试脚本(在 Windows 上需要 Git Bash)
bash tests/test.sh
```
测试脚本验证了:
- 镜像加载成功且 `dasel version` 报告为 `v3.3.1`
- JSON 键提取(`-i json 'test'`)
- JSON 到 YAML 的转换(`-i json -o yaml --root`)
- CVE 补丁:恶意的十亿笑声 YAML 会触发 `"yaml expansion budget exceeded"` 而非挂起
## CVE-2026-33320 修复
该漏洞允许通过指数级嵌套的 YAML 别名(十亿笑声攻击)造成无限制的 CPU/内存消耗。位于 `melange/CVE-2026-33320.patch` 的补丁为 dasel 的 YAML 读取器增加了两道防线:一个是限制递归别名嵌套的展开深度限制(32),另一个是限制每个文档总别名解引用次数的展开预算(1000)。当触及任一限制时,解码将立即返回错误。
## 安全性、可复现性与极简性
- **安全性**:CVE-2026-33320 在构建时已被修补。所有软件包均已签名。镜像仅包含 3 个 APK 软件包(wolfi-baselayout、ca-certificates-bundle、dasel)
- **可复现性**:软件包和镜像均采用声明式 YAML。源码压缩包通过 SHA256 固定。所有工具版本均已记录在案。Go 二进制文件使用 `-trimpath` 构建,以剥离本地构建路径
- **极简性**:最终镜像中没有 shell,也没有软件包管理器 - 仅有 dasel 二进制文件、CA 证书和 baselayout
### 镜像加固
该镜像在最小化打包的基础上应用了纵深防御:
| 层级 | 措施 | 效果 |
| ------- | ---------------------------------- | --------------------------------------------------- |
| 构建 | 非 root 用户 (UID 65532) | 容器进程永远不会以 root 身份运行 |
| 构建 | `-s -w` ldflags + 自动 `-trimpath` | 经过剥离的二进制文件,无本地路径泄露 |
| 构建 | 仅 3 个软件包 | 最小攻击面,没有 shell 或软件包管理器 |
| 运行时 | `--read-only` | 不可变的根文件系统 |
| 运行时 | `--cap-drop=ALL` | 零 Linux capabilities |
| 运行时 | `--no-new-privileges` | 防止通过 setuid/setgid 进行特权升级 |
## 漏洞扫描
构建好的镜像(`dasel.tar`)使用行业标准工具进行了扫描,以验证超出 CVE 补丁本身的安全态势。
### Syft (SBOM 生成)
Syft 通过检查 Go 二进制文件的模块元数据,从镜像中提取了 **36 个软件包**:
- **3 个 APK 软件包**:`wolfi-baselayout` 20230201-r29、`ca-certificates-bundle` 20260413-r0、`dasel` 3.3.1-r0
- **32 个 Go 模块**:包括 `go.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 个
- **清点的 19 个文件**:`/usr/bin/dasel`、`/etc/ssl/certs/ca-certificates.crt`、APK DB、每个软件包的 SBOM,以及 baselayout 配置文件
### Grype (漏洞扫描器)
我生成的 SBOM 使用 Grype 进行了检查,在所有 32 个 Go 模块或 3 个 APK 软件包中未发现其他漏洞。
## 提交
### 假设
- **仅限 x86_64** - 单架构构建。多架构构建将需要额外的 `--arch` 标志
- **一次性签名密钥** - 在本地生成并已被 gitignore。在生产环境中,私钥签名密钥应存储在 secrets manager 中,而不是本地文件系统上。因为即使是被 gitignore 的文件,也可能通过备份工具、容器卷挂载或受损的工作站暴露。
- **Wolfi OS 依赖** - 构建和最终镜像依赖于 Wolfi 软件包(`busybox`、`go`、`ca-certificates-bundle`)。如果在这些上游软件包中的任何一个发现漏洞,也将影响此镜像。在生产中,保持 Wolfi 软件包最新或订阅其安全建议是必要的
- **Docker Compose 包装器** - melange 和 apko 通过 `compose.yaml` 作为 Docker 容器运行。此项在 Kali 2025.3 上开发,并在带有 Docker Desktop 29.3.1 的 Windows 10 上进行了验证
- **测试脚本需要 bash** - `tests/test.sh` 使用 `timeout`(coreutils)和 Docker CLI。所有其他命令都是纯粹的 `docker` 命令,可在 PowerShell 或 CMD 中运行。在 Windows 上,请从 Git Bash 运行测试脚本(参见 [Windows 要求](#windows-requirements))
### SBOM 覆盖范围缺口
apko 在构建时会自动将 SPDX SBOM 生成到 `sbom/` 目录中(`sbom/sbom-x86_64.spdx.json`、`sbom/sbom-index.spdx.json`)。它们跟踪 3 个已安装的 APK 软件包的版本、CPE、来源证明和 Melange 构建定义引用。然而,它们**不**包括编译到 `dasel` 二进制文件中的 Go 模块依赖。我决定对它们进行扫描,并使用 Syft 通过从二进制文件的嵌入元数据中提取所有 32 个 Go 模块来弥补这一缺口。
对于生产环境,应该有一些自动化 SBOM 提取的工具来定期轮询。然后也许可以使用我用 Golang 编写的类似 [https://github.com/nedlir/CVEnotifier](https://github.com/nedlir/CVEnotifier) 的工具附加 SBOM 结果,以发现供应链中的新漏洞。
### 运行的命令及结果
| 命令 | 结果 |
| ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `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 hunks),生成了 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 压缩包 |
| `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) |
### 未来改进
- **多架构构建** - 支持多种架构来构建此容器。
- **CI/CD 流水线** - 在 GitHub Actions 中通过 melange/apko 容器操作自动化构建和测试
- **melange 中的 Go 级别 SBOM** - 在 melange 构建流水线期间运行 `syft`,并将 Go 模块 SBOM 与 APK 一起嵌入
标签:Apko, APK打包, Chainguard, CVE-2026-33320, Dasel, DevSecOps, Docker, GitHub Advanced Security, Go语言, Melange, OCI镜像, Wolfi Linux, x86_64架构, YAML反序列化安全, 上游代理, 安全加固, 安全补丁, 安全防御评估, 容器化构建, 容器镜像安全, 数据选择器, 日志审计, 漏洞修复, 程序破解, 网络安全培训, 请求拦截