
dasel v3.3.1 verpackt mit Melange und als minimales apko-Image ausgeliefert, gepatcht für CVE-2026-33320
Dieses Repository paketiert das dasel CLI (v3.3.1) als APK mit Melange, erstellt ein minimales Container-Image mit apko und wendet eine Lösung für CVE-2026-33320 an, während es auf dem v3.3.1-Codebestand bleibt (ein Patch, kein Versionssprung).
Das Ergebnis ist ein ~4 MB großes Image, das nur das statische dasel-Binary enthält – keine Shell, kein Paketmanager, keine libc – und das als Nicht-Root-Benutzer läuft.
melange/
dasel.yaml # Melange-Rezept: v3.3.1 holen, Patch anwenden, .apk bauen
apko/
dasel.yaml # apko-Rezept: Minimalimage aus der lokalen .apk zusammenstellen
patches/
cve-2026-33320.patch # Der CVE-Fix (minimaler Backport von Upstream 282943b auf v3.3.1)
NOTES.md # Was der CVE ist, Schweregrad und wie der Fix funktioniert
tests/
test.sh # Führt das erstellte IMAGE aus und testet Verhalten + CVE-Fix
README.md
melange und apko im PATH.Während der Entwicklung verwendete Versionen:
| Tool | Version |
|---|---|
| melange | 0.50.8 |
| apko | 1.2.14 |
| Docker | 29.5.2 |
Alle folgenden Befehle werden vom Repository-Stammverzeichnis aus ausgeführt.
melange keygen
Erzeugt melange.rsa (privat) und melange.rsa.pub (öffentlich). Beide sind gitignored – Schlüssel werden von jedem, der den Build reproduziert, neu generiert und niemals committed.
melange build melange/dasel.yaml \
--source-dir patches \
--signing-key melange.rsa \
--arch x86_64 \
--runner docker
--source-dir patches macht patches/cve-2026-33320.patch innerhalb der Build-Sandbox verfügbar, wo der patch-Schritt des Rezepts ihn anwendet. Ausgabe: packages/x86_64/dasel-3.3.1-r0.apk (signiert) und packages/x86_64/APKINDEX.tar.gz.
melange test installiert die frisch gebaute .apk in einer sauberen Umgebung und führt den test:-Block des Rezepts aus. Es benötigt das Wolfi-Repo (für busybox) und unser lokales packages/-Repo (für dasel), jeweils mit seinem Signierschlüssel:
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
Prüft: dasel version meldet 3.3.1; eine echte JSON-Abfrage; eine JSON→YAML-Konvertierung; und dass eine Billion-Laughs-YAML-Bombe abgelehnt wird durch die Expansionssperre (CVE-2026-33320 behoben).
apko build apko/dasel.yaml dasel:test dasel.tar --arch x86_64
docker load < dasel.tar
Ausgabe: dasel.tar (ein ladbares OCI-Image) plus eine SBOM (SPDX JSON). apko hängt die Architektur an den Tag an, sodass das geladene Image dasel:test-amd64 heißt.
Wie das Image das lokal gebaute Paket verwendet (die zentrale Einschränkung). apko/dasel.yaml listet ./packages als Repository und ./melange.rsa.pub als Schlüsselbund. Daher installiert apko genau das dasel-APK, das melange build in packages/x86_64/ geschrieben hat – verifiziert mit unserem eigenen Signierschlüssel – und nicht ein vorgebautes Upstream-Paket. (Führen Sie apko build vom Repository-Stamm aus, damit diese relativen Pfade aufgelöst werden.) Das ist der Zusammenhang zwischen Paket-Build und Image-Build.
./tests/test.sh
Führt das Image über docker run aus und prüft (5 Tests): dasel ist vorhanden und meldet v3.3.1, eine verschachtelte JSON-Abfrage, eine JSON→YAML-Konvertierung, eine Array-Index-Abfrage und die YAML-Bombe wird abgelehnt. Das Skript beendet sich mit einem Fehler, wenn ein Test fehlschlägt (kann so CI steuern). Überschreiben Sie den Tag mit IMAGE=<tag> ./tests/test.sh.
CVE-2026-33320 ist ein Denial-of-Service (CWE-674, unkontrollierte Rekursion) im YAML-Reader von dasel: ein "Billion Laughs"-Angriff durch unbegrenzte YAML-Alias-Expansion. dasel implementierte ein eigenes UnmarshalYAML und löste Alias-Knoten ohne Begrenzung rekursiv auf, wodurch der integrierte Schutz der zugrunde liegenden Bibliothek umgangen wurde.
Wir portieren nur den Upstream-Fix (Commit 282943b, ausgeliefert in v3.3.2) auf den v3.3.1-Quellcode als patches/cve-2026-33320.patch. Er begrenzt die Expansion mit einer Tiefenbeschränkung (32) und einem gemeinsamen Budget (1000) und gibt einen Fehler zurück, anstatt unbegrenzt zu expandieren. Wir schließen bewusst die nicht zusammenhängenden Bugfixes aus, die ebenfalls in v3.3.2 ausgeliefert wurden, und halten die Änderung minimal und prüfbar. Siehe patches/NOTES.md für vollständige Details.
git-checkout fixiert expected-commit auf den Commit-Hash von v3.3.1, sodass der Build fehlschlägt, falls der Tag jemals auf anderen Code umgeleitet wird (Supply-Chain-Sicherheit).CGO_ENABLED=0 gebaut (gesetzt in der Build-Umgebung des Rezepts), sodass das Binary kein cgo und keine Shared-Library-Abhängigkeiten hat – was dem Image ermöglicht, ohne libc/Shell/Paketmanager ausgeliefert zu werden.packages:-Liste enthält nur dasel; das Image installiert nur unser lokal gebautes Paket (verifiziert mit unserer melange.rsa.pub).nonroot) für Defense-in-Depth.x86_64 (die Architektur der Entwicklungsmaschine).docker als Melange-Runner (bubblewrap würde auf nativem Linux auch funktionieren)./etc/os-release); nichts im Image benötigt es. Dies ist eine bewusste Minimalitätsentscheidung, die durch Hinzufügen von wolfi-baselayout leicht rückgängig gemacht werden kann.go und busybox statt fixierter Snapshots, geht also davon aus, dass Wolfi weiterhin Go ≥ 1.25 bereitstellt (die go.mod-Anforderung von dasel). Die dasel-Quelle ist per Commit fixiert; das Fixieren der Build-Toolchain würde den Build vollständig hermetsch machen (siehe unten).go/busybox-Snapshots) und ein festes Build-Datum für einen vollständig hermetschen, bit-für-bit reproduzierbaren Build (die Quelle ist bereits per Commit fixiert).aarch64) für ARM-Maschinen.melange build + melange test: Paket baut, Patch wird sauber angewendet (alle 7 Hunks – 1 in parsing/yaml/yaml.go, 6 in parsing/yaml/yaml_reader.go), alle Paket-Tests grün, einschließlich des CVE-Bomb-Tests.apko build + tests/test.sh: Image baut (~4 MB Inhalt), alle 5 Image-Tests grün.