📍 الدليل الرئيسي: Pipeline SAST DAST SCA في 2026: معمارية، أدوات، وتكامل CI/CD
هذا الدرس يفصّل تفعيل CodeQL على GitHub ثم كتابة استعلام QL مخصص، كمكمّل لبقية أدوات SAST في خط الأنابيب.
لماذا تبنّي CodeQL في 2026
CodeQL محرّك تحليل ساكن يختلف عن أدوات SAST الأخرى بفلسفته: بدل تطبيق قواعد جاهزة، يحوّل الكود إلى قاعدة بيانات قابلة للاستعلام ويعرض لغة استعلام (QL) تشبه SQL العلائقية. النتيجة العملية: يستطيع فريق الأمن أن يكتب استعلاماً مثل «اعثر على كل المسارات التي تنتقل فيها سلسلة من header HTTP إلى استدعاء Runtime.exec() دون المرور بـ shellEscape()» وتشغيله على ملايين أسطر الكود في دقائق. هذه القدرة التعبيرية تفسّر لماذا اشترت GitHub شركة Semmle في 2019 وجعلت CodeQL المحرّك خلف Code Scanning.
النسخة 2.25.2 الصادرة في 15 أبريل 2026 تحسّن اكتشاف ثغرات Java (CFG معاد كتابته) وتُصلح ثغرة DoS في Jackson 2.16.1 المستخدمة لتحليل manifests. CodeQL مجاني للمستودعات العامة (تحليل عبر GitHub Actions بلا تكلفة) وللبحث الأكاديمي. أما المستودعات الخاصة، فهو جزء من عرض GitHub Advanced Security المدفوع، الذي انقسم منذ 1 أبريل 2025 إلى منتجَين تُفوتر حسب الاستخدام لكل committer نشط: GitHub Code Security (30 دولاراً/شهر/committer) و GitHub Secret Protection (19 دولاراً/شهر/committer). الـ CLI نفسه يبقى قابلاً للتحميل مجاناً، مما يسمح بالتجريب وكتابة الاستعلامات محلياً مهما كان وضع المستودع.
المتطلبات المسبقة
- مستودع GitHub لديك صلاحية الكتابة فيه (لتفعيل Code Scanning).
- نسخة حديثة من Git، و8 جيجا RAM كحد أدنى إذا كنت تنوي فهرسة مشروع Java أو C++ متوسط محلياً.
- VS Code مع إضافة CodeQL من GitHub مثبتة لكتابة الاستعلامات (إكمال تلقائي لـ QL ونتائج inline).
- المستوى المتوقع: متوسط في التطوير، مرتاح مع لغة مُجمَّعة وقراءة AST.
- الوقت المقدّر: 90 دقيقة للتفعيل والتحليل وكتابة استعلام QL أول.
الخطوة 1 — تفعيل Code Scanning في وضع default
وضع default هو أسرع طريق للاستفادة من CodeQL: تكتشف GitHub اللغات الموجودة في المستودع، وتختار تلقائياً مجموعات الاستعلامات المناسبة، وتُطلق المسح على كل push و pull request. لا حاجة لكتابة أي ملف YAML. للمستودع العام مجاني؛ وللخاص يجب توفر ترخيص GHAS.
Settings → Security → Code security
→ Code scanning : Set up
→ Default
→ Confirm
بعد دقائق من التأكيد، ينطلق التحليل الأول في تبويب Actions. في النهاية، تبويب Security → Code scanning يعرض النتائج المحتملة، مصنّفة حسب الخطورة (Critical, High, Medium, Low) ومرفقة بمسار الانتشار لثغرات تدفق البيانات. إذا فشل التحليل لأن مشروعاً مُجمَّعاً يتطلب خطوات بناء خاصة، فإن وضع default لم يعد كافياً ويجب الانتقال إلى وضع advanced.
الخطوة 2 — الانتقال إلى وضع advanced للتخصيص
وضع advanced يولّد ملف .github/workflows/codeql.yml يمكن للفريق تحريره لتكييف المُحفِّز ومصفوفة اللغات وحزم الاستعلامات المفعّلة أو أمر البناء. النقر على Set up → Advanced في شاشة Code Scanning يولّد الهيكل؛ المحتوى النموذجي لمشروع متعدد اللغات يبدو كما يلي.
name: CodeQL
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '17 3 * * 1'
permissions:
security-events: write
actions: read
contents: read
jobs:
analyze:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
language: [java-kotlin, javascript-typescript, python]
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
queries: security-extended,security-and-quality
- uses: github/codeql-action/autobuild@v4
- uses: github/codeql-action/analyze@v4
with:
category: "/language:${{ matrix.language }}"
ثلاث تعديلات تستحق الانتباه. المحفِّز schedule يُعيد تشغيل التحليل كل ليلة اثنين لاكتشاف CVE المُسجَّلة حديثاً في حزم CodeQL حتى دون تغيير الكود. مجموعات security-extended,security-and-quality تُفعّل superset من القواعد بما فيها الاكتشافات التجريبية — مفيدة في الوضع الإعلامي عند البدء، ثم تُشدَّد لاحقاً. صلاحية security-events: write ضرورية لدفع النتائج إلى Code Scanning، وهي نقطة كثيراً ما تُنسى عند وراثة workflow من فريق آخر.
الخطوة 3 — تثبيت CLI الخاص بـ CodeQL محلياً
العمل فقط عبر GitHub Actions يحدّ من سرعة التكرار. الـ CLI يسمح بتوليد قاعدة البيانات محلياً وتشغيل الاستعلامات في ثوانٍ، وهو أمر لا غنى عنه لتطوير استعلام مخصص. حمّل الحزمة الرسمية.
cd /opt
sudo curl -sLO https://github.com/github/codeql-cli-binaries/releases/download/v2.25.2/codeql-linux64.zip
sudo unzip codeql-linux64.zip
sudo ln -s /opt/codeql/codeql /usr/local/bin/codeql
codeql --version
git clone --depth 1 https://github.com/github/codeql.git /opt/codeql-libraries
codeql resolve languages
يجب أن يعرض خرج codeql --version سطر CodeQL command-line toolchain release 2.25.2. استنساخ مستودع github/codeql يحتوي مكتبات الاستعلامات الرسمية والحزم القياسية. أمر codeql resolve languages يسرد المستخرِجات المتاحة: cpp, csharp, go, java (alias java-kotlin), javascript (alias javascript-typescript), python, ruby, swift، بالإضافة إلى المستخرِج actions الذي يحلّل ملفات workflows YAML.
الخطوة 4 — إنشاء قاعدة CodeQL محلياً
قبل كتابة استعلام، يجب فهرسة الكود المصدري في قاعدة CodeQL. للّغات المُفسَّرة (Python, JavaScript, Ruby)، تمرّ الفهرسة ببساطة على الملفات؛ أما اللغات المُجمَّعة (Java, C++, C#, Go) فيجب على CodeQL مراقبة سلسلة الترجمة لاستخراج الأنواع وحلّ الرموز.
cd /path/to/python-project
codeql database create ./codeql-db \
--language=python \
--source-root=.
# لمشروع Java مع Maven
cd /path/to/java-project
codeql database create ./codeql-db \
--language=java \
--command="mvn -B clean install -DskipTests"
تُنتج العملية مجلد codeql-db/ يحتوي جداول علائقية تصف الكود (classes, methods, expressions, types, references). على مشروع Java بـ 100 ألف سطر، تستغرق الفهرسة من ثلاث إلى عشر دقائق حسب الجهاز. قد يصل حجم المجلد المُنتَج إلى مئات الميغابايت؛ ضعه في volume منفصل واستثنه من Git عبر .gitignore.
الخطوة 5 — تشغيل استعلام من المجموعة الرسمية
قبل كتابة استعلاماتك، تحقّق من القاعدة باستخدام الاستعلامات الرسمية. الحزم codeql/python-queries و codeql/java-queries وغيرها تحتوي الاكتشافات التي تشحنها GitHub. شغّل مجموعة security-extended على القاعدة.
codeql database analyze ./codeql-db \
codeql/python-queries:codeql-suites/python-security-extended.qls \
--format=sarif-latest \
--output=results.sarif
# للحصول أيضاً على CSV قابل للقراءة في الطرفية
codeql database analyze ./codeql-db \
codeql/python-queries:codeql-suites/python-security-extended.qls \
--format=csv \
--output=results.csv
صيغة SARIF تقرأها GitHub و DefectDojo و VS Code ومعظم منصات التجميع. الخرج CSV الذي يُحصَل عليه باستدعاء ثانٍ لـ analyze --format=csv يعطي جدولاً مقروءاً في الطرفية دون المرور عبر jq. إذا كنت تعمل مع VS Code، افتح ملف results.sarif عبر إضافة CodeQL للتنقّل التفاعلي بين النتائج والكود المصدري. هذا التحليل الأول يؤكد أن القاعدة بُنيت جيداً قبل الاستثمار في كتابة استعلامات محلية.
الخطوة 6 — كتابة أول استعلام QL مخصص
لنفترض أن كود Python لديك يستخدم دالة داخلية internal_audit.log_action(user_input) تنتهي في ملف log غير مُعقَّم. إذا احتوى user_input سطراً جديداً متبوعاً بإدخال مزيّف، يمكن للمهاجم حقن أسطر مزيفة في الـ log وإخفاء نشاطه (log forging, CWE-117). لا توجد استعلامات رسمية تغطي هذه الدالة الداخلية. أنشئ ملف queries/log-forging.ql.
/**
* @name Log forging via internal_audit.log_action
* @description User-controlled input flows into log_action without
* newline sanitization, enabling log injection.
* @kind path-problem
* @problem.severity error
* @security-severity 6.5
* @precision high
* @id custom/log-forging
* @tags security
* external/cwe/cwe-117
*/
import python
import semmle.python.security.dataflow.LogInjectionQuery
import LogInjectionFlow::PathGraph
class InternalLogSink extends DataFlow::Node {
InternalLogSink() {
exists(API::CallNode call |
call = API::moduleImport("internal_audit").getMember("log_action").getACall() and
this = call.getArg(0)
)
}
}
from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink
where
LogInjectionFlow::flowPath(source, sink) and
sink.getNode() instanceof InternalLogSink
select sink, source, sink,
"User input flows from $@ to internal log without sanitization.",
source, source.getNode().toString()
البنية تتبع الاتفاقية: تعليق ميتاداتا (اسم، وصف، نوع المشكلة، خطورة)، استيرادات المكتبات الضرورية، تعريف صنف يصف الـ sink (الدالة internal_audit.log_action)، ثم الاستعلام الرئيسي الذي يختار كل مسارات التدفق من مصدر غير موثوق إلى الـ sink. التوجيه @kind path-problem يخبر CodeQL بإنتاج مسار كامل (وليس مجرد نتيجة نقطية)، مما يساعد المطورين على فهم الانتشار. اختبر الاستعلام بـ codeql query run queries/log-forging.ql --database=./codeql-db.
الخطوة 7 — تعبئة الاستعلامات في حزمة QL قابلة للتوزيع
عندما يصبح لديك عدة استعلامات، إصدارها في حزمة QL يسمح بتوزيعها على المستودعات المختلفة دون نسخ ولصق. أنشئ ملف qlpack.yml في جذر مجلد الاستعلامات.
name: yourorg/security-queries
version: 0.1.0
dependencies:
codeql/python-all: '*'
codeql/python-queries: '*'
suites:
- codeql-suites/security.qls
defaultSuiteFile: codeql-suites/security.qls
انشر الحزمة إلى registry الخاص بـ GitHub بـ codeql pack publish بعد المصادقة (gh auth token مُصدَّر كـ GITHUB_TOKEN). بعد النشر، يمكن لأي workflow CodeQL الإشارة إلى الحزمة عبر مفتاح packs: في YAML: packs: yourorg/security-queries@~0.1. الإدارة الدلالية للإصدارات تتجنّب أن يكسر تحديث قاعدة في الحزمة تحاليل المستهلكين دون رقابة.
الخطوة 8 — فرز النتائج في GitHub Code Scanning
بمجرد أن تكون الاستعلامات في الإنتاج، تبويب Security → Code scanning في GitHub يسرد التنبيهات. ثلاث إجراءات فرز تُنظِّم العمل. Dismiss with reason يغلق نتيجة بأحد الأسباب الثلاثة (false positive, used in tests, won t fix)؛ هذا الإجراء يُولّد أثراً قابلاً للاستعراض في السجل. Open in IDE يفتح الكود في VS Code عبر بروتوكول vscode:// مع المؤشر على السطر المعني. أخيراً، Branch protection rules تتيح اشتراط غياب نتائج critical قبل إمكانية merge أي PR نحو main، مما يُفعِّل سياسة fail-on-new-issue على مستوى المستودع.
لتصدير التنبيهات إلى DefectDojo أو SIEM، استخدم REST API الخاص بـ GitHub: GET /repos/{owner}/{repo}/code-scanning/alerts يُرجع JSON الكامل، قابل للأتمتة في cron. خرج SARIF متاح أيضاً لكل تنبيه إذا كانت دقة التحليل ضرورية.
الأخطاء الشائعة
| العَرَض | السبب | الحل |
|---|---|---|
| التحليل يفشل بـ The autobuilder was unable to build the project | للمشروع خطوة بناء مخصصة لم تُكتشف | استبدل autobuild بأمر run: صريح (mvn package، ./gradlew build) |
| لغة موجودة في المستودع لا تظهر في المصفوفة | Code Scanning لا يضمّن YAML افتراضياً | أضف actions صراحة في قائمة اللغات لمسح workflows GitHub Actions |
| نتائج مكرّرة بين تشغيلين متتاليين | لا توجد فئة فريدة لكل لغة | ضمّن دائماً category: "/language:[matrix.language]" في خطوة analyze |
| الفهرسة المحلية تستغرق أكثر من 30 دقيقة | ذاكرة غير كافية (افتراضياً 2 جيجا) | خصّص المزيد بـ codeql database create --ram=8000 |
| استعلام مخصص يُرجع 0 نتائج بينما توقعنا نتائج | صنف أب خاطئ أو import منسي | اختبر أولاً بـ codeql query run --warnings=show لرصد الأخطاء الصامتة |
| تعارض بين حزم محلية وعامة | إصدارات غير متوافقة في qlpack.yml |
ثبّت الإصدارات الدقيقة (codeql/python-all: 1.2.3) بدل * |
الأسئلة الشائعة
هل CodeQL مجاني فعلاً للمستودعات الخاصة مفتوحة المصدر؟ لا. المجانية تخص فقط المستودعات العامة. المستودعات الخاصة، حتى لو كانت مفتوحة المصدر روحياً، تتطلّب GitHub Code Security (جزء من GHAS منذ أبريل 2025). الـ CLI يبقى قابلاً للتحميل والاستخدام مجاناً محلياً، لكن دمج GitHub Actions على مستودع خاص يُفوتر حسب الاستخدام لكل committer نشط.
ما الفرق مع Semgrep في وضع taint؟ CodeQL ينتج تحليلاً interprocedural شاملاً، يتتبع تدفق البيانات عبر البرنامج كله وكل المكتبات المرتبطة. Semgrep CE داخل-إجرائي؛ Semgrep Pro Engine بين-إجرائي لكنه مدفوع. في نفس الحالة الواقعية، يجد CodeQL غالباً مسارات انتشار تفوّت Semgrep، بمقابل وقت فهرسة أعلى 10 إلى 50 مرة.
كيف نُجمِّع CodeQL مع SonarQube؟ الأداتان لا تتبادلان: SonarQube يجمع الدين النوعي والأمني في dashboard تاريخي، CodeQL يتفوّق في اكتشاف مسارات انتشار معقدة. فريق ناضج يُشغِّل كليهما في CI ويستورد SARIF منهما في DefectDojo للتجميع النهائي.
هل تُشبه لغة QL لغة برمجة؟ QL تصريحية ومنطقية، أقرب إلى Datalog أو Prolog من Python. منحنى التعلم الأولي حقيقي (1 إلى 2 أسبوع لتصبح منتجاً)، لكن قوة التعبير تعوّض الاستثمار لفرق الأمن المتفرّغة.
كيف نمسح workflows الخاصة بـ GitHub Actions لاكتشاف هجوم سلسلة التوريد؟ أضف actions في مصفوفة اللغات. سيُحمِّل CodeQL تلقائياً استعلامات حزمة codeql/actions-queries التي تكتشف الأنماط الخطرة (استخدام actions خارجية بلا pin SHA، تسريب secrets، حقن في run:، صلاحيات مفرطة).
دروس ذات صلة
- كتابة قواعد Semgrep مخصصة: pattern، taint analysis، autofix — فلسفة pattern، أسرع تعلُّماً من QL للحالات البسيطة.
- حجب PR على الثغرات الجديدة دون عرقلة الفريق — سياسة عتبة قابلة للتطبيق على CodeQL عبر Branch Protection Rules.
🔝 العودة إلى الدليل الرئيسي: Pipeline SAST DAST SCA في 2026: معمارية، أدوات، وتكامل CI/CD
قراءات موصى بها
- الوثائق الرسمية لـ CodeQL
- إصدارات CLI الثنائية
- مستودع المكتبات الرسمية
- action GitHub الرسمية codeql-action
- وثائق GitHub Code Scanning مع CodeQL