
dasel v3.3.1 empaquetado con Melange y distribuido como una imagen apko mínima, parcheado para CVE-2026-33320
Este repositorio empaqueta la CLI dasel (v3.3.1) como un
APK con Melange, construye una imagen de contenedor mínima con apko, y aplica una corrección para
CVE-2026-33320 manteniéndose en el código base v3.3.1 (un parche, no un salto de versión).
El resultado es una imagen de ~4 MB que contiene únicamente el binario estático dasel — sin shell, sin gestor
de paquetes, sin libc — que se ejecuta como un usuario no root.
melange/
dasel.yaml # receta de melange: descargar v3.3.1, aplicar el parche, compilar el .apk
apko/
dasel.yaml # receta de apko: ensamblar una imagen mínima desde el .apk local
patches/
cve-2026-33320.patch # la corrección del CVE (backport mínimo de upstream 282943b sobre v3.3.1)
NOTES.md # qué es el CVE, gravedad y cómo funciona la corrección
tests/
test.sh # ejecuta la IMAGEN compilada y verifica comportamiento real + la corrección del CVE
README.md
melange y apko en el PATH.Versiones utilizadas durante el desarrollo:
| Herramienta | Versión |
|---|---|
| melange | 0.50.8 |
| apko | 1.2.14 |
| Docker | 29.5.2 |
Todos los comandos siguientes se ejecutan desde la raíz del repositorio.
melange keygen
Produce melange.rsa (privada) y melange.rsa.pub (pública). Ambas están en .gitignore — las claves son
regeneradas por quien reproduzca la compilación, nunca se confirman.
melange build melange/dasel.yaml \
--source-dir patches \
--signing-key melange.rsa \
--arch x86_64 \
--runner docker
--source-dir patches hace que patches/cve-2026-33320.patch esté disponible dentro del entorno sandbox de compilación,
donde el paso patch de la receta lo aplica. Salida: packages/x86_64/dasel-3.3.1-r0.apk
(firmado) y packages/x86_64/APKINDEX.tar.gz.
melange test instala el .apk recién compilado en un entorno limpio y ejecuta el bloque test: de la receta.
Necesita el repositorio Wolfi (para busybox) y nuestro repositorio local packages/ (para
dasel), cada uno con su clave de firma:
melange test melange/dasel.yaml dasel \
--arch x86_64 --runner docker \
--repository-append https://packages.wolfi.dev/os \
--keyring-append https://packages.wolfi.dev/os/wolfi-signing.rsa.pub \
--repository-append "$(pwd)/packages" \
--keyring-append melange.rsa.pub
Verifica: dasel version reporta 3.3.1; una consulta JSON real; una conversión JSON→YAML; y que una
bomba YAML de mil millones de risas es rechazada por el guardián de expansión (CVE-2026-33320 corregido).
apko build apko/dasel.yaml dasel:test dasel.tar --arch x86_64
docker load < dasel.tar
Salida: dasel.tar (imagen OCI cargable) más un SBOM (JSON SPDX). apko añade la
arquitectura a la etiqueta, por lo que la imagen cargada es dasel:test-amd64.
Cómo consume la imagen el paquete compilado localmente (la restricción clave). apko/dasel.yaml
lista ./packages como repositorio y ./melange.rsa.pub como llavero. Así que apko instala el
APK dasel exacto que melange build escribió en packages/x86_64/ — verificado con nuestra propia
clave de firma — y no un paquete precompilado de upstream. (Ejecute apko build desde la raíz del repositorio para
que esas rutas relativas se resuelvan). Esto es lo que conecta la compilación del paquete con la compilación de la imagen.
./tests/test.sh
Ejecuta la imagen mediante docker run y verifica (5 comprobaciones): dasel está presente y reporta v3.3.1, una
consulta JSON anidada, una conversión JSON→YAML, una consulta por índice de arreglo, y la bomba YAML rechazada. El
script sale con código distinto de cero si falla alguna comprobación (por lo que puede servir como puerta en CI). Sobrescriba la etiqueta con
IMAGE=<tag> ./tests/test.sh.
CVE-2026-33320 es una denegación de servicio (CWE-674, recursión no controlada) en el lector YAML de dasel:
un ataque de "mil millones de risas" mediante expansión de alias YAML sin límite. dasel implementó su propio
UnmarshalYAML y resolvía nodos de alias recursivamente sin límite, eludiendo la protección incorporada de la
biblioteca subyacente.
Hacemos backport solo de la corrección de upstream (commit 282943b, incluido en v3.3.2) sobre el código fuente
v3.3.1 como patches/cve-2026-33320.patch. Limita la expansión con un límite de profundidad (32) y un
presupuesto compartido (1000), devolviendo un error en lugar de expandir sin límite. Excluimos deliberadamente
las correcciones de errores no relacionadas que también se incluyeron en v3.3.2, manteniendo el cambio mínimo y
auditable. Consulte patches/NOTES.md para más detalles.
git-checkout fija expected-commit al SHA del commit v3.3.1, por lo que la
compilación falla si la etiqueta se reasigna a código diferente (seguridad de cadena de suministro).CGO_ENABLED=0 (definido en el entorno de compilación de la receta), por lo que el
binario no tiene cgo ni dependencias de bibliotecas compartidas — que es lo que permite que la imagen funcione sin
libc/shell/gestor de paquetes.packages: de apko es solo dasel; la imagen instala únicamente nuestro
paquete compilado localmente (verificado con nuestra melange.rsa.pub).nonroot) para defensa en profundidad.x86_64 (la arquitectura de la máquina de desarrollo).docker como ejecutor de Melange (bubblewrap también funcionaría en Linux nativo)./etc/os-release); nada en la imagen
lo necesita. Es una elección deliberada de minimalismo, fácilmente reversible añadiendo
wolfi-baselayout.go y busybox de Wolfi en lugar de instantáneas fijadas, por lo que asume
que Wolfi sigue sirviendo Go ≥ 1.25 (requisito de go.mod de dasel). La fuente de dasel está fijada por
commit; fijar también la cadena de herramientas de compilación haría la compilación completamente hermética (ver abajo).go/busybox de Wolfi) y una fecha de compilación fija para una
compilación completamente hermética y bit a bit reproducible (la fuente ya está fijada por commit).aarch64) para máquinas ARM.