الدليل الرئيسي: Pipeline SAST DAST SCA 2026: المعماريّة، الأدوات وتكامل CI/CD
هذا الدرس يُركّز على التوليد التشغيليّ لـ SBOM CycloneDX 1.7.
لماذا توليد SBOM CycloneDX 1.7 في 2026
الـ Software Bill of Materials يفرض نفسه كجواز سفر رقميّ لمنتج برمجيّ. مواصفة CycloneDX 1.7، المنشورة من OWASP في 25 فبراير 2026، تُوسّع النسخة 1.6 بدعم Cryptographic Bill of Materials (CBOM)، الـ External Components، قيود التوزيع TLP، الـ Data Provenance & Citations، و name-value store قابل للتوسيع. هذا الثراء يجعله الصيغة المرجعيّة للاستجابة لمتطلّبات Cyber Resilience Act الأوروبيّ، التي تدخل التزاماتها بشأن شفافيّة المكوّنات تدريجياً حيّز التنفيذ حتى ديسمبر 2027.
أبعد من الامتثال، SBOM مُدار جيّداً يخدم ثلاث حالات استعمال تشغيليّة. الأولى هي الاستجابة للحوادث: حين تسقط CVE حرجة (Log4Shell، XZ-Utils backdoor)، استعلام على SBOMs يسمح في ثوان قليلة بتحديد الخدمات المُتأثّرة. الثانية هي التدقيق على الموردين: اشتراط SBOM CycloneDX في أيّ عقد مع ناشر طرف ثالث يعطي رؤية مستقلّة على الكود المُضمَّن. الثالثة هي diff بين الإصدارات: مقارنة SBOM قبل وبعد تحديث تكشف إدخال تبعيّات جديدة أو اختفاء مكتبة مُتوقَّعة. هذا الدرس يبني خطوة بخطوة سلسلة توليد مع Syft 1.44، Trivy 0.70 و cdxgen 11، ثمّ يُرفق الـ SBOM بـ OCI image عبر cosign ويُوثّق الـ CVEs غير القابلة للاستغلال بـ VEX.
المتطلّبات
- جهاز Linux أو macOS مع Docker مُثبَّت.
- مشروع تطبيقيّ بـ manifest تبعيّات (
package-lock.json،go.sum،requirements.txt، إلخ) و/أو صورة container منشورة. - حساب على registre OCI (Docker Hub، GHCR، GitLab Container Registry).
- المستوى المتوقَّع: متوسّط DevOps، مرتاح مع سطر الأوامر و JSON.
- الوقت المُقَدَّر: 75 دقيقة للسلسلة الكاملة، 30 دقيقة إضافيّة للأتمتة في CI.
الخطوة 1 — فهم المحاور الثلاثة لـ SBOM CycloneDX
SBOM لا يُختصَر في قائمة تبعيّات. المواصفة تُميّز ثلاث عائلات علاقات يتوقّع المستهلك إيجادها. الـ composants هي الجرد المُسطَّح: اسم، نسخة، hash، نوع (library، framework، OS، file)، رخصة، مصدر. الـ dépendances تُعبّر عن graphe العلاقات بين المكوّنات — من يعتمد على من، في أوّل أو nth transitive. الـ vulnérabilités و VEX تُشير إلى الـ CVEs المعروفة المُؤثّرة على المكوّنات وموقف الناشر من قابليّة استغلالها الفعليّة في سياقه.
SBOM منشور دون تبعيّات صريحة جودته متوسّطة: نعرف أنّ مكتبة موجودة دون معرفة ما إذا كانت مُستخدَمة مباشرة أم مأخوذة بـ transitivité. SBOM دون vulnérabilités مجرّد حالة في لحظة T. SBOM مع VEX هو كائن حيّ يحاور الـ scanners ويسمح بـ triage آليّ. المواصفة 1.7 تُسهّل هذه النقطة الأخيرة بتوحيد الحقول analysis.state و analysis.justification.
الخطوة 2 — تثبيت Syft، أداة SBOM المرجعيّة
Syft، المُدار من Anchore برخصة Apache 2.0، هو الأداة الأكثر تعدّداً لتوليد SBOM. يفحص filesystems، صور OCI، أرشيف tar، مجلّدات مستودع Git، ويعرف أكثر من 25 نظاماً بيئياً (npm، pip، gem، gomod، cargo، maven، packagist، إلخ). النسخة v1.44.0، المنشورة في 1 مايو 2026، تُضيف دعم معماريّة linux-riscv64 وتُحسّن parsing الـ aliases في yarn.lock.
curl -sSfL https://get.anchore.io/syft | sudo sh -s -- -b /usr/local/bin
syft version
التثبيت بالـ script يُنزّل binary مُوقَّع من GitHub Releases ويُثبّته في /usr/local/bin. تحقّق من المُخرَج: نسخة 1.44.0 أو أعلى، OS مُكتشَف بشكل صحيح. للتكامل CI Docker، الصورة الرسميّة anchore/syft:v1.44.0 تتجنّب خطوة التثبيت وتضمن reproducibilité للفحص من build إلى آخر.
الخطوة 3 — توليد SBOM CycloneDX لمشروع محلّيّ
لمشروع قيد التطوير، فحص مجلّد المصدر يُنتج SBOM يعكس بدقّة التبعيّات المُصرَّح بها. المُخرَج بصيغة cyclonedx-json قابل للقراءة من GitHub Code Scanning، GitLab، DefectDojo وأغلبيّة أدوات إدارة الثغرات.
cd /chemin/vers/projet
syft scan dir:. \
-o cyclonedx-json=sbom.cdx.json \
-o spdx-json=sbom.spdx.json \
-o table
ثلاثة مخارج تُنتَج بالتوازي: CycloneDX للأدوات OWASP-compatibles، SPDX للأدوات الأكثر توجّهاً Linux Foundation (Tern، FOSSology)، وجدول قابل للقراءة في console للتحقّق الفوريّ. الملفّ sbom.cdx.json يحوي كائناً JSON مُهيكَلاً بـ root bomFormat: "CycloneDX" و specVersion: "1.7"، يليه قائمة المكوّنات و graphe تبعيّاتها.
الخطوة 4 — فحص صورة OCI والتقاط طبقات OS
لمنتج مُنشَر في container، الـ SBOM يجب أن يعكس في آن واحد التبعيّات التطبيقيّة و paquets OS لصورة القاعدة. Syft يفحص الصورة بتجميع المستويين تلقائياً.
syft scan registry:ghcr.io/votreorg/votreapp:v1.2.3 \
-o cyclonedx-json=sbom-image.cdx.json \
--scope all-layers
الخيار --scope all-layers يُجبر Syft على اجتياز كلّ طبقات الصورة، بما فيها المحذوفة بـ RUN rm لاحق — ما هو ضروريّ لـ SBOM كامل، لأنّ ملفّاً محذوفاً يبقى موجوداً في طبقة وسيطة ويمكن أن يستردّه مهاجم لديه وصول إلى الصورة. دون هذا الخيار، Syft يفحص فقط الطبقة النهائيّة (squashed) ويفوّت paquets مُثبَّتة مؤقّتاً للبناء.
الخطوة 5 — استكمال بـ cdxgen للأنظمة البيئيّة الخاصّة
Syft يتفوّق على الأنظمة البيئيّة الشائعة لكنّه قد يكون أقلّ دقّة على stacks هامشيّة (Erlang، Lua، Dart، Haskell) أو على التحليل العميق لتبعيّات Java مع gradle. cdxgen، المُدار من CycloneDX/AppThreat، يستكمل البانوراما بدعم متخصّص لحوالي 40 نظاماً بيئياً وتكامل أصيل لـ deep scan Java.
npm install -g @cyclonedx/cdxgen
cdxgen -t java --deep -o sbom-java.cdx.json .
الخيار --deep يُفعّل التحليل عند التنفيذ لتتبّع classloaders، ما يكشف تبعيّات يفوّتها parse ساكن لـ pom.xml أو build.gradle. لمشروع polyglotte، أَطلِق syft و cdxgen منفصلين ثمّ ادمج SBOMs بـ cyclonedx-cli merge --input-files sbom-syft.cdx.json sbom-cdxgen.cdx.json --output-file sbom-merged.cdx.json. صيغة CycloneDX تدعم الدمج أصليّاً، ما يتجنّب التكرار.
الخطوة 6 — إثراء SBOM بالثغرات عبر Trivy
Trivy 0.70 يعرف كيف يفحص SBOM قائماً (trivy sbom) ليُبلّغ CVEs المكوّنات المُدرَجة. للحصول على SBOM CycloneDX مُثرَى بالثغرات مُدمَجة في نفس الملفّ، النمط الموصى به هو إعادة توليد SBOM من الصورة بـ trivy image --scanners vuln --format cyclonedx، الذي يُنتج وثيقة تحوي في آن واحد المكوّنات و vulnerabilities[].
# لإنتاج SBOM CycloneDX مُثرَى بالثغرات، أعد التوليد مباشرة
# من الصورة بـ --scanners vuln، بدلاً من إعادة فحص SBOM
trivy image \
--scanners vuln \
--format cyclonedx \
--output sbom-with-vulns.cdx.json \
ghcr.io/votreorg/votreapp:v1.2.3
# لقائمة CVEs لـ SBOM قائم فقط (مُخرَج JSON Trivy كلاسيكيّ):
trivy sbom sbom-image.cdx.json --format json --output cve-report.json
الملفّ sbom-with-vulns.cdx.json المُولَّد هكذا يحوي قسم vulnerabilities[] مع، لكلّ CVE، المُعرِّف، شدّة CVSS، URL الـ advisory، المكوّن المُتأثِّر والنسخة المُصحَّحة إن وُجدت. هذا التمثيل المُثرَى هو بالضبط ما تنتظره منصّات إدارة الثغرات كمُدخَل: DefectDojo يستوعبها عبر endpoint /api/v2/import-scan/ مع scanner type CycloneDX Scan، ويُزيل التكرار آلياً مع findings أدوات أخرى.
الخطوة 7 — توثيق CVEs غير القابلة للاستغلال بـ VEX
كلّ CVEs المُكتشَفة ليست قابلة للاستغلال في سياقك: الدالّة الضعيفة غير مُستدعاة، الهجمة تتطلّب إعداداً لا تملكه، أو mitigation runtime تحجب السطح. صيغة VEX (Vulnerability Exploitability eXchange)، المُعَيَّرة في CycloneDX 1.4 والمُوسَّعة في 1.7، تسمح بتوثيق هذه التحليلات بطريقة مُهيكَلة وقابلة للقراءة آلياً.
bomFormat: "CycloneDX"
specVersion: "1.7"
serialNumber: "urn:uuid:f1b1f1b1-1111-2222-3333-444455556666"
version: 1
metadata:
timestamp: "2026-05-06T10:00:00Z"
component:
bom-ref: "pkg:image/votreapp@sha256:abc123def456"
type: "container"
name: "votreapp"
version: "1.2.3"
vulnerabilities:
- id: "CVE-2024-12345"
source:
name: "NVD"
url: "https://nvd.nist.gov/vuln/detail/CVE-2024-12345"
affects:
- ref: "pkg:image/votreapp@sha256:abc123def456"
analysis:
state: "not_affected"
justification: "code_not_reachable"
detail: "كودنا لا يستدعي أبداً الدالّة الضعيفة openssl_sign_old(). مُتحقَّق بـ CodeQL في 2026-04-15."
response: ["will_not_fix"]
خمس قيم لـ state مسموحة: resolved، resolved_with_pedigree، exploitable، in_triage، false_positive، not_affected. تسع قيم لـ justification تُغطّي الأسباب التقنيّة (code_not_present، code_not_reachable، requires_configuration، requires_dependency، requires_environment، protected_by_compiler، protected_at_runtime، protected_at_perimeter، protected_by_mitigating_control). هذا الهيكل المُعَيَّر يتجنّب أن يخترع كلّ فريق مفرداته الخاصّة ويسمح للأدوات في المراحل اللاحقة بالترشيح آليّاً.
الخطوة 8 — إرفاق SBOM بصورة OCI عبر cosign
SBOM منشور في ملفّ منفصل على خادم ويب قد يُحرَّف أو يُفقَد. الممارسة 2026 تنشر SBOM كـ in-toto attestation مُوقَّعة مُرفَقة مباشرة بصورة OCI عبر cosign attest. الأمر cosign attach sbom لا يزال موجوداً لكنّه مُعَلَّم deprecated من مشروع Sigstore منذ 2024: يُرفق SBOM دون توقيعه، ما لا يُقدّم أيّ ضمانة أصالة. cosign attest هو الطريق الموصى به لأنّه يجمع الإرفاق والتوقيع في attestation قابلة للتحقّق.
IMAGE=ghcr.io/votreorg/votreapp:v1.2.3
DIGEST=$(crane digest $IMAGE)
# الخطوة الموصى بها: وقّع الصورة ثمّ انشر SBOM كـ attestation مُوقَّعة
cosign sign --key cosign.key ${IMAGE}@${DIGEST}
cosign attest --predicate sbom-with-vulns.cdx.json \
--type cyclonedx \
--key cosign.key \
${IMAGE}@${DIGEST}
عمليّتان متكاملتان: cosign sign يُوقّع الصورة نفسها (هويّة الناشر)، cosign attest ينشر SBOM كـ attestation مُوقَّعة تشفيرياً بصيغة in-toto، مُرفَقة بالصورة في الـ registry OCI تحت الامتداد .att. المستهلك يسترجع ويتحقّق من attestation بـ cosign verify-attestation --type cyclonedx --key cosign.pub ${IMAGE}@${DIGEST}. إذا لم يطابق التوقيع، الـ attestation مرفوضة — مهاجم حرّف SBOM لا يستطيع تمرير SBOM له على أنّه أصيل.
الأخطاء المتكرّرة
| العَرَض | السبب | الحلّ |
|---|---|---|
| SBOM فارغ أو غير كامل على مشروع Java | Syft لا يفعل deep scan Java افتراضياً | أكمل بـ cdxgen –deep، ادمج SBOMs |
| مكوّنات OS غائبة من SBOM image | scope افتراضيّ squashed دون --scope all-layers |
استعمل دائماً --scope all-layers في CI |
| Trivy لا يجد CVEs المُتوقَّعة | قاعدة بيانات vuln غير مُحدَّثة | أَجبر trivy --download-db-only قبل الفحص؛ pinner version >= 0.70.0 |
| VEX مرفوض من المستهلك | justification غير قياسيّة | استعمل صراحة قيم CycloneDX 1.7 المُعَيَّرة |
| cosign attach يفشل بـ annotation conflict | SBOM مُرفَق سلفاً بنسخة سابقة | استعمل cosign clean قبل إعادة الإرفاق، أو versionner عبر tag |
| SBOM يمرّ المُتحقّق الرسميّ لكنّه مُكسَّر في المراحل اللاحقة | فرق بين 1.6 و 1.7 | Pinner specVersion: "1.7" واشترط مستهلكين مُحدَّثين |
أسئلة شائعة
CycloneDX أم SPDX، أيّ صيغة نختار؟ الاثنان معترف بهما من NTIA للامتثال Executive Order 14028 ومن ENISA لـ CRA. CycloneDX أكثر توجّهاً طبيعياً نحو أمن التطبيقات (VEX، vulnerabilités أصيلة، CBOM). SPDX أكثر نضجاً من ناحية امتثال الرخص ومُستعمَل تاريخياً في عالم Linux Foundation. سلسلة ناضجة تُولّد الاثنين؛ CycloneDX 1.7 هو الصيغة المحوريّة للـ pipelines الحديثة.
هل Cyber Resilience Act يفرض صيغة محدّدة؟ لا، CRA يبقى agnostique على الصيغة. يفرض أن يوجد SBOM، يُحافَظ عليه طوال مدّة دعم المنتج (5 سنوات كحدّ أدنى لأغلب الفئات)، ويُقدَّم عند طلب السلطات المختصّة. CycloneDX 1.7 و SPDX 2.3 كلاهما متوافقان.
هل يجب نشر SBOM علنياً؟ القاعدة العمليّة: انشر SBOMs لصور container العامّة، قيّد الوصول إلى SBOMs منتجات تجاريّة propriétaires للعملاء المُتعاقَدين. الحقل distribution (TLP) المُدخَل في CycloneDX 1.7 يسمح بوَسم SBOM TLP:AMBER للإشارة إلى تقييد المشاركة.
كيف نُديم SBOM بين إصدارين؟ أَعِد التوليد عند كلّ build عبر CI، أَرفِق النسخة المُؤرَّخة بالصورة، احفظ التاريخ طوال مدّة الدعم. للخدمات SaaS التي تنشر عدّة مرّات يومياً، حفظ SBOM لكلّ نشر إنتاج يسمح بتحقيق post-mortem موثوق.
هل يمكن إثراء SBOM قائم بـ VEX خارجيّ؟ نعم، صيغة VEX يمكنها العيش في ملفّ منفصل يُشير إلى SBOM عبر bom-ref. هذا الفصل مفيد حين ينشر الناشر SBOM ثابتاً ويُصدر بانتظام تحليلات VEX لـ CVEs المُكتشَفة بعد النشر.
دروس مرتبطة
- أمن supply-chain برمجيّ: SBOM، signing، scanning — نظرة شاملة أوسع للتدابير المضادّة في supply-chain.
- Policy Controller Sigstore على Kubernetes — التحقّق من signatures و SBOM في cluster.
- الدليل الرئيسي: Pipeline SAST DAST SCA 2026
الكلمات المفتاحيّة: SBOM CycloneDX 1.7، Cyber Resilience Act، Syft، Trivy، cdxgen، VEX، cosign attestation، Sigstore، supply chain security.