
dasel v3.3.1 معبّأ مع Melange ويُقدَّم كصورة apko مصغّرة، مع تصحيح الثغرة CVE-2026-33320
يحزم هذا المستودع أداة سطر الأوامر dasel (الإصدار v3.3.1) كحزمة APK باستخدام Melange، ويبني صورة حاوية صغيرة باستخدام apko، ويطبّق إصلاحًا لـ CVE-2026-33320 مع البقاء على الشيفرة المصدرية للإصدار v3.3.1 (رقعة، وليس ترقية إصدار).
النتيجة صورة بحجم ~4 MB تحتوي فقط على ثنائي dasel الثابت — بلا غلاف أوامر، بلا مدير حزم، بلا libc — وتعمل كمستخدم غير جذر.
melange/
dasel.yaml # melange recipe: fetch v3.3.1, apply the patch, build the .apk
apko/
dasel.yaml # apko recipe: assemble a minimal image from the local .apk
patches/
cve-2026-33320.patch # the CVE fix (minimal backport of upstream 282943b onto v3.3.1)
NOTES.md # what the CVE is, severity, and how the fix works
tests/
test.sh # runs the built IMAGE and asserts real behavior + the CVE fix
README.md
melange و apko متاحتين في PATH.النسخ المستخدمة أثناء التطوير:
| الأداة | النسخة |
|---|---|
| melange | 0.50.8 |
| apko | 1.2.14 |
| Docker | 29.5.2 |
يتم تشغيل جميع الأوامر أدناه من جذر المستودع.
melange keygen
ينتج melange.rsa (خاص) و melange.rsa.pub (عام). كلاهما مستبعد في git (gitignored) — يُعاد توليد المفاتيح بواسطة أي شخص يعيد إنتاج البناء، ولا تُدرج أبدًا في التعديلات.
melange build melange/dasel.yaml \
--source-dir patches \
--signing-key melange.rsa \
--arch x86_64 \
--runner docker
الخيار --source-dir patches يجعل الملف patches/cve-2026-33320.patch متاحًا داخل بيئة البناء المعزولة، حيث تطبّقه خطوة patch في الوصفة. الناتج: packages/x86_64/dasel-3.3.1-r0.apk (موقع) و packages/x86_64/APKINDEX.tar.gz.
يثبّت melange test حزمة .apk المبنية حديثًا في بيئة نظيفة ويشغّل كتلة test: في الوصفة. يتطلب مستودع Wolfi (من أجل busybox) ومستودع packages/ المحلي (من أجل dasel)، كلٌّ بمفتاح التوقيع الخاص به:
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
يؤكد الاختبار أن: dasel version يعرض 3.3.1؛ ونجاح استعلام JSON فعلي؛ وتحويل JSON→YAML؛ وأن قنبلة YAML من نوع billion-laughs مرفوضة بواسطة حارس التوسّع (تم إصلاح CVE-2026-33320).
apko build apko/dasel.yaml dasel:test dasel.tar --arch x86_64
docker load < dasel.tar
الناتج: dasel.tar (صورة OCI قابلة للتحميل) بالإضافة إلى SBOM (SPDX JSON). يُلحق apko البنية بالوسم، لذا تكون الصورة المحمّلة هي dasel:test-amd64.
كيف تستهلك الصورة الحزمة المبنية محليًا (القيد الأساسي). يُدرج apko/dasel.yaml المجلد ./packages كمستودع و./melange.rsa.pub كحلقة مفاتيح. لذلك يثبّت apko حزمة dasel APK نفسها التي كتبها melange build في packages/x86_64/ — موثّقة بمفتاح التوقيع الخاص بنا — وليس حزمة مُجهّزة من المصدر الأصلي. (شغّل apko build من جذر المستودع حتى تُحلّ تلك المسارات النسبية بشكل صحيح.) هذا ما يربط بناء الحزمة ببناء الصورة.
./tests/test.sh
يشغّل الصورة عبر docker run ويؤكد (5 فحوصات): وجود dasel وعرضه لـ v3.3.1، واستعلام JSON متداخل، وتحويل JSON→YAML، واستعلام فهرس مصفوفة، ورفض قنبلة YAML. يخرج السكربت بقيمة غير صفرية عند فشل أي فحص (ليصلح كبوابة لـ CI). يمكن تجاوز الوسم عبر IMAGE=<tag> ./tests/test.sh.
CVE-2026-33320 هو ثغرة حجب خدمة (CWE-674، استدعاء ذاتي غير متحكم فيه) في قارئ YAML الخاص بـ dasel: هجوم "billion laughs" عبر توسّع أسماء مستعارة غير محدود في YAML. نفّذ dasel دالة UnmarshalYAML الخاصة به وقد حلّ عقد الأسماء المستعارة بشكل استدعاء ذاتي دون حدّ، متجاوزًا الحماية المدمجة في المكتبة الأساسية.
نعيد تطبيق إصلاح المصدر الأصلي فقط (الالتزام 282943b، الذي صدر في v3.3.2) على شيفرة v3.3.1 كملف patches/cve-2026-33320.patch. يحدّ التوسّع من خلال حدّ عمق (32) وميزانية مشتركة (1000)، ويعيد خطأً بدلاً من التوسّع بلا حدود. نستبعد عمدًا إصلاحات الأخطاء غير المرتبطة التي صدرت أيضًا في v3.3.2، للحفاظ على التغيير ضئيلًا وقابلًا للمراجعة. راجع patches/NOTES.md للتفاصيل الكاملة.
git-checkout قيمة expected-commit على SHA الالتزام الخاص بـ v3.3.1، لذا يفشل البناء إذا أُعيد توجيه الوسم إلى شيفرة مختلفة (أمان سلسلة التوريد).CGO_ENABLED=0 (مضبوط في بيئة بناء الوصفة)، لذا لا يحتوي الثنائي على cgo ولا على تبعيات مكتبات مشتركة — وهذا ما يتيح للصورة أن تصدر دون libc/غلاف أوامر/مدير حزم.packages: في apko هي dasel فقط؛ تثبّت الصورة حزمتنا المبنية محليًا فقط (موثقة باستخدام melange.rsa.pub).nonroot) لتعميق الدفاع.x86_64 فقط (بنية جهاز التطوير).docker كمشغّل لـ Melange (bubblewrap سيعمل أيضًا على Linux الأصلي)./etc/os-release)؛ ولا يحتاجها أي شيء داخل الصورة. هذا خيار تقليص متعمّد، ويمكن عكسه بسهولة بإضافة wolfi-baselayout.go و busybox بدلاً من لقطات مثبّتة، لذا يفترض أن Wolfi يستمر في توفير Go ≥ 1.25 (متطلب ملف go.mod الخاص بـ dasel). مصدر dasel مثبّت حسب الالتزام؛ وتثبيت سلسلة أدوات البناء أيضًا سيجعل البناء معزولًا تمامًا (انظر أدناه).go/busybox) وتاريخ بناء ثابت للحصول على بناء معزول تمامًا وقابل للإعادة بتطابق بتّي (المصدر مثبّت بالفعل حسب الالتزام).aarch64) لأجهزة ARM.melange build + melange test: تُبنى الحزمة، وتُطبَّق الرقعة بنظافة (كل الـ 7 مقاطع — 1 في parsing/yaml/yaml.go، و6 في parsing/yaml/yaml_reader.go)، وجميع اختبارات الحزمة ناجحة بما فيها اختبار قنبلة CVE.apko build + tests/test.sh: تُبنى الصورة (~4 MB محتوى)، وجميع اختبارات الصورة الخمسة ناجحة.