أمن سلسلة توريد البرمجيات: ما هي SBOM وهل يمكنك الوثوق بتبعيات مشروعك؟
تطبيقك في معظمه كود كتبه آخرون. إليك كيف تخبرك SBOM وإثباتات المنشأ الموقّعة وضوابط الإدخال، في دقائق معدودة، ما إذا كانت هجمة سلسلة التوريد القادمة تطالك أم لا.
بقلم Innovation T Team
التطبيق الإنتاجي المتوسط يحتوي على كود كتبه غرباء أكثر بكثير مما كتبه فريقك. من واقع خبرتنا مع شركات في تونس والمنطقة، خدمة Node.js فيها 30 تبعية مباشرة تجرّ وراءها عادة أكثر من ألف حزمة متعدية (transitive)، ولم يقرأ أحد تقريبًا أيًّا منها. وعندما تقع لحظة XZ Utils أو event-stream القادمة، فإن الرابحين هم الفرق القادرة على الإجابة عن سؤال واحد في دقائق: هل نشغّل فعلًا الإصدار المتأثر؟
جبل الجليد في شجرة التبعيات
أنت تدقّق الكود الذي تكتبه. تراجع طلبات الدمج بعناية. ثم يأتي npm install فينفّذ سكربتات postinstall عشوائية من حزمة تقبع في المستوى السادس من شجرتك، كتبها شخص يحمي حسابه بكلمة مرور من عام 2014. هذا هو اختلال التوازن في قلب أمن سلسلة التوريد: ضوابطك تغطي العشرة بالمئة من الكود الذي كتبته بنفسك، والمهاجمون يعرفون ذلك جيدًا.
ثلاث خصائص تجعل التبعيات سطح هجوم شديد الخطورة بشكل استثنائي:
- اللامرئية المتعدية. أنت اخترت
express. لكنك لم تختر عشرات الحزم التي جلبها معه، ولا اختارها أي أحد آخر في فريقك. لم يتخذ أحد قرار ثقة بشأن معظم شجرتك. - التنفيذ عند التثبيت. كثير من المنظومات تشغّل سكربتات دورة الحياة أثناء التثبيت. اخترق حزمة واحدة شائعة وستحصل على تنفيذ كود على كل حاسوب مطوّر وكل خادم CI يسحبها، قبل أن يبدأ التطبيق أصلًا.
- وراثة الثقة. حاسوب مصانٍ (maintainer) مخترق، أو نطاق بريد إلكتروني منتهي الصلاحية، أو مشروع جانبي سُلّم لغيره، كل ذلك يصبح حادثة أمنية عندك أنت. هجمة event-stream نجحت بهذه الطريقة بالضبط: غريب لطيف طلب صلاحيات النشر على حزمة مهجورة، فحصل عليها.
لا يمكنك الخروج من هذا المأزق بالمراجعة اليدوية. الشجرة أكبر من أن تُقرأ وهي تتغير أسبوعيًا. ما يمكنك فعله هو بناء ثلاث طبقات: الجرد (اعرف ما الذي تشحنه)، والتحقق (أثبت من أين جاء)، وضوابط الإدخال (أبطئ ونظّف ما يدخل). إن SBOM هي طبقة الجرد، وكل ما عداها يُبنى فوقها.
ما الذي تعنيه SBOM فعليًا
قائمة مكونات البرمجيات (Software Bill of Materials) هي جرد قابل للقراءة الآلية لكل مكوّن في قطعة أثرية (artifact) محددة: اسم الحزمة، والإصدار الدقيق، والمورّد، والبصمات التشفيرية، والترخيص، وعلاقات الاعتماد بين المكونات. ليست جدول Excel. وليست ملف package.json الذي يسجّل النوايا لا النتائج المحسومة. إنها وثيقة مهيكلة مرتبطة ببناء واحد ملموس.
صيغتان تهيمنان على المشهد، والاختيار بينهما أقل درامية مما توحي به النقاشات على الإنترنت:
- SPDX (المعيار ISO/IEC 5962). الأقدم والأرسخ. أقوى إرث في الامتثال للتراخيص، وأدوات واسعة الانتشار، ومفضّل عبر منظومات Linux Foundation.
- CycloneDX (من OWASP، وأصبح الآن معيار ECMA-424). صُمم لمسارات العمل الأمنية. دعم من الدرجة الأولى لمراجع الثغرات و VEX والخدمات ومكونات العتاد ونماذج ML. إذا كانت حالتك الأساسية هي الاستجابة للثغرات، فابدأ من هنا.
كلاهما يُسلسل إلى JSON. وكلاهما يتحول إلى الآخر بدقة مقبولة. اختر واحدة، وولّدها باتساق، وارفض أن تؤخر نقاشات الصيغ إطلاق المشروع.
التنظيمات تقوم بجزء كبير من الدفع. المشتريات الفيدرالية الأمريكية تشترط SBOM من المورّدين منذ الأمر التنفيذي 14028، وقانون المرونة السيبرانية الأوروبي (EU Cyber Resilience Act) يمدّ التزامات مشابهة إلى كل من يبيع تقريبًا منتجات ذات عناصر رقمية داخل الاتحاد الأوروبي. وهذا يعنينا مباشرة في منطقتنا: شركات البرمجيات التونسية والمغاربية التي تصدّر خدماتها إلى أوروبا ستجد هذه البنود تصلها عبر عقود عملائها، والمشتريات الحكومية والمصرفية في الخليج بدأت بدورها تطالب بجرد المكونات ضمن أطرها السيبرانية. إذا كنت تبيع برمجيات، فبنود SBOM قادمة إلى عقودك سواء استعددت أم لا. والاستعداد أرخص.
ولّدها عند البناء، لا عند الطلب
أكثر أنماط فشل SBOM شيوعًا: توليد واحدة كل ثلاثة أشهر من مسح للمصدر ثم إعلان أن الخانة قد أُشّرت. إن SBOM المنفصلة عن قطعة بناء محددة ليست سوى تخمين بامتداد ملف. القواعد التي تهم:
- SBOM واحدة لكل قطعة أثرية، لكل بناء. فقائمة
api:1.4.2تصف تلك الصورة بالضبط، بملف القفل المحسوم وكل شيء. - امسح القطعة الأثرية، لا المصدر فقط. صورة الحاوية تحتوي على حزم نظام التشغيل (apk و deb و rpm)، وتبعيات اللغة، وملفات ثنائية شاردة نسخها أحدهم إلى الداخل. مسح المصدر لا يرى الفئة الأولى إطلاقًا ويفوّت الثالثة تمامًا.
- خزّن قوائم SBOM مع الإصدار وأبقها قابلة للاستعلام. قيمتها تتضاعف عندما تستطيع البحث عبر كل الإصدارات المنشورة دفعة واحدة.
مع Syft، كل من وضعي التوليد أمر واحد:
# مجلد المصدر، مع وعي بملفات القفل (lockfile)
syft dir:. -o cyclonedx-json > sbom.cdx.json
# صورة الحاوية المبنية، تشمل حزم نظام التشغيل والملفات الثنائية
syft registry:ghcr.io/acme/api:1.4.2 -o cyclonedx-json > sbom-image.cdx.json
ثم أرفق SBOM بالصورة كإثبات (attestation) موقّع، ليتمكن المستهلكون من التحقق من أنها صدرت عن خط أنابيبك ولم تُعدَّل بعد ذلك:
cosign attest --predicate sbom-image.cdx.json \
--type cyclonedx ghcr.io/acme/api:1.4.2
أين تموت دقة SBOM بصمت
لكل مولّد نقاطه العمياء. اعرف نقاطك:
- الكود المضمّن والمنسوخ. دالة مأخوذة من تدوينة أو مكتبة أُدرجت يدويًا لا هوية حزمة لها. لن تظهر في القائمة.
- الملفات الثنائية الساكنة. ثنائيات Go تضمّن معلومات البناء وتستطيع الأدوات قراءتها. أما ثنائي C مجرّد من الرموز فهو صندوق أسود له اسم ملف.
- كود الواجهة المحزوم. بعد تشغيل webpack أو esbuild، تصبح القطعة الأثرية كتلة مضغوطة مبهمة. ولّد SBOM من ملف القفل قبل الحزم، ثم اشحن الاثنين معًا.
- حزم jar المظللة (shaded jars) في عالم JVM تعيد تسمية الحزم داخليًا وتُفشل المطابقة الساذجة.
قائمة SBOM تدّعي اكتمالًا لا تملكه أسوأ من لا قائمة على الإطلاق، لأن الناس تثق بها. وثّق بدقة ما تغطيه خطوة التوليد لديك وما لا تستطيع رؤيته.
من الجرد إلى الإجابات
الثمرة تُقطف عندما تسقط ثغرة CVE خطيرة. بدون SBOM، تعيد بناء ومسح كل خدمة لتعرف ما إذا كنت معرّضًا، وهو ما يستهلك أيامًا لا تملكها، بينما تمتلئ مجموعات WhatsApp الداخلية بسؤال واحد لا جواب له: هل نحن متأثرون؟ مع قوائم SBOM المخزّنة، تستعلم عن وثائق:
grype sbom:./sbom-image.cdx.json --fail-on high
والأفضل من ذلك: حمّل SBOM كل إصدار إلى خادم Dependency-Track. فهو يعيد باستمرار تقييم جردك القائم مقابل التحذيرات الجديدة، بحيث عندما تهبط الثغرة التالية من عيار Log4Shell تحصل على قائمة الخدمات المتأثرة في دقائق دون أن تلمس بناء واحدًا. وبما أنه يُستضاف ذاتيًا، تبقى بيانات جردك داخل بنيتك التحتية، وهي نقطة تهم الفرق الخاضعة لمتطلبات إقامة البيانات في الخليج وفي القطاعات المنظمة عمومًا. فارق السرعة هذا هو اللعبة كلها أثناء الحادثة، وهو يتكامل مباشرة مع العمل الإجرائي في دليلنا للاستجابة للحوادث.
توقّع ضوضاء. الماسح الذي يطابق ضد SBOM يعلّم إصدارات مصابة لا يمر بها كودك أصلًا. ولهذا وُجد VEX (Vulnerability Exploitability eXchange): بيان قابل للقراءة الآلية، يُنشر إلى جانب SBOM، ويسجّل نتيجة تحليلك:
{
"@context": "https://openvex.dev/ns/v0.2.0",
"statements": [{
"vulnerability": { "name": "CVE-2026-XXXXX" },
"products": [{ "@id": "pkg:oci/api@sha256%3A3d1f..." }],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}]
}
الفرق التي تتجاوز VEX تغرق في النتائج، ثم تبدأ بتجاهل الماسح، وتنتهي في وضع أسوأ مما كانت عليه قبل تركيبه. الفرز ليس عبئًا اختياريًا. إنه المنتج نفسه.
ما الذي لن تلتقطه SBOM أبدًا
كن صريحًا بشأن الحدود، لأن البائعين لن يكونوا كذلك. إن SBOM جرد للمكونات المعروفة. وهي لا تفعل شيئًا ضد:
- الحزم الخبيثة بلا CVE. حزمة typosquat أو إصدار زُرع فيه باب خلفي حديثًا يبقى "نظيفًا" حتى يكتشفه أحد. ستدرجه SBOM بأمانة ولن تطلق أي إنذار.
- اختراق نظام البناء. شحنت SolarWinds بناءات مسمومة من قائمة تبعيات نظيفة. دخلت البرمجية الخبيثة أثناء الترجمة، تحت الطبقة التي تصفها أي SBOM.
- الاستيلاء على حساب المصان الذي ينشر إصدار ترقيع يبدو شرعيًا عبر القناة الاعتيادية.
سد هذه الفجوات يتطلب إثبات المنشأ وضوابط الإدخال، لا مزيدًا من الجرد.
اطلب إثبات المنشأ (provenance). دليل تشفيري على مصدر القطعة الأثرية وعلى خط الأنابيب الذي بناها. يوفر SLSA نموذج النضج، ويوفر Sigstore الأدوات. عمليًا: انشر حزمك الخاصة عبر npm publish --provenance، وتحقق من صور الأطراف الثالثة بواسطة cosign verify مقابل هوية CI الخاصة بالناشر، وعامل القطع غير الموقّعة من المورّدين الحرجين كنتائج تستوجب التصعيد.
ثبّت بالمحتوى، لا بالاسم. الأسماء والوسوم قابلة للتحريك. أما البصمات (digests) فلا:
# GitHub Actions: ثبّت على commit SHA، لا على وسم يمكن لأحدهم إعادة توجيهه
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
# ثبّت الصور الأساسية عبر البصمة (digest)
FROM node:22-slim@sha256:3d1f9a...
أبطئ مسار الإدخال. معظم إصدارات الحزم الخبيثة تُكتشف وتُسحب خلال أيام من نشرها. فترة التهدئة تحوّل قدرة المجتمع على الاكتشاف إلى حماية لك:
{
"extends": ["config:recommended"],
"minimumReleaseAge": "7 days",
"internalChecksFilter": "strict"
}
تهيئة Renovate هذه تعني أن أي إصدار مخطوف يجب أن ينجو من أسبوع كامل من التدقيق العلني قبل أن تقترحه روبوتاتك أصلًا. الثمن تبعيات أقدم قليلًا. والمكسب أنك تكفّ عن أن تكون الضحية المبكرة التي تكتشف الاختراق نيابة عن الجميع.
حيّد سكربتات التثبيت. تشغيل npm ci --ignore-scripts في CI يزيل أكثر بدائل التنفيذ شيوعًا، مقابل إدراج حزمة في قائمة السماح من حين لآخر لأنها تحتاج فعلًا خطوة بناء. من واقع خبرتنا، المقايضة تستحق في كل مكان، بما في ذلك حواسيب المطورين.
خطة طرح في 30 يومًا تصمد فعلًا
الترتيب هنا مهم. الجرد قبل البوابات، والبوابات قبل التوقيع. الفرق التي تبدأ بالتوقيعات وتتجاوز ملفات القفل تبني كاتدرائية على الرمل.
- الأيام من 1 إلى 3: انضباط ملفات القفل. كل مستودع يودع ملفات القفل. يثبّت CI عبر
npm ciأوpip install --require-hashesأو ما يعادلهما في منظومتك، ويفشل عند الانحراف. - الأيام من 4 إلى 7: ولّد SBOM في CI. أضف Syft إلى خطوط أنابيب خدماتك الخمس الأكثر حرجًا. صيغة CycloneDX JSON، بواقع SBOM واحدة لكل قطعة مبنية، تُخزَّن مع الإصدار.
- الأيام من 8 إلى 12: انصب Dependency-Track. استوعب كل SBOM آليًا. وجّه التنبيهات إلى القناة التي يقرؤها فريق المناوبة فعلًا.
- الأيام من 13 إلى 17: خط الأساس والفرز. المسح الأول سيكون قبيحًا. صنّف كل نتيجة: قابلة للاستغلال الآن، أو تحتاج ترقية مجدولة، أو غير مؤثرة (اكتب بيان VEX والتحليل ما زال طازجًا).
- الأيام من 18 إلى 22: ضع بوابة على خط الأنابيب. أفشل البناءات عند الثغرات الحرجة الجديدة ذات الاستغلالات المعروفة. لا تضع بوابة على الرصيد التاريخي المتراكم، وإلا التفّ الفريق حول البوابة خلال شهر.
- الأيام من 23 إلى 26: ثبّت وتحقق. ثبّت إجراءات CI على SHA وثبّت الصور الأساسية بالبصمات. فعّل التحقق من إثبات المنشأ لمورّديك الأكثر حرجًا.
- الأيام من 27 إلى 30: أضف فترة التهدئة. فعّل Renovate أو Dependabot مع حد أدنى لعمر الإصدار، إضافة إلى
--ignore-scriptsفي كل مهمة CI.
كل هذا يعيش داخل خط أنابيب التسليم لديك، ولهذا فهو ينتمي إلى المحادثة نفسها التي تشمل بقية ضوابطك. دليلانا حول خط أنابيب DevSecOps وخطوط CI/CD التي تثق بها الفرق يغطيان الآلة المحيطة بذلك.
ما مقدار الصرامة التي تحتاجها فعلًا؟
ليس كل فريق بحاجة إلى المستوى الثالث من SLSA. الإطار الذي نطبقه مع عملائنا:
- تبيع برمجيات أو APIs لمؤسسات كبرى أو جهات منظَّمة. برنامج كامل: SBOM لكل إصدار، و Dependency-Track، و VEX، وإثبات منشأ موقّع. بنوك المنطقة والجهات الحكومية والعملاء الأوروبيون سيطالبون بالوثائق قريبًا، وعبارة "نستطيع توليد واحدة الفصل القادم" تخسر الصفقات.
- تشغّل SaaS لعملاء أصغر. توليد SBOM، ومسح مستمر، وانضباط ملفات القفل وفترة التهدئة. أجّل VEX حتى تصبح ضوضاء الماسح كلفة قابلة للقياس.
- أدوات داخلية وفريق صغير. ملفات قفل، و
osv-scannerفي CI، وإجراءات مثبّتة على SHA. ساعة إعداد واحدة تقريبًا تشتري معظم خفض المخاطر المتاح. - تدمج كودًا مولّدًا بالذكاء الاصطناعي بكثافة. أضف بوابة بشرية مخصصة تحديدًا لإدخال التبعيات الجديدة. نماذج LLM تهلوس أسماء حزم معقولة الشكل، والمتصيدون يسجلون تلك الأسماء، وأصبح slopsquatting اليوم ناقل إدخال حقيقيًا.
الخيط المشترك: الضوابط على مسار الإدخال رخيصة ومعمّرة. أما التحليل بعد وقوع الفأس فمكلف ومتأخر دائمًا. الثقة في شجرة تبعياتك يجب أن تُكتسب بالدليل، لا أن تُفترض أبدًا، وهو المبدأ نفسه الذي تطبقه فلسفة الثقة الصفرية على طبقة الشبكة.
كيف تساعدك Innovation T
تبني Innovation T هذه الآلة وتشغّلها لفرق في تونس وشمال إفريقيا وأوروبا والخليج: توليد SBOM موصول في CI، ونشر Dependency-Track بطريقة تصمد أمام حجم التنبيهات الحقيقي، وإثبات منشأ موقّع، وسياسات إدخال مضبوطة بحيث يبقى المطورون سريعين ويصبح المهاجمون بطيئين. ننفذ خطة الثلاثين يومًا أعلاه كمهمة محددة النطاق، ثم نسلّمك خط أنابيب يستطيع فريقك صيانته فعلًا.
إذا طلب منك عميل للتو ملف SBOM، أو كنت ببساطة عاجزًا عن الإجابة عن سؤال "هل نشغّل الإصدار المتأثر" في أقل من ساعة، فتحدث إلينا. استكشف خدماتنا أو تواصل معنا للحصول على تقييم جاهزية سلسلة التوريد لديك.
جاهز للبناء مع Innovation T؟
سواء كان الأمر يتعلق بالأمن أو النمو أو الهندسة، يمكن لفريقنا مساعدتك على تنفيذه بإتقان.