Gitleaks في CI: امنع API Key قبل ما يدخل main
هتطلع من المقال بخط دفاع عملي يمنع تسريب مفاتيح API قبل ما تتحول لتذكرة Incident وتدوير مفاتيح في نص اليوم.
مستوى القارئ: متوسط
المشكلة باختصار
المشكلة مش إن المطورين مهملين. اللي بيحصل فعلاً إن secret صغير بيتحط في ملف .env أو test fixture، وبعدها يدخل commit عادي جدًا. لو اكتشفته بعد الدمج، أنت غالبًا هتعمل 3 حاجات: تلغي المفتاح، تدوّر secret جديد، وتفتش في اللوجات عن استخدام غريب.
الافتراض هنا إن عندك repo على GitHub، وفريق صغير إلى متوسط، وبتستخدم GitHub Actions. لو عندك 20 مطور و10 pull requests يوميًا، فحص مدته 20 إلى 40 ثانية على كل PR أرخص من ساعتين استجابة لتسريب مفتاح production.
مثال سريع قبل التعريف
ركز في السيناريو ده: مطور بيجرّب خدمة دفع، فيحط السطر ده في ملف اختبار مؤقت:
STRIPE_SECRET_KEY=sk_live_51Nxxxxxxxxxxxxxxxxxxxxxxxxلو الملف اتعمله commit، GitHub ممكن يلتقط السر حسب نوعه وإعدادات secret scanning. لكن أفضل طريقة مش إنك تستنى GitHub بعد push. الأفضل إن الفحص يحصل محليًا ثم في CI. كده السر بيتوقف قبل ما يدخل main.
علميًا، Gitleaks بيعمل pattern matching على محتوى Git history أو directory، ويطلع findings فيها rule id، الملف، والسطر. هو مش مدير أسرار، ومش بيعمل rotation. هو إنذار مبكر. GitHub push protection طبقة ثانية تمنع أنواع مدعومة من الأسرار أثناء push، لكن لها نطاق دعم وحدود معلنة في توثيق GitHub.
التركيب العملي: pre-commit ثم GitHub Actions
ابدأ محليًا. الهدف إن المطور يعرف الخطأ قبل ما يفتح PR.
# macOS/Linux عبر Homebrew
brew install gitleaks
# فحص مجلد المشروع الحالي
gitleaks dir . --redact --verbose
# فحص Git history لو عايز baseline أول مرة
gitleaks git . --redact --report-format json --report-path gitleaks-report.jsonبعدها ضيف GitHub Action بسيط. ده خط دفاع إلزامي لأن pre-commit اختياري ويمكن تخطيه.
name: secret-scan
on:
pull_request:
push:
branches: [main]
jobs:
gitleaks:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}ليه fetch-depth: 0؟ عشان لو عايز تفحص التاريخ المتاح للـ PR بدقة أعلى. الـ trade-off هنا إن checkout ممكن يزيد من 5 ثواني إلى 15 أو 25 ثانية في repo كبير، لكنك تكسب رؤية أفضل بدل فحص snapshot ضيق.
استخدم baseline بدون ما تدفن المشكلة
لو أول تشغيل طلع 80 finding قديم، متقفلش الفحص بالكامل. اعمل baseline، ثم خلي أي finding جديد يفشل الـ PR.
gitleaks git . --redact --report-format json --report-path gitleaks-baseline.json
gitleaks git . \
--redact \
--baseline-path gitleaks-baseline.json \
--report-format json \
--report-path gitleaks-new.jsonالرقم الواقعي: في repo عمره 4 سنين، ممكن تلاقي 30 إلى 100 إنذار أول مرة. بعد baseline مضبوط، الفحص اليومي غالبًا يطلع صفر. المهم إن baseline ما يبقاش مقبرة. راجعه مرة كل شهر وامسح منه الأسرار التي تم تدويرها.
Push protection مش بديل كامل
GitHub secret scanning وpush protection مهمين جدًا، خصوصًا للأنماط المدعومة. لكن التوثيق نفسه يوضح إن الدعم مرتبط بأنواع secrets محددة، وإن بعض الحالات زي pushes الكبيرة أو أنواع غير مدعومة قد لا يتم منعها بنفس الشكل. لذلك خليه طبقة ثانية، مش الطبقة الوحيدة.
الترتيب العملي يكون كده: Gitleaks محليًا، Gitleaks في CI، GitHub push protection، ثم rotation policy واضحة. لو secret اتسرب فعلًا، لا تكتفي بحذف commit. اعتبر المفتاح محروقًا ودوّره فورًا.
الـ trade-off هنا
بتكسب تقليل احتمال تسريب مفاتيح production، وتخلي الخطأ يظهر في PR بدل production incident. بتخسر وقت CI إضافي، وبعض false positives، ووقت إعداد baseline. لو كل PR عندك بياخد 6 دقائق أصلًا، إضافة 30 ثانية مقبولة. لو CI عندك حساس جدًا للوقت، شغّل الفحص على الملفات المتغيرة في PR، واعمل فحص كامل مجدول بالليل.
متى لا تستخدم هذه الطريقة
لا تستخدم Gitleaks كبديل عن Vault أو AWS Secrets Manager أو Doppler. هو لا يخزن الأسرار ولا يدوّرها. ولا تعتمد عليه وحده لو عندك متطلبات امتثال صارمة؛ في الحالة دي تحتاج secret scanning مركزي، صلاحيات أقل، audit logs، وسياسة rotation. كذلك لو repo فيه ملفات binary ضخمة أو history فوضوي جدًا، ابدأ بفحص directory الحالي ثم خطط لتنظيف التاريخ لاحقًا.
مصادر
- Gitleaks official repository and usage documentation
- GitHub Docs: working with secret scanning and push protection
- GitHub Docs: secret scanning detection scope and limitations
الخطوة التالية
افتح repo واحد مهم عندك النهارده، شغّل gitleaks dir . --redact، ثم ضيف GitHub Action أعلاه على PR واحد فقط. لو طلع false positives، اعمل baseline بدل تعطيل الفحص.