
مراقب أمان سلسلة التوريد الآلي الذي يستطلع سجلات PyPI و npm، ويقارن الإصدارات الجديدة مع سابقاتها، ويستخدم تحليلات LLM لاكتشاف تغييرات الكود الضارة مع تنبيهات Slack.
مراقبة آلية لأفضل حزم PyPI و npm للكشف عن اختراقات سلسلة التوريد. يقوم باستقصاء كلا السجلين للإصدارات الجديدة، ويقارن كل إصدار بسابقه، ويستخدم نموذج لغة كبير (عبر Cursor Agent CLI) لتصنيف الفروقات على أنها حميدة أو ضارة. تؤدي النتائج الضارة إلى إطلاق تنبيه عبر Slack.
يتم مراقبة كلا النظامين البيئيين افتراضيًا. استخدم --no-pypi أو --no-npm لتعطيل أحدهما.
كل نظام بيئي يشغل خيط استقصاء خاص به، لكنه يشارك في خط التحليل والتنبيه.
┌─── PyPI ──────────────────────┐ ┌─── npm ───────────────────────┐
│ │ │ │
│ changelog_since_serial() │ │ CouchDB _changes feed │
│ │ │ │ │ │
│ ▼ │ │ ▼ │
│ ┌────────────┐ │ │ ┌────────────┐ │
│ │ All PyPI │─┐ │ │ │ All npm │─┐ │
│ │ events │ │ │ │ │ changes │ │ │
│ └────────────┘ ▼ │ │ └────────────┘ ▼ │
│ hugovk ──► Watchlist │ │ download-counts ─► Watchlist │
│ │ │ │ │ │
│ "new release" events only │ │ new versions since last epoch │
└───────────────┬───────────────┘ └───────────────┬───────────────┘
│ │
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ Download old + new│ │ Download old + new│
│ (sdist + wheel) │ │ (tarball) │
└───────────────────┘ └───────────────────┘
│ │
└─────────────────┬─────────────────┘
▼
┌───────────────┐
│ Unified diff │
│ report (.md) │
└───────┬───────┘
▼
┌───────────────┐ ◄── LLM analysis
│ Cursor Agent │ (read-only)
│ CLI (ask mode)│
└───────┬───────┘
│
verdict?
│
malicious │
▼
┌───────────────┐
│ Slack alert │
└───────────────┘
يتم توجيه تحليل LLM للبحث عن:
pip install -r requirements.txt (تغطي المكتبة القياسية معظم الأداة؛ requests تُستخدم لرفع الملفات إلى Slack)agent، وليس IDEويندوز (PowerShell):
irm 'https://cursor.com/install?win32=true' | iex
macOS / Linux:
curl https://cursor.com/install -fsS | bash
تحقق من التثبيت باستخدام:
agent --version
يجب أن تكون مصادقًا لدى Cursor (agent login أو قم بتعيين CURSOR_API_KEY).
ضع رمز bot الخاص بـ Slack في etc/slack.json:
{
"url": "https://hooks.slack.com/services/...",
"bot_token": "xoxb-...",
"channel": "C01XXXXXXXX"
}
يحتاج bot إلى نطاق chat:write على القناة المستهدفة. حقل channel هو معرف قناة Slack حيث تُنشر التنبيهات.
# تشغيل لمرة واحدة: تحليل الإصدارات من آخر 10 دقائق تقريبًا
python monitor.py --once
# تشغيل مستمر: مراقبة أفضل 1000 حزمة (كلا النظامين البيئيين)، استقصاء كل 5 دقائق
python monitor.py --top 1000 --interval 300
# إنتاجي: مراقبة أفضل 15000، تنبيه إلى Slack
python monitor.py --top 15000 --interval 300 --slack
# npm فقط، أفضل 5000
python monitor.py --no-pypi --npm-top 5000
# PyPI فقط
python monitor.py --no-npm
python monitor.py [OPTIONS]
الخيارات:
--top N عدد أفضل الحزم المراقبة لكل نظام بيئي (الافتراضي: 15000)
--interval SECS فترة الاستقصاء بالثواني (الافتراضي: 300)
--once تشغيل لمرة واحدة على الأحداث الأخيرة، ثم الخروج
--slack تفعيل تنبيهات Slack للنتائج الضارة
--model MODEL تجاوز نموذج LLM (الافتراضي: composer-2-fast)
--debug تفعيل تسجيل DEBUG (يشمل المخرجات الأولية للوكيل)
خيارات PyPI:
--no-pypi تعطيل مراقبة PyPI
--serial N تسلسل سجل PyPI للبدء منه
خيارات npm:
--no-npm تعطيل مراقبة npm
--npm-top N أفضل N من حزم npm للمراقبة (الافتراضي: نفس --top)
--npm-seq N تسلسل تكرار npm للبدء منه
يعمل كل من PyPI و npm في خيط استقصاء خاص به. يتم حفظ حالة الاستقصاء (تسلسل PyPI، تسلسل + عصر npm) في last_serial.yaml حتى يستأنف المراقب من حيث توقف بعد إعادة التشغيل.
خط أنابيب PyPI:
--interval ثانية، يستدعي changelog_since_serial() — استدعاء API واحد يعيد جميع الأحداث منذ آخر فحص"new release" المطابقة لقائمة المراقبةخط أنابيب npm:
replicate.npmjs.com--interval ثانية، يجلب خلاصة _changes لجميع تغييرات السجل منذ آخر تسلسليتم تسجيل جميع المخرجات في كل من وحدة التحكم و logs/monitor_YYYYMMDD.log.
# مقارنة نسختين من PyPI
python package_diff.py requests 2.31.0 2.32.0
# مقارنة نسختين من npm
python package_diff.py --npm express 4.18.2 4.19.0
# حفظ في ملف
python package_diff.py telnyx 2.0.0 2.1.0 -o telnyx_diff.md
# مقارنة أرشيفات محلية
python package_diff.py --local old.tar.gz new.tar.gz -n mypackage
يتم التنزيل مباشرة عبر واجهات API للسجل (PyPI JSON API / npm registry)، وليس عبر pip أو npm. هذا يعني:
# تحليل ملف الفرق
python analyze_diff.py telnyx_diff.md
# إخراج JSON
python analyze_diff.py telnyx_diff.md --json
# استخدام نموذج محدد
python analyze_diff.py telnyx_diff.md --model claude-4-opus
يشغل Cursor Agent CLI في وضع --mode ask (للقراءة فقط) مع --trust. يقرأ الوكيل ملف الفرق ويعيد حكمًا منظمًا.
رموز الخروج: 0 = حميد، 1 = ضار، 2 = غير معروف/خطأ.
# رؤية ما يُنشر الآن (آخر 10 دقائق تقريبًا)
python pypi_monitor.py --once --top 15000
# مراقبة مستمرة (مخرجات وحدة التحكم فقط، بدون تحليل)
python pypi_monitor.py --top 1000 --interval 120
مفيد لاستكشاف سرعة إصدار PyPI أو تصحيح واجهة سجل التغييرات دون تشغيل خط التحليل الكامل.
# طباعة أفضل 1000 حزمة
python top_pypi_packages.py
# استخدام كمكتبة
from top_pypi_packages import fetch_top_packages
packages = fetch_top_packages(top_n=500)
# [{"project": "boto3", "download_count": 1577565199}, ...]
يقوم المراقب بـ استدعاء API واحد لكل فترة استقصاء ولكل نظام بيئي (سجل PyPI / npm _changes)، بالإضافة إلى 2-3 استدعاءات لكل إصدار جديد (تاريخ الإصدار + التحميلات). هذا خفيف جدًا.
عندما يكتشف المراقب إصدارًا ضارًا، ينشر في Slack:
PyPI:
🚨 تنبيه سلسلة التوريد: telnyx 4.87.2
الرتبة: #5,481 من أفضل حزم PyPI
الحكم: ضار
PyPI: https://pypi.org/project/telnyx/4.87.2/
ملخص التحليل (مبتور):
التغييرات في src/telnyx/_client.py تنفذ سلوك تنزيل-فك-تشغيل
مبهم وآثار جانبية لاستيراد الوحدات. دالة _d() تفك ترميز
سلاسل base64، كتلة _p ضخمة تحتوي على سكريبت سرقة
يقوم بتنزيل ملف .wav من
http://83.142.209.203:8080/ringtone.wav ويستخرج حمولة
مخفية عبر إخفاء المعلومات...
npm:
🚨 تنبيه سلسلة التوريد: axios 0.30.4
الرتبة: #42 من أفضل حزم npm
الحكم: ضار
npm: https://www.npmjs.com/package/axios/v/0.30.4
ملخص التحليل (مبتور):
1. **تبعية غير قياسية** — كتلة `dependencies` تتضمن `plain-crypto-js`. إصدارات axios المنشورة تعتمد فقط على `follow-redirects` و`form-data` و`proxy-from-env`. حزمة رابعة اسمها يبدو كأنه **انتحال أسلوب crypto-js** هو علامة كلاسيكية على حزمة معدلة أو مزيفة، وليس إصدار axios عادي.
agent CLI.ask للقراءة فقط ولكن بدون عزل على مستوى نظام التشغيل.تُكتب السجلات إلى كل من stdout و logs/monitor_YYYYMMDD.log. يتم إنشاء ملف جديد كل يوم. يسجل كلا النظامين البيئيين في نفس الملف، مع بادئة [npm] لسطور npm. مثال:
2026-03-27 12:01:15 [INFO] جلب أفضل 15,000 حزمة من مجموعة hugovk...
2026-03-27 12:01:16 [INFO] تم تحميل قائمة المراقبة: 15,000 حزمة (آخر تحديث للمجموعة 2026-03-01 07:34:08)
2026-03-27 12:01:16 [INFO] جلب أفضل 15,000 حزمة npm من مجموعة download-counts...
2026-03-27 12:01:18 [INFO] تم تحميل قائمة مراقبة npm: 15,000 حزمة (download-counts 1.0.52)
2026-03-27 12:01:19 [INFO] [pypi] بدء التسلسل: 35,542,068 (من last_serial.yaml) — استقصاء كل 300 ثانية
2026-03-27 12:01:19 [INFO] [npm] بدء التسلسل: 42,817,503 (من last_serial.yaml) — استقصاء كل 300 ثانية
2026-03-27 12:06:18 [INFO] [pypi] تم الكشف عن إصدارين جديدين في قائمة المراقبة (تسلسل 35,542,068 -> 35,542,190)
2026-03-27 12:06:18 [INFO] [pypi] معالجة fast-array-utils 1.4 (الرتبة #8,231)...
2026-03-27 12:06:18 [INFO] [pypi] مقارنة fast-array-utils 1.3 -> 1.4
2026-03-27 12:06:50 [INFO] [pypi] تحليل الفرق لـ fast-array-utils...
2026-03-27 12:07:35 [INFO] [pypi] الحكم لـ fast-array-utils 1.4: حميد
2026-03-27 12:06:20 [INFO] [npm] تم الكشف عن إصدار جديد واحد في قائمة المراقبة (تسلسل -> 42,817,612)
2026-03-27 12:06:20 [INFO] [npm] معالجة axios 0.30.4 (الرتبة #42)...
2026-03-27 12:06:21 [INFO] [npm] مقارنة axios 0.30.3 -> 0.30.4
2026-03-27 12:07:01 [INFO] [npm] تحليل الفرق لـ axios...
2026-03-27 12:07:45 [INFO] [npm] الحكم لـ axios 0.30.4: ضار
هذا المشروع مرخص بموجب رخصة MIT. مصادر البيانات والإشعارات من طرف ثالث ملخصة في NOTICE.txt.
المساهمات مرحب بها — راجع CONTRIBUTING.md. يتبع هذا المستودع ميثاق المساهم. أبلغ عن المشكلات الأمنية عبر SECURITY.md، وليس عبر المشكلات العامة.
الأسئلة والنقاش: مجتمع Elastic Slack.
| الملف | الغرض |
|---|
monitor.py | المنسق الرئيسي — استقصاء PyPI + npm، مقارنة، تحليل، تنبيه (خيوط متوازية) |
pypi_monitor.py | مستقصي سجل تغييرات PyPI المستقل (يُستخدم للاستكشاف) |
package_diff.py | تنزيل ومقارنة نسختين من أي حزمة PyPI أو npm |
analyze_diff.py | إرسال الفرق إلى Cursor Agent CLI، تحليل الحكم |
top_pypi_packages.py | جلب وعرض أفضل N من حزم PyPI حسب عدد التحميلات |
slack.py | عميل API Slack (إرسال رسالة، رفع ملف) |
etc/slack.json | بيانات اعتماد Bot Slack |
last_serial.yaml | حالة الاستقصاء المحفوظة (تسلسل PyPI + تسلسل/عصر npm) |
logs/ | ملفات سجل يومية (monitor_YYYYMMDD.log) |
| المصدر | ماذا | حدود المعدل |
|---|
| hugovk/top-pypi-packages | أفضل 15,000 حزمة PyPI حسب التحميلات في 30 يومًا (JSON شهري) | لا توجد (ملف ثابت) |
PyPI XML-RPC changelog_since_serial() | تيار أحداث PyPI في الوقت الفعلي | متهالك ولكنه يعمل؛ استدعاء واحد لكل استقصاء كافٍ |
| PyPI JSON API | بيانات الحزمة، تاريخ الإصدار، روابط التحميل | سخي؛ يُستخدم بشكل محدود (استدعاء واحد لكل إصدار) |
| download-counts (nice-registry) | إحصائيات التحميل الشهرية لكل حزمة npm (counts.json) | لا توجد (tarball npm) |
npm CouchDB replication _changes feed | تيار تغييرات سجل npm في الوقت الفعلي | عام؛ قراءات مقسمة إلى صفحات |
| npm registry API | مستندات الحزمة، تحميلات tarball | سخي؛ يُستخدم بشكل محدود |