
Moniteur automatisé de sécurité des chaînes d'approvisionnement qui interroge les registres PyPI et npm, compare les nouvelles versions avec leurs prédécesseurs, et utilise l'analyse LLM pour détecter les modifications malveillantes de code avec alertes Slack.
Surveillance automatisée des principaux paquets PyPI et npm pour détecter les compromissions de la chaîne d'approvisionnement. Interroge les deux registres pour les nouvelles versions, effectue un diff de chaque version par rapport à la précédente, et utilise un LLM (via Cursor Agent CLI) pour classer les diffs comme bénins ou malveillants. Les découvertes malveillantes déclenchent une alerte Slack.
Les deux écosystèmes sont surveillés par défaut. Utilisez --no-pypi ou --no-npm pour en désactiver un.
Chaque écosystème exécute son propre thread d'interrogation mais partage le pipeline d'analyse et d'alertes.
┌─── 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 │
└───────────────┘
L'analyse par LLM est instruite de rechercher :
pip install -r requirements.txt (la bibliothèque standard couvre la plupart de l'outil ; requests est utilisé pour les téléversements Slack)agent, pas l'IDEWindows (PowerShell) :
irm 'https://cursor.com/install?win32=true' | iex
macOS / Linux :
curl https://cursor.com/install -fsS | bash
Vérifiez avec :
agent --version
Vous devez être authentifié auprès de Cursor (agent login ou définir CURSOR_API_KEY).
Placez votre jeton de bot Slack dans etc/slack.json :
{
"url": "https://hooks.slack.com/services/...",
"bot_token": "xoxb-...",
"channel": "C01XXXXXXXX"
}
Le bot a besoin de la portée chat:write sur le canal cible. Le champ channel est l'ID du canal Slack où les alertes sont postées.
# One-shot: analyze releases from the last ~10 minutes
python monitor.py --once
# Continuous: monitor top 1000 packages (both ecosystems), poll every 5 min
python monitor.py --top 1000 --interval 300
# Production: monitor top 15000, alert to Slack
python monitor.py --top 15000 --interval 300 --slack
# npm only, top 5000
python monitor.py --no-pypi --npm-top 5000
# PyPI only
python monitor.py --no-npm
| Fichier | Objectif |
|---|---|
monitor.py | Orchestrateur principal — interroge PyPI + npm, diff, analyse, alerte (threads parallèles) |
pypi_monitor.py | Interrogateur de changelog PyPI autonome (utilisé pour l'exploration) |
package_diff.py | Télécharge et diff deux versions de n'importe quel paquet PyPI ou npm |
analyze_diff.py | Envoie un diff à Cursor Agent CLI, analyse le verdict |
top_pypi_packages.py | Récupère et liste les N meilleurs paquets PyPI par nombre de téléchargements |
slack.py | Client API Slack (SendMessage, PostFile) |
etc/slack.json | Identifiants du bot Slack |
last_serial.yaml | État d'interrogation persistant (série PyPI + séquence/époque npm) |
logs/ | Fichiers journaux quotidiens (monitor_YYYYMMDD.log) |
python monitor.py [OPTIONS]
Options :
--top N Nombre de paquets les plus populaires à surveiller par écosystème (défaut : 15000)
--interval SECS Intervalle d'interrogation en secondes (défaut : 300)
--once Passe unique sur les événements récents, puis quitte
--slack Active les alertes Slack pour les découvertes malveillantes
--model MODEL Remplace le modèle LLM (défaut : composer-2-fast)
--debug Active la journalisation DEBUG (inclut la sortie brute de l'agent)
Options PyPI :
--no-pypi Désactive la surveillance PyPI
--serial N Série du changelog PyPI à partir de laquelle commencer
Options npm :
--no-npm Désactive la surveillance npm
--npm-top N Les N meilleurs paquets npm à surveiller (défaut : identique à --top)
--npm-seq N Séquence de réplication npm à partir de laquelle commencer
PyPI et npm s'exécutent chacun dans leur propre thread d'interrogation. L'état d'interrogation (série PyPI, séquence npm + époque) est persistant dans last_serial.yaml afin que le moniteur reprenne là où il s'est arrêté après un redémarrage.
Pipeline PyPI :
--interval secondes, appelle changelog_since_serial() — un seul appel API qui renvoie tous les événements depuis la dernière vérification"new release" correspondant à la liste de surveillancePipeline npm :