ما هي سلسلة التوريد البرمجية؟
سلسلة التوريد البرمجية تشمل كل المكونات والعمليات التي تدخل في بناء تطبيقك: التبعيات، أدوات CI/CD، السجلات (registries)، والأشخاص الذين يطورون الكود.
💡 نسخة 2025 من OWASP Top 10 العامة رفعت هذا الموضوع إلى فئة مستقلة قائمة بذاتها — Software Supply Chain Failures (A03:2025) — بعد أن كان مدمجًا فقط ضمن "مكونات قديمة/عرضة للثغرات". هذا يعكس حجم الخطر الفعلي: تحليل عشرات آلاف الثغرات المسجّلة أظهر أن سلسلة التوريد تستحق تصنيفًا منفصلًا لا مجرد فرع من موضوع آخر.
Software Supply Chain:
مطور --> كود --> تبعيات --> بناء --> CI/CD --> سجل --> إنتاج
↑ ↑
npm/PyPI/Maven Docker Hub/GHCR
Software Bill of Materials (SBOM)
SBOM هو قائمة رسمية بكل المكونات في تطبيقك - مثل قائمة المكونات لمنتج صناعي.
{
"$schema": "https://cyclonedx.org/schema/bom-1.4.schema.json",
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"version": 1,
"metadata": {
"component": {
"name": "my-api",
"version": "1.0.0",
"type": "application"
}
},
"components": [
{
"name": "express",
"version": "4.18.2",
"type": "library",
"licenses": [
{ "license": { "id": "MIT" } }
],
"purl": "pkg:npm/express@4.18.2",
"externalReferences": [
{
"url": "https://github.com/expressjs/express",
"type": "vcs"
}
]
}
]
}
إنشاء SBOM
# باستخدام Syft (للمشاريع والحاويات)
syft packages . -o cyclonedx-json > sbom.json
syft myimage:latest -o spdx-json > sbom.image.json
# باستخدام npm
npm sbom --sbom-format=cyclonedx > sbom.npm.json
# باستخدام Trivy
trivy filesystem --format cyclonedx --output sbom.json .
trivy image --format spdx-json --output sbom.image.json node:18-alpine
توقيع الكود والحزم (Code & Package Signing)
التوقيع يضمن أن الكود الذي تستخدمه هو فعلاً من المطور الأصلي ولم يتم التلاعب به.
# توقيع Git commits
git config --global user.signingkey ABCDEF123456
git config --global commit.gpgSign true
git commit -S -m "feat: add secure auth"
# توقيع Git tags
git tag -s v1.0.0 -m "Release v1.0.0"
# التحقق من التوقيعات
git verify-commit HEAD
git verify-tag v1.0.0
Cosign - توقيع الحاويات
# تثبيت Cosign
brew install cosign
# إنشاء مفتاح توقيع
cosign generate-key-pair
# توقيع صورة Docker
cosign sign --key cosign.key ghcr.io/myorg/myapp:latest
# التحقق من التوقيع
cosign verify --key cosign.pub ghcr.io/myorg/myapp:latest
هجمات Dependency Confusion
هجوم يعتمد على أن مدير الحزم يفضل الحزمة العامة على الخاصة إذا كان لهما نفس الاسم:
// dependency-confusion-attack.js
// مهاجم ينشر حزمة على npm بنفس اسم حزمة داخلية
const attack = {
// المثال: شركة تستخدم حزمة داخلية "@company/auth"
// المهاجم ينشر "auth" على npm العام
packages: [
{ internal: '@company/auth', public: 'auth' },
{ internal: '@company/logger', public: 'company-logger' },
],
// إذا كان npm config يسمح بالحزم العامة،
// npm install auth --> يحمل الحزمة الخبيثة
};
منع Dependency Confusion
// .npmrc - تعيين سجل خاص فقط
@company:registry=https://npm.pkg.github.com/
registry=https://registry.npmjs.org/ // عام للمتبقي
// أو منع الحزم العامة تماماً
// .npmrc
registry=https://private-registry.company.com/
# GitHub Actions مع منع الحزم العامة
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
registry-url: https://npm.pkg.github.com/
scope: '@company'
- run: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Lock Files
Lock files تثبت إصدارات التبعيات و hashesها لضمان أن كل بيئة تحصل على نفس المكونات:
// package-lock.json (جزء)
{
"name": "my-app",
"lockfileVersion": 3,
"packages": {
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
"integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfzO...",
"engines": { "node": ">= 0.10.0" }
}
}
}
# استخدام lock files بأمان
npm ci # يستخدم lock file فقط - أسرع وأأمن
npm install # قد يحدث lock file - استخدمه فقط لإضافة حزمة
# التحقق من أن lock file مطابق
npm ls --all # يعرض شجرة التبعيات
السجلات الموثوقة (Trusted Registries)
| نوع السجل | مثال | الموثوقية |
|---|---|---|
| Official | npmjs.org, Docker Hub Official | عالية جداً |
| Verified | GitHub Packages, GCR | عالية |
| Private | سجل الشركة الداخلي | كاملة |
| Personal | حساب شخصي | متوسطة |
| Unknown | سجل غير معروف | منخفضة جداً |
// التحقق من مصدر الحزمة
async function verifyPackageSource(packageName) {
const npmInfo = await fetch(`https://registry.npmjs.org/${packageName}`)
.then(r => r.json());
return {
name: packageName,
version: npmInfo['dist-tags']?.latest,
hasSignature: npmInfo.dist?.signatures?.length > 0,
maintainers: npmInfo.maintainers?.map(m => m.name),
created: npmInfo.time?.created,
hasIntegrity: !!npmInfo.dist?.integrity,
};
}
Package Provenance
GitHub Artifact Attestation يثبت أن الحزمة بنيت من مصدر معين:
# GitHub Actions مع attestation
name: Build and Publish
jobs:
build:
permissions:
id-token: write # مطلوب للتوقيع
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- run: npm ci && npm run build
# توقيع ورفع
- uses: actions/attest-build-provenance@v1
with:
subject-path: 'dist/*.tgz'
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
# التحقق من provenance
gh attestation verify dist/my-package-1.0.0.tgz \
--owner my-org
مراقبة السلسة في CI/CD
# .github/workflows/supply-chain.yml
name: Supply Chain Security
on: [push, pull_request]
jobs:
sbom:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
format: cyclonedx-json
output-file: sbom.json
- name: Validate SBOM
run: |
# التحقق من أن كل التبعيات معروفة
node .scripts/validate-sbom.js sbom.json
- name: Upload SBOM
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.json
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Verify dependencies
run: |
npm ci --audit=false
npm audit --audit-level=high
- name: Check for dependency confusion
run: |
node .scripts/check-confusion.js
أفضل ممارسات أمن سلسلة التوريد
- أنشئ وصَدر SBOM لكل إصدار
- وقع git commits بالتوقيعات GPG أو SSH
- وقع صور Docker باستخدام Cosign أو Docker Content Trust
- استخدم lock files (package-lock.json, yarn.lock)
- امنع Dependency Confusion عبر scoped packages وسجلات خاصة
- تحقق من integrity للتبعيث (subresource integrity)
- استخدم سجلات موثوقة فقط (Official, Verified, Private)
- طبق سياسة تحديثات منتظمة
- راجع التبعيات يدوياً خاصة عند إضافة حزمة جديدة
- راقب GitHub Advisory Database للثغرات في التبعيات
⚠️ هجمات سلسلة التوريد من أخطر الهجمات حالياً (SolarWinds 2020, Codecov 2021, ودودة npm الذاتية الانتشار "Shai-Hulud" 2025 التي أصابت مئات حزم npm عبر سرقة بيانات اعتماد المطورين ونشرت نفسها تلقائيًا في كل حزمة يملك المصاب صلاحية نشر عليها). حزمة خبيثة واحدة قد تخترق آلاف التطبيقات. ثق لكن تحقق (Trust but Verify).
🎯 التالي: معيار OWASP ASVS