نظرة عامة
تسريب الأسرار في أنابيب CI/CD هو السبب الأول لاختراق الأنابيب. بيانات الاعتماد المكشوفة — مفاتيح API، وكلمات مرور قواعد البيانات، ورموز الوصول إلى السحابة — تمنح المهاجمين مساراً مباشراً إلى أنظمة الإنتاج. وفقاً لتقرير GitGuardian لعام 2025 حول حالة انتشار الأسرار، تم اكتشاف أكثر من 12 مليون سر جديد في عمليات commit العامة على GitHub في عام واحد.
المشكلة ليست أن المطورين مهملون. بل إن تسليم البرمجيات الحديث يتضمن عشرات ملفات الإعداد ومتغيرات البيئة ونقاط التكامل حيث يمكن أن ينتهي الأمر بالأسرار عن طريق الخطأ في التحكم بالإصدارات. مفتاح AWS واحد مسرّب يمكن أن يكلف المؤسسة عشرات الآلاف من الدولارات في دقائق.
يرشدك هذا المختبر العملي خلال إعداد استراتيجية كشف أسرار متعددة الطبقات تغطي ثلاث نقاط تفتيش حرجة:
- الفحص قبل الـ commit — اكتشاف الأسرار قبل أن تصل إلى المستودع.
- الفحص داخل الأنبوب — حظر طلبات السحب وعمليات الدفع التي تحتوي على أسرار.
- الفحص بعد الـ commit وأثناء التشغيل — اكتشاف الأسرار التي تتسلل والتعامل معها.
بنهاية هذا المختبر، سيكون لديك إعداد دفاع متعمق يعمل باستخدام gitleaks وtruffleHog وGitHub secret scanning وقواعد كشف مخصصة.
المتطلبات الأساسية
قبل البدء، تأكد من توفر ما يلي:
- Git 2.30+ مثبّت ومُعدّ.
- Python 3.8+ مع توفر
pip. - Docker (اختياري، لكن يُوصى به للفحص باستخدام الحاويات).
- حساب GitHub مع صلاحية إنشاء مستودعات (مطلوب لتمرين GitHub secret scanning).
- طرفية (macOS أو Linux أو WSL على Windows).
لا حاجة لأسرار حقيقية أو حسابات سحابية. سنستخدم أسراراً اختبارية مزروعة عمداً طوال هذا المختبر.
إعداد البيئة
الخطوة 1: إنشاء مستودع اختباري
ابدأ بإنشاء مستودع Git جديد سنستخدمه في جميع التمارين:
mkdir secret-leak-lab && cd secret-leak-lab
git init
echo "# Secret Leak Detection Lab" > README.md
git add README.md
git commit -m "Initial commit"
الخطوة 2: زرع أسرار اختبارية
نحتاج إلى أسرار واقعية (لكنها مزيفة) في مواقع مختلفة لمحاكاة سيناريو واقعي. أنشئ الملفات التالية:
ملف .env يحتوي على بيانات اعتماد قاعدة البيانات:
cat > .env <<'EOF'
DB_HOST=localhost
DB_PORT=5432
DB_USER=admin
DB_PASSWORD=SuperSecret123!
DB_NAME=production_db
SECRET_KEY=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
EOF
سكريبت Python يحتوي على مفتاح AWS مضمّن في الكود:
cat > deploy.py <<'EOF'
import boto3
# WARNING: These are intentionally fake credentials for testing
AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
def deploy_to_s3(bucket, file_path):
s3 = boto3.client(
's3',
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY
)
s3.upload_file(file_path, bucket, file_path)
print(f"Deployed {file_path} to s3://{bucket}")
if __name__ == "__main__":
deploy_to_s3("my-app-bucket", "dist/app.zip")
EOF
ملف YAML للإعداد يحتوي على سلسلة اتصال قاعدة البيانات:
cat > config.yml <<'EOF'
app:
name: my-application
environment: production
database:
url: "postgresql://admin:SuperSecret123!@db.example.com:5432/prod"
pool_size: 10
redis:
url: "redis://:MyRedisPassword@cache.example.com:6379/0"
EOF
ملف Dockerfile يحتوي على مفتاح API في تعليمة ENV:
cat > Dockerfile <<'EOF'
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# WARNING: Never do this in production
ENV API_KEY=sk-proj-abc123def456ghi789jkl012mno345pqr678stu901vwx234
ENV STRIPE_SECRET_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc
COPY . .
CMD ["python", "app.py"]
EOF
الخطوة 3: التحقق من الحالة “قبل”
في هذه المرحلة، لا شيء يمنع هذه الأسرار من أن يتم عمل commit لها:
git add -A
git status
يقوم Git بتجهيز كل شيء بسعادة، بما في ذلك الأسرار. لا توجد hooks، ولا فحص، ولا حواجز حماية. هذه هي الحالة التي تبدأ بها معظم المستودعات. هدفنا هو تغيير ذلك.
# Reset staging so we can test scanning before committing
git reset HEAD
التمرين 1: الفحص قبل الـ commit باستخدام gitleaks
Gitleaks هي أداة مفتوحة المصدر مصممة لاكتشاف الأسرار المضمنة في الكود داخل مستودعات Git. تدعم فحص مجلد العمل وسجل عمليات الـ commit، ويمكن تشغيلها كـ pre-commit hook لحظر الأسرار قبل أن يتم عمل commit لها.
تثبيت gitleaks
اختر طريقة التثبيت المفضلة لديك:
# macOS (Homebrew)
brew install gitleaks
# Docker
docker pull zricethezav/gitleaks:latest
# Go (from source)
go install github.com/gitleaks/gitleaks/v8@latest
تحقق من التثبيت:
gitleaks version
تشغيل gitleaks يدوياً
افحص مجلد العمل بحثاً عن الأسرار:
gitleaks detect --source . -v
يجب أن ترى مخرجات مشابهة لما يلي:
Finding: AWS_ACCESS_KEY_ID = "AKIAIOSFODNN7EXAMPLE"
Secret: AKIAIOSFODNN7EXAMPLE
RuleID: aws-access-key-id
Entropy: 3.52
File: deploy.py
Line: 4
Finding: AWS_SECRET_ACCESS_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
Secret: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
RuleID: aws-secret-access-key
Entropy: 4.71
File: deploy.py
Line: 5
Finding: DB_PASSWORD=SuperSecret123!
Secret: SuperSecret123!
RuleID: generic-credential
Entropy: 3.40
File: .env
Line: 4
Finding: STRIPE_SECRET_KEY=sk_live_4eC39HqLyjWDarjtT1zdp7dc
Secret: sk_live_4eC39HqLyjWDarjtT1zdp7dc
RuleID: stripe-secret-key
Entropy: 4.20
File: Dockerfile
Line: 9
12:14PM INF 6 commits scanned.
12:14PM WRN leaks found: 6
يتعرف Gitleaks بشكل صحيح على مفاتيح AWS وبيانات الاعتماد العامة ومفاتيح Stripe وغيرها. يتضمن كل اكتشاف الملف ورقم السطر وقاعدة الكشف التي أطلقته.
إعداد gitleaks كـ Pre-commit Hook
يسهّل إطار عمل pre-commit تشغيل gitleaks تلقائياً قبل كل عملية commit. أولاً، ثبّت pre-commit:
pip install pre-commit
أنشئ ملف .pre-commit-config.yaml في جذر المستودع:
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks
ثبّت الـ hook:
pre-commit install
اختبار الـ Hook: عمل commit لسر (محظور)
git add deploy.py
git commit -m "Add deployment script"
يتم حظر الـ commit:
Detect hardcoded secrets.................................................Failed
- hook id: gitleaks
- exit code: 1
12:15PM WRN leaks found: 2
يوقف pre-commit hook عملية الـ commit بالكامل. لا يصل السر أبداً إلى سجل Git.
اختبار الـ Hook: عمل commit لكود نظيف (يمر بنجاح)
أنشئ ملفاً لا يحتوي على أسرار:
cat > utils.py <<'EOF'
def format_date(date_obj):
return date_obj.strftime("%Y-%m-%d")
def sanitize_input(user_input):
return user_input.strip().replace("<", "<").replace(">", ">")
EOF
git add utils.py
git commit -m "Add utility functions"
المخرجات:
Detect hardcoded secrets.................................................Passed
[main abc1234] Add utility functions
1 file changed, 5 insertions(+)
الكود النظيف يمر بدون مشاكل.
التمرين 2: الفحص داخل الأنبوب باستخدام gitleaks في GitHub Actions
تُعد pre-commit hooks طبقة أولى قوية، لكنها تعمل محلياً ويمكن تجاوزها. يضيف الفحص داخل الأنبوب طبقة إنفاذ من جانب الخادم لا يمكن تخطيها.
إنشاء سير عمل GitHub Actions
أنشئ الملف .github/workflows/secret-scan.yml بالمحتوى التالي:
name: Secret Scanning
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
gitleaks:
name: Detect Secrets with gitleaks
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
معامل fetch-depth: 0 ضروري — فهو يضمن توفر سجل Git الكامل حتى يتمكن gitleaks من فحص جميع عمليات الـ commit، وليس فقط الأخيرة.
كيف يعمل في الممارسة العملية
السيناريو أ: طلب سحب يحتوي على سر مسرّب. يضيف مطور مفتاح API عن طريق الخطأ إلى ملف إعداد ويفتح طلب سحب. يفحص gitleaks action الفرق، ويكتشف السر، ويُعلّم الفحص على أنه فاشل. لا يمكن دمج طلب السحب حتى تتم إزالة السر.
السيناريو ب: طلب سحب نظيف. يفتح مطور طلب سحب يحتوي على منطق التطبيق بدون أسرار. يفحص gitleaks action الفرق، ولا يجد شيئاً، ويُعلّم الفحص على أنه ناجح. يمكن لطلب السحب المتابعة إلى مراجعة الكود والدمج.
لإنفاذ هذا، اذهب إلى إعدادات المستودع Settings ← Branches ← Branch protection rules وأضف gitleaks كفحص حالة مطلوب للفرع main. هذا يمنع أي شخص من دمج طلب سحب يفشل في فحص الأسرار.
التمرين 3: الفحص داخل الأنبوب باستخدام truffleHog
TruffleHog يتبع نهجاً مختلفاً في اكتشاف الأسرار. بالإضافة إلى مطابقة الأنماط، يمكنه التحقق مما إذا كانت الأسرار المكتشفة نشطة فعلاً عن طريق اختبارها مقابل API الخدمة المقابلة.
تثبيت truffleHog
# pip
pip install trufflehog
# Docker
docker pull trufflesecurity/trufflehog:latest
# Homebrew
brew install trufflehog
تشغيل truffleHog على المستودع الاختباري
# Scan the local repo
trufflehog git file://. --only-verified
علامة --only-verified تُخبر truffleHog بالإبلاغ فقط عن الأسرار التي تأكد من أنها نشطة. هذا يقلل بشكل كبير من النتائج الإيجابية الكاذبة. إذا أردت رؤية جميع الاكتشافات بما في ذلك غير المُتحقق منها، احذف العلامة:
# Show all findings (verified and unverified)
trufflehog git file://.
مُتحقق منه مقابل غير مُتحقق منه: السر المُتحقق منه هو سر اختبره truffleHog مقابل API المزود وتأكد من أنه نشط. على سبيل المثال، سيحاول المصادقة باستخدام مفتاح AWS لمعرفة ما إذا كان يعمل. السر غير المُتحقق منه يطابق نمطاً معروفاً لكن لم يتم تأكيده كنشط — قد يكون مفتاحاً مُلغى أو عنصراً نائباً أو نتيجة إيجابية كاذبة.
إنشاء مهمة في أنبوب GitLab CI
يتكامل TruffleHog بشكل جيد مع GitLab CI. أضف ما يلي إلى ملف .gitlab-ci.yml:
stages:
- security
secret-scan:
stage: security
image:
name: trufflesecurity/trufflehog:latest
entrypoint: [""]
script:
- trufflehog git file://. --fail --json > trufflehog-results.json
artifacts:
when: always
paths:
- trufflehog-results.json
expire_in: 30 days
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: '$CI_COMMIT_BRANCH == "main"'
علامة --fail تجعل truffleHog يخرج برمز حالة غير صفري إذا تم العثور على أسرار، مما يُفشل الأنبوب. علامة --json تُخرج نتائج منظمة يمكن تحليلها بواسطة أدوات أو لوحات تحكم أخرى.
gitleaks مقابل truffleHog: متى تستخدم أياً منهما
| الميزة | gitleaks | truffleHog |
|---|---|---|
| طريقة الكشف | Regex + entropy | Regex + entropy + verification |
| التحقق من الأسرار | لا | نعم (يختبر إذا كان السر نشطاً) |
| السرعة | سريع جداً | أبطأ (بسبب التحقق) |
| معدل النتائج الإيجابية الكاذبة | متوسط | منخفض (مع –only-verified) |
| قواعد مخصصة | نعم (.gitleaks.toml) | نعم (custom detectors) |
| دعم Pre-commit | أصلي | عبر سكريبت مُغلّف |
| الأفضل لـ | فحص pre-commit وPR السريع | الفحص العميق والتحقق |
التوصية: استخدم gitleaks لـ pre-commit hooks السريعة وفحوصات PR. استخدم truffleHog للفحوصات العميقة الدورية وعندما تحتاج إلى نتائج مُتحقق منها لتحديد أولويات المعالجة.
التمرين 4: GitHub Secret Scanning وPush Protection
يوفر GitHub فحص أسرار مدمج يعمل على مستوى المنصة. على عكس gitleaks وtruffleHog اللذين تقوم بتثبيتهما وإعدادهما بنفسك، فإن GitHub secret scanning مدمج مباشرة في إعدادات المستودع.
تفعيل Secret Scanning
- اذهب إلى مستودعك على GitHub.
- انتقل إلى Settings ← Code security and analysis.
- فعّل Secret scanning.
- فعّل Push protection.
Push protection هي الميزة الرئيسية هنا. عند تفعيلها، سيحظر GitHub أي عملية push تحتوي على نمط سر معروف قبل أن تصل إلى المستودع.
اختبار Push Protection
حاول عمل push لـ commit يحتوي على نمط سر معروف، مثل مفتاح وصول AWS أو رمز وصول شخصي لـ GitHub:
# Stage and commit a file with a test secret
git add deploy.py
git commit -m "Add deploy script"
git push origin main
يحظر GitHub عملية الدفع برسالة مثل:
remote: error: GH013: Repository rule violations found for refs/heads/main.
remote:
remote: - GITHUB PUSH PROTECTION
remote: ——————————————————————————————————————————
remote: Resolve the following violations before pushing again
remote:
remote: — Push cannot contain secrets —
remote:
remote:
remote: (?) To push, remove secret from commit(s) or follow this URL to allow the secret.
remote:
remote: — Amazon AWS Access Key ID —
remote: locations:
remote: - commit: abc1234def5678
remote: path: deploy.py:4
remote:
! [remote rejected] main -> main (push rule violations)
error: failed to push some refs
التعامل مع النتائج الإيجابية الكاذبة
إذا وضع GitHub علامة على قيمة ليست سراً حقيقياً (على سبيل المثال، بيانات اختبار ثابتة أو مثال توثيقي)، يمكنك تجاوز push protection مع تقديم سبب. يوفر GitHub رابطاً في رسالة الرفض حيث يمكنك:
- اختيار سبب التجاوز: “يُستخدم في الاختبارات” أو “نتيجة إيجابية كاذبة” أو “سأصلحه لاحقاً”.
- إرسال التجاوز، مما يسمح بعملية الدفع لكن يُسجّل الحدث للتدقيق.
يمكن لمسؤولي المؤسسة رؤية جميع التجاوزات في لوحة تحكم Security ← Secret scanning.
برنامج الشركاء
يتشارك GitHub مع أكثر من 200 مزود خدمة (AWS وStripe وTwilio وSendGrid وغيرها) من خلال برنامج شركاء secret scanning. عند اكتشاف سر من شريك:
- يُخطر GitHub مزود الخدمة تلقائياً.
- يلغي المزود بيانات الاعتماد المخترقة.
- يتم إخطار مالك المستودع عبر البريد الإلكتروني وتبويب Security.
هذا يعني أنه حتى لو تسلل سر متجاوزاً جميع خطوط الدفاع الأخرى ووصل إلى مستودع عام، يمكن تقليل نافذة الضرر إلى دقائق من خلال الإلغاء التلقائي.
التمرين 5: أنماط الأسرار المخصصة
تغطي قواعد الكشف الافتراضية المزودين الشائعين (AWS وStripe وGitHub وGoogle Cloud وغيرها)، لكن معظم المؤسسات لديها أيضاً أسرار داخلية بتنسيقات مخصصة لن تكتشفها الأدوات القياسية. يدعم Gitleaks القواعد المخصصة من خلال ملف إعداد .gitleaks.toml.
إنشاء إعداد gitleaks مخصص
أنشئ ملف .gitleaks.toml في جذر المستودع:
[extend]
# Extend the default gitleaks configuration
# useDefault = true
[[rules]]
id = "mycompany-api-key"
description = "MyCompany Internal API Key"
regex = '''MYCOMPANY-KEY-[A-Za-z0-9]{32}'''
tags = ["internal", "api-key"]
keywords = ["mycompany-key"]
[[rules]]
id = "internal-database-url"
description = "Internal Database Connection String"
regex = '''postgresql://[^:]+:[^@]+@internal-db\.[a-z0-9-]+\.corp\.[a-z]+\.com'''
tags = ["internal", "database"]
keywords = ["internal-db"]
[[rules]]
id = "internal-jwt-signing-key"
description = "Internal JWT Signing Key"
regex = '''JWT_SIGNING_KEY=[A-Za-z0-9+/=]{64,}'''
tags = ["internal", "jwt"]
keywords = ["jwt_signing_key"]
[allowlist]
description = "Global allowlist"
paths = [
'''(.*?)test(.*?)\.py''',
'''(.*?)_test\.go''',
'''(.*?)spec(.*?)\.js''',
'''(.*?)fixtures(.*?)''',
'''README\.md'''
]
[[rules.allowlist]]
id = "mycompany-api-key"
regexes = [
'''MYCOMPANY-KEY-EXAMPLE[A-Za-z0-9]{24}''',
'''MYCOMPANY-KEY-TEST[A-Za-z0-9]{28}'''
]
فهم ملف الإعداد
- القواعد المخصصة: تُحدد أقسام
[[rules]]أنماطاً خاصة بمؤسستك. يستخدم حقلregexتعبيرات نظامية متوافقة مع Go. يساعد حقلkeywordsأداة gitleaks على تصفية الملفات بسرعة — فقط الملفات التي تحتوي على الكلمة المفتاحية يتم فحصها بالتعبير النظامي الكامل، مما يحسن الأداء. - قائمة السماح العامة: يُحدد قسم
[allowlist]المسارات التي يجب استبعادها من جميع عمليات الفحص. ملفات الاختبارات والبيانات الثابتة والتوثيق هي استثناءات شائعة. - قائمة السماح على مستوى القاعدة: يُحدد قسم
[[rules.allowlist]]استثناءات لقواعد محددة. هنا، نستثني مفاتيح الأمثلة المعروفة التي تظهر في التوثيق أو مساعدات الاختبار.
اختبار الإعداد المخصص
أنشئ ملفاً يحتوي على سر مخصص للاختبار:
cat > internal-config.py <<'EOF'
MYCOMPANY_API_KEY = "MYCOMPANY-KEY-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
EOF
شغّل gitleaks مع الإعداد المخصص:
gitleaks detect --source . --config .gitleaks.toml -v
تكتشف القاعدة المخصصة مفتاح API الداخلي الذي كان سيُفوَّت بالقواعد الافتراضية.
بناء استراتيجية الدفاع المتعمق
لا تكفي طبقة واحدة من اكتشاف الأسرار. يمكن للمطورين تخطي pre-commit hooks. فحوصات الأنابيب تكتشف الأسرار فقط في وقت طلب السحب. GitHub push protection يغطي فقط أنماط المزودين المعروفين. الاستراتيجية القوية تُطبّق كل هذه الطبقات معاً.
الطبقات الخمس للدفاع عن الأسرار
┌─────────────────────────────────────────────────────┐
│ Layer 1: Pre-commit Hook (gitleaks) │
│ → Catches secrets before they enter local history │
├─────────────────────────────────────────────────────┤
│ Layer 2: PR / Merge Request Scan (gitleaks action) │
│ → Blocks PRs that contain secrets │
├─────────────────────────────────────────────────────┤
│ Layer 3: Push Protection (GitHub / GitLab) │
│ → Platform-level block on known secret patterns │
├─────────────────────────────────────────────────────┤
│ Layer 4: Post-merge Scan (truffleHog scheduled) │
│ → Weekly deep scan with verification │
├─────────────────────────────────────────────────────┤
│ Layer 5: Runtime Monitoring (vault audit logs) │
│ → Detect secret usage anomalies in production │
└─────────────────────────────────────────────────────┘
لماذا لا تكفي طبقة واحدة
- Pre-commit hooks يمكن تجاوزها باستخدام
git commit --no-verifyأو باستخدام عميل Git لا يدعم الـ hooks. - فحوصات الأنابيب تعمل فقط على الفروع التي تُشغّل CI — عمليات الدفع المباشرة إلى الفروع غير المحمية أو عمليات force push قد تتخطاها.
- Push protection تكتشف فقط أنماط المزودين المعروفين — الأسرار الداخلية المخصصة غير مشمولة.
- الفحوصات بعد الدمج تفاعلية — تجد الأسرار بعد أن تكون بالفعل في المستودع.
كل طبقة تعوّض نقاط ضعف الطبقات الأخرى. معاً، تُنشئ نظاماً حيث يحتاج السر إلى تجاوز جميع الطبقات الخمس ليمر دون اكتشاف.
سير العمل المُدمج: فحص PR والفحص الأسبوعي الشامل
إليك سير عمل GitHub Actions مُدمج يُشغّل gitleaks على كل PR ويُجري فحصاً شاملاً للمستودع أسبوعياً:
name: Secret Scanning (Multi-Layer)
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
# Full repository scan every Monday at 6:00 AM UTC
- cron: '0 6 * * 1'
jobs:
# Layer 2: PR and push scanning
gitleaks-pr-scan:
name: gitleaks PR Scan
runs-on: ubuntu-latest
if: github.event_name == 'push' || github.event_name == 'pull_request'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run gitleaks (diff scan)
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Layer 4: Weekly deep scan with truffleHog
trufflehog-full-scan:
name: truffleHog Full Repository Scan
runs-on: ubuntu-latest
if: github.event_name == 'schedule'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install truffleHog
run: pip install trufflehog
- name: Run truffleHog (full scan with verification)
run: |
trufflehog git file://. --fail --json > trufflehog-results.json || true
if [ -s trufflehog-results.json ]; then
echo "::error::Secrets detected in repository. See trufflehog-results.json."
cat trufflehog-results.json | python -m json.tool
exit 1
fi
- name: Upload scan results
if: always()
uses: actions/upload-artifact@v4
with:
name: trufflehog-results
path: trufflehog-results.json
retention-days: 90
يضمن سير العمل هذا أن كل تغيير في الكود يتم فحصه في الوقت الفعلي، ويتم تدقيق سجل المستودع بالكامل أسبوعياً بحثاً عن الأسرار التي قد تكون فُوِّتت.
التنظيف
بعد إكمال المختبر، أزل أسرار الاختبار وأعد تعيين المستودع:
# Remove test files with secrets
rm -f .env deploy.py config.yml Dockerfile internal-config.py
# Remove test configurations (optional — keep if you want to reuse them)
# rm -f .gitleaks.toml .pre-commit-config.yaml
# Commit the cleanup
git add -A
git commit -m "Remove test secrets from lab exercises"
# If you want to completely remove secrets from Git history,
# use git-filter-repo (more thorough than git filter-branch):
pip install git-filter-repo
git filter-repo --invert-paths --path deploy.py --path .env --path config.yml --path Dockerfile
مهم: مجرد حذف الملفات لا يزيلها من سجل Git. أي شخص لديه وصول إلى المستودع يمكنه العثور على الأسرار في عمليات الـ commit السابقة. استخدم git-filter-repo لإعادة كتابة السجل وإزالة الملفات الحساسة نهائياً. بعد إعادة كتابة السجل، قم بعمل force-push إلى الخادم البعيد واطلب من جميع المتعاونين إعادة استنساخ المستودع.
النقاط الرئيسية
- الأسرار في CI/CD هي أكثر متجهات الهجوم شيوعاً لاختراق الأنابيب. بيانات اعتماد واحدة مسرّبة يمكن أن تمنح المهاجم وصولاً كاملاً إلى بنية الإنتاج التحتية.
- Pre-commit hooks مع gitleaks توفر أسرع حلقة تغذية راجعة. يتم تنبيه المطورين فوراً، قبل أن يدخل السر إلى سجل Git.
- الفحص داخل الأنبوب هو طبقة إنفاذ إلزامية. لا يمكن للمطورين تجاوزها وتضمن عدم دمج أي طلب سحب يحتوي على أسرار.
- قدرة التحقق في truffleHog تقلل النتائج الإيجابية الكاذبة بشكل كبير. استخدمه للفحوصات العميقة المجدولة حيث تهم الدقة أكثر من السرعة.
- GitHub push protection وبرنامج الشركاء يضيفان دفاعاً على مستوى المنصة يعمل دون أي إعداد في أنابيب CI/CD الخاصة بك.
- قواعد الكشف المخصصة ضرورية لاكتشاف الأسرار الخاصة بالمؤسسة التي ستفوتها الأدوات القياسية. استثمر الوقت في كتابة قواعد لتنسيقات مفاتيحك الداخلية.
- الدفاع المتعمق هو الاستراتيجية الموثوقة الوحيدة. لا توجد أداة أو طبقة واحدة تكتشف كل شيء. اجمع بين pre-commit والفحص داخل الأنبوب وpush protection والفحوصات المجدولة ومراقبة وقت التشغيل للتغطية الشاملة.
الخطوات التالية
الآن بعد أن أصبح بإمكانك اكتشاف ومنع تسريب الأسرار، الخطوة التالية هي إزالة الأسرار المضمنة في الكود بالكامل من خلال تبني إدارة أسرار صحيحة:
- إدارة الأسرار في أنابيب CI/CD — تعلم كيفية استخدام HashiCorp Vault وAWS Secrets Manager ومخازن أسرار CI/CD الأصلية لحقن الأسرار في وقت التشغيل دون تخزينها في الكود.
- بيانات الاعتماد قصيرة الأجل وWorkload Identity Federation — تخلص من الأسرار طويلة الأجل نهائياً باستخدام OIDC-based workload identity federation لمصادقة الأنابيب مع مزودي السحابة دون أي بيانات اعتماد مُخزّنة.