
طبقة أمان اعتمادية آلية لمساعدي الترميز بالذكاء الاصطناعي تقوم بتدقيق الحزم بحثاً عن CVEs، وانتحال الهجاء، والتخلي، ومشاكل عمر الإصدار، وتكامل التجزئة عبر أنظمة npm، PyPI، RubyGems، Maven، Go، وRust.
عندما تقوم مساعدات البرمجة بالذكاء الاصطناعي مثل Claude بإضافة حزم إلى مشروعك، فإنها غالبًا ما تختار أي إصدار يبدو مناسبًا — دون التحقق مما إذا كان يحتوي على ثغرات أمنية معروفة، أو ما إذا كانت الحزمة لا تزال قيد الصيانة النشطة، أو ما إذا كان الاسم على بُعد خطأ إملائي واحد من اسم مشابه خبيث.
safer-dependencies هي طبقة أمان لـ Claude Code: تقع بين Claude وملفات البيان الخاصة بك وتقوم بتشغيل فحوصاتها الأمنية تلقائيًا: يتم رفض التثبيتات المعرضة للخطر قبل تشغيلها، ويتم تصحيح الإصدار الخطير المكتوب في ملف بيان على القرص مباشرة بعد الكتابة. تكتشف وتصلح التبعيات الخطرة — CVEs، وانتحال الأسماء، والحزم المهجورة، ومشاكل عمر الإصدار، بالإضافة إلى فترة تبريد للإصدارات الجديدة تمامًا — عبر npm وPyPI وRubyGems وMaven وGo وRust وPHP (Composer). راجع CAPABILITIES.md لمعرفة بالضبط ما هو مغطى وما ليس مغطى.
جديد هنا؟ GETTING-STARTED.md يأخذك من الصفر إلى تثبيت يعمل في حوالي خمس دقائق.
الأمان والخصوصية: راجع SECURITY.md (الإفصاح عن الثغرات)، وPRIVACY.md (تصدير البيانات، بدون تتبع)، وCAPABILITIES.md (ما يدافع عنه الأداة وما لا يدافع عنه).
الترخيص (المصدر متاح — وليس "مفتوح المصدر" وفقًا لـ OSI): مجاني للاستخدام والتعديل لأغراضك الخاصة، بما في ذلك الاستخدام الداخلي للربح/للشركات وبناء المنتجات التي تبيعها. يلزم ترخيص مدفوع منفصل فقط لتحقيق الدخل من البرنامج نفسه — بيعه، أو شحنه داخل منتج أو خدمة تُباع، أو تقديم وظائفه لأطراف ثالثة مقابل رسوم (بما في ذلك الاستضافة/SaaS/API). يجب أن يحتفظ إعادة التوزيع والمشتقات بالترخيص وينسب الفضل إلى هذا المشروع. راجع (القسم 4 للقيود التجارية)؛ طلبات الترخيص التجاري عبر .
GETTING-STARTED.md يأخذك من الصفر إلى تثبيت يعمل في حوالي خمس دقائق — المتطلبات الأساسية، والتثبيت التفاعلي، والتحقق. للمرجع الكامل للتثبيت (التثبيتات العامة/المشروع/اليدوية، خصوصيات Windows، قائمة السماح بالأذونات، والتحديث، وإلغاء التثبيت)، راجع INSTALLATION.md.
الاستخدام اليومي: بمجرد تثبيت الخطافات، لا يوجد شيء لتشغيله — يعمل safer-dependencies تلقائيًا في الخلفية. عندما يضيف Claude الحزم أو يثبتها، فإنه يشير إلى التبعيات الخطرة ويقوم بترقية الإصدارات المعرضة للخطر إلى إصدار آمن في مكانها — ويمنع تثبيتًا معروفًا بأنه معرض للخطر قبل أن يعمل حتى — بحيث يتم اكتشاف الحزم غير الآمنة وتصحيحها دون أن تضطر إلى السؤال. لا يزال بإمكانك استدعاءه مباشرة في أي وقت: "هل [email protected] آمن؟"، "تحقق من إعداد safer-dependencies"، أو "اعرض إحصائيات safer-dependencies".
عندما يكون Claude على وشك إضافة حزمة إلى مشروعك، يقوم safer-dependencies بالاعتراض وتشغيل 5 فحوصات:
requirements.txt مع تثبيتات --hash=sha256:...، يتم التحقق من التجزئة المعلنة مقابل تجزئات PyPI المنشورة؛ عدم التطابق يصدر تحذيرًا WARNINGpaperclip، request، pycrypto، github.com/dgrijalva/jwt-go) يتم حظرها بشدة فورًا مع اقتراح بديل؛ الحزم التي لا تحتوي على إصدار مستقر منذ أكثر من عامين تحصل على تحذير استشاري STALE:. تتم إزالة الحزم المحظورة بشدة من ملف البيان وسيسأل Claude عن كيفية المتابعة؛ الحزم القديمة فقط تُترك في مكانها.إذا تم العثور على مشكلات، يصدر Claude تحذيرات وقد يتراجع إلى إصدار أكثر أمانًا. يتم تسجيل جميع الفحوصات في ~/.claude/safer-dependencies-audit-YYYY-MM.log (ملف واحد لكل شهر تقويمي).
تُطلق المهارة تلقائيًا عندما يقوم Claude بـ:
عمليات ملفات البيان / التثبيت
package.json، requirements.txt، Gemfile، pom.xml، build.gradle، Cargo.toml، go.mod، أو أي ملف بيان مدعوم آخرimport أو require أو use لحزمة غير معلنة بالفعل في ملف البيانnpm install، bundle install، poetry install، uv sync، go mod tidy، إلخ) — ما قبل التثبيت يدقق وسائط الأمر، وما بعد التثبيت يدقق ملف القفل الناتجDockerfile أو سير عمل CI (.github/workflows/*.yml، إلخ) يتضمن خطوات تثبيت مدير حزم مثبتةأسئلة الاختيار والتوصية
عبارات نية الاستخدام (قبل الإضافة)
أسئلة صحة الحزمة والثقة
أوامر التهيئة
npx create-react-app، npm create vite@latest، django-admin startproject، rails new، cargo new + cargo add، "أنشئ مشروع FastAPI جديدًا"إضافات الحزم الضمنية (طلبات الميزات التي تعني تبعية جديدة)
الترحيل والنقل
لا يُطلق لـ:
os، fs، java.util.*، إلخ)هذه حزمة مهارة + خطافات، وليست ملف مهارة واحدًا. ينشر التثبيت الكامل هذه الأجزاء:
| الملف | الدور |
|---|---|
skills/safer-dependencies.md | المهارة (SKILL.md بعد التثبيت). تصف إجراءات التدقيق وتتضمن وضع الإدارة للتثبيت/الإحصائيات. |
skills/safer-dependencies-shim.sh | خطاف PostToolUse:Write/Edit — يدقق كتابات ملفات البيان وملفات القفل ويصحح تلقائيًا الإصدارات المعرضة للخطر في مكانها (وضع الاعتراض). |
skills/safer-dependencies-pretooluse-bash.sh | خطاف PreToolUse:Bash — تدقيق OSV أولي لأوامر تثبيت مدير الحزم؛ يرفض التثبيتات المحددة المعرضة للخطر قبل تشغيل التثبيت (وضع ما قبل التثبيت). |
skills/safer-dependencies-posttooluse-bash.sh | خطاف PostToolUse:Bash — تدقيق لاحق بعد أوامر Bash؛ يلتقط CVEs غير المباشرة في ملفات القفل المكتوبة حديثًا، وملفات البيان المعدلة عبر sed/jq/البرامج النصية، والبيئة المحلولة لـ pip install العادي (وضع ما بعد التثبيت). |
skills/safer-dependencies-pretooluse-agent.sh + skills/safer-dependencies-posttooluse-agent.sh | زوج خطافات PreToolUse:Agent + PostToolUse:Agent — يسد فجوة تغطية الوكلاء الفرعيين. الأوضاع 2–4 تُطلق فقط لاستدعاءات أدوات الجلسة الرئيسية، لذا فإن أي ملف بيان يكتبه وكيل فرعي يتجاوزها. ما بعد الوكيل يدقق ما كتبه الوكيل الفرعي بعد كل استدعاء أداة وكيل يعود (وضع ما بعد الوكيل). |
skills/scripts/ | مكتبة Python مشتركة (safedep/) وبرامج حل مستقلة تستخدمها جميع الخطافات. |
skills/scripts/safer_dependencies_manager.py | وحدة الإدارة للتثبيت التفاعلي وإحصائيات الاستخدام والتحقق من الإعداد. |
ملف المهارة وحده ليس كافيًا — بدون الخطافات، يعتمد الاستدعاء التلقائي على قرار Claude بالوصول إلى المهارة. ثبّت جميع الأجزاء الخمسة لتغطية كاملة؛ العديد من المهارات والأوامر المائلة ترسل وكلاء فرعيين داخليًا، لذا فإن زوج ما بعد الوكيل مهم حتى لو لم تقم بتوليد واحد صراحةً أبدًا. (راجع FAQ.md لمعرفة لماذا لا يمكن للمهارة وحدها ضمان التغطية.)
| النظام البيئي | ملف البيان | ملف القفل |
|---|---|---|
| npm | package.json | package-lock.json، yarn.lock، pnpm-lock.yaml |
| PyPI | requirements.txt، pyproject.toml، Pipfile، setup.py، setup.cfg | Pipfile.lock، poetry.lock، uv.lock |
| RubyGems | Gemfile، *.gemspec | Gemfile.lock |
| Maven | pom.xml، build.gradle، libs.versions.toml | -- |
| Go | go.mod | go.sum |
| Rust | Cargo.toml | Cargo.lock |
| PHP (Composer) | composer.json | composer.lock |
جديد في المشروع؟ ابدأ بـ GETTING-STARTED.md. النسخة المختصرة:```bash git clone https://github.com/robert-auger/safer-dependencies /tmp/safer-dependencies python3 /tmp/safer-dependencies/skills/scripts/safer_dependencies_manager.py interactive_install
يطلب المثبّت تحديد النطاق (عام مقابل مشروع) وأي خطافات (hooks) يجب تفعيلها، ثم يكتب ملف `settings.json` لك — سواءً إدخالات الخطافات **أو** قائمة السماح بالأذونات التي تتيح لأوامر الفحص الخاصة بالأداة العمل دون طلب موافقة في كل تدقيق.
كل ما يتعلق بالتثبيت موجود في **[INSTALLATION.md](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md)**، وهو المرجع الوحيد لآليات التثبيت: التثبيت اليدوي ملفًا بملف (على المستوى العام ومستوى المشروع)، تفاصيل ويندوز، خطافات Post-Agent، [قائمة السماح بالأذونات](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#permissions-allowlist)، التحقق من الإعداد، التحديث، التثبيت على إصدار محدد (release tag)، وإلغاء التثبيت.
بعد التثبيت، تتم الإدارة اليومية عبر اللغة الطبيعية مع Claude — `install safer-dependencies` (إعادة التشغيل / تغيير الخطافات)، `show safer-dependencies stats`، `check safer-dependencies setup` — أو عبر قائمة `/safer-dependencies`. التحديث يتم أيضًا داخل الجلسة: `/safer-dependencies update` يطبّق أحدث إصدار (`update --check` لتجربة جافة، `update --rollback` للتراجع)؛ راجع [INSTALLATION.md](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#in-session-self-updater-safer-dependencies-update) لنموذج الثقة.
> **ملاحظة حول المنصات:** يتم دعم macOS وLinux وWindows. يتطلب ويندوز Git for Windows (الذي يوفر bash) وPython 3 على `PATH` — دون الحاجة إلى WSL. الاختبار العملي حتى الآن ركّز على **macOS وWindows**؛ دعم Linux يتم تغطيته عبر مصفوفة CI الآلية.
### الإعداد (Configuration)
هناك أمران قابلان للتكوين بعد التثبيت:
- **قائمة السماح بالأذونات** — تعتمد مسبقًا أوامر الفحص للقراءة فقط الخاصة بالأداة (قواعد `npm audit` / `bundle audit` بالصيغة الدقيقة وسكربتات الحل الخاصة بالأداة) بحيث تعمل عمليات التدقيق دون طلب موافقة في كل مرة؛ لا يتم أبدًا اعتماد `curl` مسبقًا، و`npm view` / `pip-audit` اختيارية عبر ملف Convenience. يكتب المثبّت التفاعلي الإدخالات الأساسية لك؛ بينما تضيف التثبيتات اليدوية الكتلة الكاملة يدويًا. الكتلة الكاملة والأساس المنطقي: [INSTALLATION.md → قائمة السماح بالأذونات](https://github.com/robert-auger/safer-dependencies/blob/main/INSTALLATION.md#permissions-allowlist).
- **سياسة الأمان** — نافذة/وضع فترة التهدئة لعمر الإصدار ومستوى `off`/`warn`/`block` لكل نوع فحص، يتم تعديلها عبر `/safer-dependencies config` وتُخزَّن في `~/.config/safer-dependencies/config.toml`. المخطط ودلالات المستويات: [`skills/references/configuration.md`](https://github.com/robert-auger/safer-dependencies/blob/main/skills/references/configuration.md).
### تغيير فترة التهدئة
فترة التهدئة (المسماة **cooloff** في الإعداد) هي الحد الأدنى لعمر الإصدار الذي يجب بلوغه قبل أن تختاره الأداة — الافتراضي **7 أيام**. لتغييرها، اطلب من Claude أو شغّل أمر الإعداد مباشرة:```
/safer-dependencies config set cooloff.days 14 # require releases to be 14+ days old
/safer-dependencies config set cooloff.mode block # gate strength: off | warn | block (default: warn)
/safer-dependencies config unset cooloff.days # revert to the 7-day default
/safer-dependencies config # show effective values and where each comes from
نفس الأفعال تعمل خارج جلسة Claude:```bash python3 skills/scripts/safer_dependencies_manager.py config set cooloff.days 14
الإعداد يستمر في `~/.config/safer-dependencies/config.toml` (قسم `[cooloff]`)؛ متغيرات البيئة `SAFE_DEP_COOLOFF_DAYS` و `SAFE_DEP_COOLOFF_MODE` تتجاوز الملف لكل جلسة. ثلاث سلوكيات يجب معرفتها: `mode = "off"` يزيل مرشح العمر من اختيار الإصدار بالكامل؛ إعادة الكتابة المدفوعة بـ CVE تتجاوز البوابة، لذا لا يتم أبدًا حجب إصلاح أمني لكونه جديدًا جدًا؛ والبوابة تغطي npm و PyPI و RubyGems و crates.io — Maven و Go غير مشمولين بالبوابة عمدًا. الدلالات الكاملة: [`skills/references/configuration.md`](https://github.com/robert-auger/safer-dependencies/blob/main/skills/references/configuration.md).
## مستويات التحذير
| المستوى | المعنى | مثال |
|-------|---------|---------|
| CRITICAL | توقف واسأل المستخدم | تم اكتشاف Typosquat، توقيع معدّل |
| HIGH | حذّر وتابع | CVE معروف، حزمة عمرها أقل من 30 يومًا |
| MEDIUM | حذّر وتابع | إصدار عمره أقل من 7 أيام، توقيع مفقود |
| LOW | حذّر وتابع | جوهرة Ruby غير موقعة (متوقعة) |
## كيف يعمل
تعمل المهارة في خمسة أوضاع (ملخصة أدناه؛ الأساس المنطقي للتصميم الأعمق موجود في `skills/safer-dependencies.md`):
### الوضع العادي (يدوي)
عندما يكون Claude على وشك كتابة `import`، أو إضافة حزمة إلى ملف manifest، أو تحديث ملف lock، تعمل المهارة مباشرة في جلستك:
1. يستعلم سجل الحزم عن الإصدارات المستقرة
2. يختار تلقائيًا أحدث إصدار نُشر قبل 7+ أيام (حتمي — بدون حكم LLM)
3. يتحقق من الثغرات المعروفة عبر أدوات النظام البيئي وواجهة OSV API
4. يتحقق من توقيعات الحزم حيثما كانت متاحة
5. يصدر تحذيرات إذا تم العثور على مشكلات، ويُثبّت الإصدار الدقيق
6. يسجّل النتيجة في سجل التدقيق
اختيار الإصدار يتم بواسطة نصوص Python مستقلة مرفقة بالمهارة، وليس بواسطة LLM الذي يفسّر القواعد. يُخرج الأمر `SELECTED: <version>` ويستخدم Claude هذا الإصدار بالضبط.
### وضع الاعتراض (تلقائي)
قم بتكوين `.claude/settings.json` مع خطاف `PostToolUse` لتمكين التحقق التلقائي والشفاف من الحزم:
1. يكتب Claude ملف manifest (مثل `package.json`) بالإصدار المطلوب أصلاً — يصل الملف إلى القرص
2. يتم تشغيل خطاف `PostToolUse` فورًا بعد اكتمال الكتابة ويستدعي `safer-dependencies-shim.sh`
3. يقرأ الشيم الملف، ويحلل الحزم المعلنة، ويشغّل جميع الفحوصات الأمنية (typosquat، مهجورة، CVE، تقادم، تثبيت hash)
4. إذا كانت التصحيحات مطلوبة، يقوم الشيم **بإعادة كتابة الملف في مكانه** بإصدارات آمنة (أو يزيل الإدخالات التي لا تحتوي على إصدار آمن)
5. يصدر الشيم إشارات (`UPDATED:`، `BLOCKED:`، `WARNING:`، `STALE:`، `MAJOR-UPDATE-CONFIRM:`، `REFACTOR-REQUIRED:`، `REGRESSION:`، `TYPOSQUAT-CONFIRM:`، `VERIFY:`، `CLEAN:`) عبر `hookSpecificOutput.additionalContext` على stdout. تسبق `REGRESSION:` إشارة `MAJOR-UPDATE-CONFIRM:` عندما يُظهر سجل التدقيق أن نفس (الملف، الحزمة) تم تصحيحه سابقًا إلى نفس الهدف الآمن — أي أن وكيلًا فرعيًا أو خطة قديمة أعادت تقديم إصدار معروف الثغرات، ويجب على المنسّق استعادة الإصدار المعتمد سابقًا بدلاً من إعادة اتخاذ قرار الترقية الرئيسية.
6. يتلقى Claude تلك الإشارات كتذكير نظام ويقوم بأعمال المتابعة (العثور على عمليات الاستيراد المتأثرة، تشغيل الاختبارات، إعادة الهيكلة للتغييرات الكاسرة)
**ملاحظة تصميم — الشكل C (تصحيحي بعد الكتابة):** الخطاف لا يمنع الكتابات. كل إصدار معرض للثغرات يصل إلى القرص أولاً ثم يتم تصحيحه تلقائيًا ضمن نفس دورة استخدام الأداة. هذا اختيار متعمد على تصميم حظر `PreToolUse` — راجع [FAQ.md](https://github.com/robert-auger/safer-dependencies/blob/main/FAQ.md#why-posttooluse-post-write-corrective-instead-of-pretooluse-pre-write-blocking-for-the-manifest-path) للمقايضات.
**مثال على الإشارة:**```
UPDATED: aiohttp 3.8.5 → 3.9.0 (HIGH: 33 CVEs fixed)
الوكيل الأصلي يستخدم هذه الإشارات لتحديد الكود المتأثر وإعادة هيكلته حسب الحاجة.
قم بتكوين .claude/settings.json مع خطاف PreToolUse:Bash لتمكين
التدقيق المسبق لأوامر تثبيت مدير الحزم. هذا يُكمّل
(لا يستبدل) وضع الاعتراض — معًا يشكلان دفاعًا متعدد الطبقات.
npm install [email protected])PreToolUse قبل تنفيذ الاستدعاء ويستدعي
safer-dependencies-pretooluse-bash.shgit status / ls / npm test تتحمل
تكلفة ضئيلة على المسار الساخنnpm/pnpm/yarn
install/i/add)، تقوم الأداة المساعدة بتقسيم المدخلات عبر shlex، وتستخرج كل
وسيط pkg@version، وترسله عبر POST إلى OSVpermissionDecision: "deny" مع معرّف GHSA-id الخاص بكل اكتشاف + CVSS +
ملخص، بالإضافة إلى تلميح لاستدعاء مهارة safer-dependenciesلماذا يوجد هذا بالإضافة إلى وضع الاعتراض: شيم ما بعد الكتابة
لا يرى أوامر Bash. npm install [email protected] يُنفذ بالكامل (وتُشغَّل
نصوص postinstall) قبل أن يتم أي تدقيق؛ وnpm install -g typosquat-pkg لا يكتب أي ملف manifest للمشروع على الإطلاق. وضع ما قبل التثبيت
يسد هذه الفجوات هيكليًا.
وضع ما قبل التثبيت يرى فقط ما كتبه المستخدم (وسائط pkg@version على
سطر الأوامر). لا يمكنه رؤية الشجرة الانتقالية التي سيُثبّتها المحلل فعليًا.
وضع ما بعد التثبيت (أدناه) يدقق ملف القفل بمجرد اكتمال التثبيت —
الوضعان متكاملان، وليسا زائدين عن الحاجة.
النطاق: واجهات سطر أوامر مدير الحزم المغطاة هنا تمتد عبر خمسة أنظمة بيئية
(npm/pnpm/yarn/bun/npx/deno، pip/pip3/pipx/pipenv/uv/uvx/poetry، gem/bundle،
go، cargo)، بالإضافة إلى Maven عبر وضع الاعتراض (تبعيات Maven تُصرَّح عادةً
في pom.xml/build.gradle، ولا تُضاف عبر فعل CLI).
فجوة معروفة: واجهة سطر أوامر Maven تدعم التنزيل المباشر عبر
mvn dependency:get -Dartifact=group:art:versionوmvn dependency:copy. هذا الخطاف لا يتعرف بعد على هذه الاستدعاءات. إذا كنت تستخدمها بانتظام، فإن شيم ما بعد الكتابة الحالي لا يزال يلتقط ما يصل إلى ملف manifest الخاص بك، لكن حماية ما قبل الجلب تنطبق فقط على الأنظمة البيئية المذكورة أعلاه. يُتتبع كمتابعة لاحقة.
الصيغة المعترف بها لكل نظام بيئي:
| PM | الأفعال | صيغة التثبيت الثابت |
|---|---|---|
npm, pnpm, yarn, bun | install, i, add (بالإضافة إلى yarn/pnpm dlx, bun x, yarn create) | [email protected], @scope/[email protected] |
npx | (بدون فعل — الحزمة هي أول وسيط موضعي) | [email protected] |
deno | add, install | npm:[email protected] (مواصفات مسبوقة بـ npm) |
pip, pip3, pipx, pipenv, uv, uvx, poetry | install (pip/pip3/pipx/pipenv) / add (uv/poetry) / بدون فعل (uvx) | pkg==1.2.3 (الإضافات pkg[extra]==X معالجة أيضًا) |
gem, bundle | install (gem) / add | -v 1.2.3, --version 1.2.3, --version=1.2.3 (علامة منفصلة) |
go | get, install | [email protected] (يجب تضمين بادئة v وفقًا لوحدات Go) |
cargo | add, install | [email protected] |
نطاقات الإصدارات (npm ^4.17, pip >=, poetry ^/~, Go @latest) و
الإصدارات غير المحددة تمر إلى وضع الاعتراض بعد التثبيت —
شيم ما بعد الكتابة يدقق ما يختاره المحلل. إعادة الكتابة التلقائية إلى
إصدار آمن مدرجة كمتابعة لاحقة.
نمط الفشل: فتح عند الفشل. أي خطأ (غياب Python، انقطاع شبكة، مدخلات غير صالحة) يخرج بالكود 0 بدون مخرجات، مما يسمح لـ bash بالمتابعة. وضع الاعتراض لا يزال يعمل بعد التثبيت، لذا فإن فشل التدقيق المسبق يتحلل بشكل آمن إلى الحماية الحالية.
مثال على الرفض:``` safer-dependencies pre-flight audit blocked this install. Vulnerable pinned version(s) detected:
### وضع ما بعد التثبيت (خطاف Bash)
قم بتكوين `.claude/settings.json` مع خطاف `PostToolUse:Bash` لتمكين
التدقيق بعد التنفيذ بعد أوامر Bash. يقوم بتشغيل **ثلاث عمليات فحص مستقلة**
ضد `cwd` الخاص بالأمر، كل منها يسد فجوة لا يمكن للخطافات الأخرى معالجتها:
- **الفحص أ — ملفات القفل.** بعد فعل تثبيت ناجح (`npm install`،
`bundle install`، `poetry install`، `uv sync`، `go mod tidy`، إلخ)، يقوم
بتدقيق ملفات القفل المعدّلة حديثًا (`package-lock.json`، `Gemfile.lock`،
`poetry.lock`، `uv.lock`، `go.sum`، `yarn.lock`، `pnpm-lock.yaml`،
`Pipfile.lock`). وهذا يسد **فجوة الثغرات غير المباشرة (transitive-CVE)** التي لا يستطيع
Pre-Install رؤيتها: المستخدم كتب `pkg@version`، لكن الحلّال قد يكون جلب
العشرات من التبعيات غير المباشرة التي لم يسمّها أحد.
- **الفحص ب — ملفات البيان (manifests).** بعد أي أمر Bash *ليس* على
قائمة الحظر للقراءة فقط (`ls`، `cat`، `git status`، …)، يقوم بتدقيق ملفات
البيان المعدّلة حديثًا. هذا هو **الوحيد** الاحتياطي لتعديلات ملفات البيان
التي تتم عبر `sed -i` أو `jq` أو سكربت — فهذه تتجاوز أداة
`Write`/`Edit` التي يعتمد عليها وضع الاعتراض (Intercept Mode).
- **الفحص ج — البيئة المُحلَّلة.** أمر `pip install` العادي /
`pip install -r requirements.txt` لا يكتب ملف قفل، لذا لا يرى الفحص أ
الشجرة المُحلَّلة أبدًا. بعد تثبيت بصيغة pip، يعيد الفحص ج استدعاء نفس
pip مع `list --format=json` للقراءة فقط ويقوم بفحص OSV للبيئة
المُحلَّلة بالكامل (المباشرة + غير المباشرة).
كيف يعمل الفحص:
1. يقوم Claude بتشغيل استدعاء أداة Bash
2. يتم تشغيل خطاف `PostToolUse` *بعد* اكتمال الأمر ويستدعي
`safer-dependencies-posttooluse-bash.sh`
3. يقوم مرشح مبكر مكتوب بلغة Bash النقية باختصار الأوامر التي لا تطابق أي بوابة فحص في
~115 مللي ثانية (نفس اصطلاح المسار السريع كما في Pre-Install)، لذا فإن `ls` / `git` / `cat`
تتحمل تكلفة ضئيلة
4. يقوم كل فحص باجتياز `cwd` باستخدام `find -maxdepth 5` (يغطي تخطيطات
monorepo؛ ويستثني `node_modules`، `.git`، `.venv`، `venv`) للملفات المعدّلة خلال
آخر 60 ثانية — يمكن تجاوزها عبر `SAFE_DEP_POSTINSTALL_MTIME_WINDOW`
5. لكل ملف معدّل حديثًا (الفحص أ/ب)، يقوم الخطاف بتزوير حمولة اصطناعية
`PostToolUse:Write` ويرسلها إلى الشيم (shim) الموجود — حيث تعمل أدوات تدقيق
ملفات القفل وملفات البيان الخاصة بالشيم دون تغيير، دون أي منطق مكرر
6. يتم دمج الإشارات لكل ملف وإخراجها كـ JSON واحد باسم `hookSpecificOutput`
إلى الوكيل الأصلي
**ما يلتقطه ولا يلتقطه Pre-Install:** الثغرات غير المباشرة.
يمكن أن يجلب `bundle install` الذي يبدو نظيفًا `[email protected]` (CVE-2025-27610)
كتبعية غير مباشرة لـ `sinatra` — المستخدم لم يكتب `rack` أبدًا، لذا
لا يمكن لـ Pre-Install رؤيته، لكن Post-Install يقرأ ملف
`Gemfile.lock` المُحلَّل ويبلغ عن الثغرة.
**النطاق:** الفحص أ لا يعيد كتابة الإصدارات المُحلَّلة — عقد التصحيح
التلقائي ينطبق فقط على ملفات البيان التي كتبها Claude مباشرة. بالنسبة للثغرات غير المباشرة،
يكون الإصلاح عادةً "تحديث التبعية المباشرة التي تملك التبعية غير المباشرة"، وهو
ما يتطلب حكمًا بشريًا. الفحص ب *يقوم* بالتصحيح التلقائي، لأنه يدقق ملفات البيان
عبر نفس مسار الشيم كما في وضع الاعتراض. يتم تخطي الفحص أ عندما تكون
طبقة فحص `transitive` مضبوطة على `off` (`config set checks.transitive off`).
**وضع الفشل:** فتح عند الفشل (fail-open)، كما هو الحال مع الخطافات الأخرى. أي خطأ (شيم
مفقود، حمولة غير صالحة، Python غير متاح) يخرج بالرمز 0 بصمت.
**مثال على تحذير (WARNING):**```
WARNING: [email protected] in lock file has GHSA-29mw-wpgm-hmr9, GHSA-35jh-r3h4-6jhm
الأنماط الأربعة أعلاه تعمل فقط لاستدعاءات الأدوات في جلسة الجذر. عندما تقوم
جلسة الجذر بإرسال وكيل فرعي (عبر أداة Agent — العديد من المهارات وأوامر
الشرطة المائلة تقوم بذلك داخليًا)، فإن استدعاءات Write/Edit/Bash الخاصة بالوكيل الفرعي تتجاوز جميع
هذه الأنماط. وضع ما بعد الوكيل هو شبكة الأمان التفاعلية لتلك الفجوة.
PreToolUse:Agent (safer-dependencies-pretooluse-agent.sh) يعمل
مباشرة قبل كل إرسال وكيل ويلمس ملف إشارة في
/tmp/.safer-deps-agent-<PPID>-<session_id>.sentinel (مع التراجع إلى
اسم يعتمد على PPID فقط عندما لا يتوفر معرف جلسة)PostToolUse:Agent (safer-dependencies-posttooluse-agent.sh) يعمل
بعد عودة استدعاء الوكيل، ويبحث عبر find عن كل manifest و lockfile أحدث من
ملف الإشارة، ويدقق كل منها عبر نفس مسار الشيمadditionalContext للدورة التالية من جلسة الجذر؛ ويتم
إزالة ملف الإشارةيتم تغطية الوكلاء الفرعيين المتداخلين تلقائيًا — خطاف PostToolUse:Agent الخاص
بالجذر يعمل فقط بعد أن تكون جميع أعمال الوكيل الخارجي (بما في ذلك أي شيء هو
أرسله) على القرص. الفجوة الوحيدة هي التثبيت العام الذي لا يكتب أي
manifest أو lockfile (npm install -g …): لا يوجد شيء لفحصه. مثل
الخطافات الأخرى، يفشل بشكل مفتوح — أي خطأ (ملف إشارة مفقود، شيم مفقود،
حمولة غير قابلة للقراءة) يخرج بالرمز 0 بصمت. الأساس المنطقي الكامل للتصميم موجود في
skills/safer-dependencies.md.
يتم تسجيل كل فحص في ~/.claude/safer-dependencies-audit-YYYY-MM.log (ملف واحد لكل شهر تقويمي، حيث YYYY-MM هو الشهر-السنة بتوقيت UTC) كسطر JSON واحد. يمكن تجاوز المسار الكامل عبر متغير البيئة SAFE_DEP_AUDIT_LOG (عند تعيينه، لا يتم إلحاق لاحقة التاريخ). يتم أيضًا تدوير الملفات حسب الحجم عندما تتجاوز SAFE_DEP_LOG_MAX_BYTES (الافتراضي 10 ميجابايت؛ اضبطه على 0 لتعطيله). اضبط SAFE_DEP_MODEL لتجاوز قيمة النموذج المكتوبة في source.model في كل إدخال — مفيد لمقارنات A/B بين إصدارات النماذج.
جميع الأنماط الخمسة تلحق بنفس الملف. يحمل كل إدخال كتلة source (المخطط 2.2) التي تحدد أي مكوّن كتبه:
source.component | كُتب بواسطة | المشغّل |
|---|---|---|
shim.posttooluse | shim.sh | كتابة manifest أو lockfile (وضع الاعتراض، إرسال ما بعد التثبيت) |
shim.install_error | shim.sh | فشل تثبيت الفحص المسبق للشيم |
bash.pretooluse | pretooluse-bash.sh | أمر تثبيت Bash (وضع ما قبل التثبيت) |
bash.posttooluse | posttooluse-bash.sh | خطاف Bash ما بعد التثبيت نفسه، عندما يفشل بشكل مفتوح قبل الوصول إلى الشيم |
agent.pretooluse | pretooluse-agent.sh | محجوز لأحداث الفشل المفتوح قبل الوكيل (الخطاف نفسه صامت حاليًا عند النجاح) |
agent.posttooluse | posttooluse-agent.sh | أحداث الفشل المفتوح لخطاف ما بعد الوكيل (مثل شيم مفقود، python_missing) |
manual.skill | Claude يعمل في الوضع العادي | التدقيق اليدوي المستدعى سطريًا |
يسجل source.model نموذج Claude Code النشط في الجلسة (مثل "claude-sonnet-4-6"). موجود في المخطط 2.1+؛ الإدخالات المكتوبة بواسطة عمليات تثبيت أقدم تحذف الحقل. يتدهور أمر الإحصائيات بأمان إلى "unknown" عندما يكون غائبًا.
قم بالتصفية حسب source.component باستخدام jq:```bash
jq -r '.source.component' audit.log | sort | uniq -c | sort -rn
jq -c 'select(.source.component == "bash.pretooluse")' audit.log
jq -c 'select(.source.mode == "fail_open") | {component: .source.component, reason: .fail_open.reason, ts}' audit.log
لسهولة التحليل، اطلب من Claude إحصائيات الاستخدام بدلاً من تحليل السجلات يدويًا:```
"Show safer-dependencies stats for the last month"
يوفر هذا ملخصات قابلة للقراءة البشرية للنشاط، وتأثير الأمان، ومقاييس الأداء المستخرجة من سجلات التدقيق هذه.
أشكال الإدخال (المخطط 2.2). ثلاثة أشكال متميزة تتشارك نفس الترويسة ts / schema / source:
| الشكل | متى يتم كتابته | الحقول المميزة |
|---|---|---|
| إدخال التدقيق | تدقيق المانيفست / ملف القفل / تثبيت bash | file, ecosystem, checked, findings, abandoned, stale, typosquat, unknown, signatures, notes, clean |
| إدخال خطأ التثبيت | خطأ تثبيت preflight الخاص بـ Shim (المكوّن shim.install_error) | install_error, shim_dir, scripts_dir |
| إدخال الفتح عند الفشل | أي نقطة دخول للخطاف تخرج مبكرًا بسبب helper_missing / shim_missing / python_missing. يكون source.mode هو "fail_open" | fail_open: { reason, detail? } |
إدخالات التدقيق: وضع الاعتراض يشغّل خط الأنابيب الكامل (الأصل، عمر الإصدار، OSV، المهجور/القديم، typosquat، التوقيعات)، لذا يمكن أن تمتلئ جميع المصفوفات. وضع ما قبل التثبيت يشغّل OSV فقط حاليًا، لذا تكون abandoned / stale / typosquat / signatures فارغة دائمًا. إرسال ما بعد التثبيت (تدقيق ملف القفل) يكتب تحت shim.posttooluse مع تعبئة findings بسلاسل WARNING: من مدققي ملفات القفل. تحمل مصفوفة notes إشارات NOTE: إعلامية (مثل تخطي المانيفست بسبب عدم تثبيت الإصدار).
أضاف المخطط 2.2 — بشكل إضافي — أربعة حقول إلى إدخالات تدقيق ملف القفل: lockfile, manifest_ref, relation_summary (تصنيف مباشر/غير مباشر/غير معروف لكل حزمة مُعلَّمة مقابل المانيفست الشقيق)، وكتلة policy تسجّل مستوى transitive المعمول به. هذا التحديث متوافق مع الإصدارات السابقة: قرّاء إدخالات 2.1 يتحملون الحقول الجديدة، ويبقى حقل source.model حاضرًا من 2.1 فصاعدًا.```json
{
"ts": "2026-04-19T12:34:56Z",
"schema": "2.2",
"source": {
"component": "shim.posttooluse",
"script": "shim.sh",
"hook": "PostToolUse:Write",
"tool": "Write",
"mode": "intercept",
"model": "claude-sonnet-4-6"
},
"file": "/path/to/project/package.json",
"ecosystem": "npm",
"checked": ["[email protected]", "[email protected]"],
"findings": ["UPDATED: express 4.18.2 → 4.22.1 (HIGH: 1 CVE fixed)"],
"abandoned": [],
"stale": [],
"typosquat": [],
"unknown": [],
"signatures": [],
"notes": [],
"clean": ["[email protected]"]
}
Pre-Install Mode example (Bash hook, vulnerable pin denied):```json
{
"ts": "2026-04-23T06:56:21Z",
"schema": "2.2",
"source": {
"component": "bash.pretooluse",
"script": "pretooluse-bash.sh",
"hook": "PreToolUse:Bash",
"tool": "Bash",
"mode": "intercept",
"model": "claude-sonnet-4-6"
},
"file": "bash:npm install [email protected] [email protected]",
"ecosystem": "npm",
"checked": ["[email protected]", "[email protected]"],
"findings": [
"BLOCKED: [email protected] GHSA-35jh-r3h4-6jhm (CVSS:3.1/...): Command Injection in lodash"
],
"abandoned": [],
"stale": [],
"typosquat": [],
"unknown": [],
"signatures": [],
"notes": [],
"clean": ["[email protected]"]
}
وضع الفشل المفتوح (Fail-open Mode) مثال (خطاف Bash بعد التثبيت يُستدعى بدون وجود shim مجاور — تثبيت معطوب):```json { "ts": "2026-05-03T07:14:11Z", "schema": "2.2", "source": { "component": "bash.posttooluse", "script": "safer-dependencies-posttooluse-bash.sh", "hook": "PostToolUse", "tool": "Bash", "mode": "fail_open", "model": "claude-sonnet-4-6" }, "fail_open": { "reason": "shim_missing", "detail": "/home/alice/.claude/skills/safer-dependencies" } }
إدخال وضع الفشل المفتوح (fail-open) يعني: "هذا الخطاف (hook) تم تشغيله لكنه خرج مبكرًا دون تدقيق لأن شرطًا أساسيًا كان مفقودًا." استخدم مرشح jq أعلاه (`select(.source.mode == "fail_open")`) لإظهار كل حدث صامت لفقدان الحماية في سجلك.
عندما يعمل الشيم (shim) في وضع التشغيل التجريبي (`SAFE_DEP_DRY_RUN=1`)، تتضمن الإدخالات أيضًا `"mode": "dry_run"` بحيث يمكن للتحليل اللاحق تصفية الاستدعاءات المخصصة للتدقيق فقط.
## المتطلبات
- Python 3.9+ (تتحقق الخطافات من ذلك وتفشل مفتوحة على المفسرات الأقدم)
- `curl` (لاستدعاءات واجهة برمجة تطبيقات السجل (registry API) وفحوصات ثغرات OSV)
- أدوات النظام البيئي (اختيارية، تتراجع المهارة إلى واجهة OSV API إذا كانت مفقودة):
- `npm` لحزم npm
- `pip-audit` لحزم Python
- `bundle` لحزم Ruby
- `dependency-check` لحزم Java
## الأسئلة الشائعة
الأساس المنطقي لقرارات التصميم (لماذا `PostToolUse` بدلاً من `PreToolUse`، ولماذا لا يتم التحقق من التوقيعات، ولماذا يتم تكرار البرامج النصية والشيم، ومشاكل تحميل المهارات، وما إلى ذلك) موثق في [`FAQ.md`](https://github.com/robert-auger/safer-dependencies/blob/main/FAQ.md).