
Serveur MCP pour l'orchestration de la remédiation des CVE et des configurations : inventaire SSH, recherches OSV/NVD, suggestions de playbooks Ansible mappés CIS/DISA STIG.
Consultez OVERVIEW.md pour une description de haut niveau de l'objectif, des composants et de la portée du dépôt avant d'apporter des modifications de comportement.
Un orchestrateur de remédiation, exposé sous forme de serveur MCP. Connectez un client MCP (Claude Desktop, Claude Code ou similaire) et soumettez une requête en langage naturel, par exemple :
Connectez-vous à l'hôte a.b.c, vérifiez les paquets installés, trouvez les CVE et suggérez un correctif - Ansible si possible, et indiquez-moi à quels contrôles de conformité cela correspond.
prescryb fournit les primitives (inventaire SSH, correspondance des CVE, recherches d'avis en direct, mappage des thématiques de conformité, rendu de playbooks Ansible). Le modèle connecté effectue le raisonnement : quels résultats comptent, quelles CVE approfondir, quel playbook générer. prescryb n'applique jamais rien sur l'hôte cible - chaque outil est en lecture seule vis-à-vis de celui-ci, ou relève de la pure génération de texte/données.
| Outil | Ce qu'il fait |
|---|---|
inventory_host(host, user="", port=22, hostname="", identity_file="", trust_unknown_host=False) | Se connecte en SSH, détecte la distribution, liste les paquets installés avec leurs versions. |
check_cves(system, packages) | Met en correspondance par lots les versions des paquets avec OSV.dev en utilisant sa comparaison de versions tenant compte des écosystèmes (et non une correspondance par nom uniquement). Chaque correspondance est enrichie d'un score de probabilité d'exploitation EPSS. |
fetch_advisory(cve_id) | Récupère l'enregistrement NVD actuel d'une CVE - description, CVSS, CWE, références - en direct, et non à partir des données d'entraînement. |
fetch_epss(cve_ids) | Récupère par lots les scores de probabilité d'exploitation EPSS pour les identifiants CVE non déjà couverts par check_cves (par exemple issus de fetch_advisory ou d'une recherche web). |
map_compliance(area) | Associe un sujet en texte libre ("ssh", "sudo", "kernel modules", ...) aux domaines thématiques CIS/DISA STIG et, s'il est présent dans le dépôt GitHub konstruktoid.hardening, au rôle correspondant - ainsi qu'aux techniques et mesures d'atténuation MITRE ATT&CK que ce domaine traite. |
lookup_cce(target, keyword, cce_id) | Recherche les entrées NIST CCE (Common Configuration Enumeration) pour une plateforme (par exemple "rhel8"), issues de la conversion JSON communautaire disponible sur konstruktoid/cce-web. |
list_cce_targets() | Liste toutes les plateformes que lookup_cce peut interroger. |
list_local_docs() | Liste les documents (Markdown/texte/PDF) trouvés sous le répertoire local LOCAL_DOCS_DIR (ignoré par git). |
search_local_docs(query, top_k=5) | Recherche sémantique de type RAG sur ces documents locaux, entièrement embarquée sur la machine. |
generate_playbook(system, cve_matches, compliance_areas, hosts_alias) | Génère un playbook Ansible en mode suggestion uniquement : les correctifs de CVE deviennent des tâches de mise à niveau de paquets, les domaines de conformité deviennent des références roles:. |
Flux typique : inventory_host, puis check_cves sur les paquets retournés, puis éventuellement fetch_advisory sur les CVE intéressantes, puis map_compliance (et lookup_cce) pour tout domaine de configuration non sécurisée repéré, puis éventuellement search_local_docs pour le contexte interne pertinent de runbook/politique, puis generate_playbook pour produire quelque chose à examiner.
flowchart TD
U["Operator: natural-language request"] --> M["Connected model\n(Claude Desktop / Claude Code)"]
M --> A["inventory_host\nSSH in, list packages"]
A --> B["check_cves\nOSV.dev match + EPSS score"]
B --> C{"Interesting\nCVE?"}
C -->|yes| D["fetch_advisory\nNVD detail for one CVE"]
C -->|no| E
D --> E["map_compliance / lookup_cce\nCIS/DISA STIG + ATT&CK mapping"]
E --> F["search_local_docs\ninternal runbooks (optional)"]
F --> G["generate_playbook\nsuggest-only Ansible playbook"]
G --> H["Model reasons over the results\nand presents findings + playbook"]
H --> R["Operator reviews\n(ansible-playbook --check --diff)\nand applies manually"]
style R fill:#f9f,stroke:#333,stroke-width:1px
Seules les boîtes à outils sont prescryb : inventory_host, check_cves,
fetch_advisory, map_compliance/lookup_cce, search_local_docs, et
generate_playbook - chacune étant un appel de recherche en lecture seule ou de génération pure de texte/données.
L'opérateur et le modèle connecté ne font pas partie de prescryb, et
rien dans cette chaîne ne touche l'hôte cible au-delà de la session SSH en lecture seule de inventory_host - l'application du playbook généré est une étape délibérée et
distincte que l'opérateur effectue en dehors de prescryb.
uv sync
Claude Code :
claude mcp add prescryb -- uv --directory /path/to/prescryb run prescryb
Claude Desktop (claude_desktop_config.json) :
{
"mcpServers": {
"prescryb": {
"command": "uv",
"args": ["--directory", "/path/to/prescryb", "run", "prescryb"]
}
}
}
inventory_host n'accepte jamais d'argument mot de passe. Les arguments des appels d'outils MCP peuvent être journalisés par les clients et sont visibles par le modèle connecté, les identifiants ne doivent donc jamais transiter par eux. L'authentification fonctionne exactement comme lorsque vous exécutez ssh host vous-même :
~/.ssh/config.hostname/identity_file de inventory_host remplacent directement l'adresse/le chemin de clé résolu, pour les hôtes que vous ne souhaitez pas ajouter à ~/.ssh/config (seul un chemin est transmis, jamais le contenu de la clé).trust_unknown_host=True
ssh host manuellement une fois pour épingler la clé.qemu/vm.sh démarre une image cloud (almalinux10, trixie, resolute) sous
QEMU avec une graine cloud-init et une redirection de port SSH sur 127.0.0.1
(2201, 2202, 2203). Il nécessite qemu-system-x86_64, qemu-img, cloud-localds
(cloud-image-utils), curl et ssh ; KVM est utilisé lorsque /dev/kvm est accessible en écriture.
Les images sont vérifiées par somme de contrôle et mises en cache dans qemu/.state/.
qemu/vm.sh up trixie
qemu/vm.sh ssh trixie true # retry until the guest answers
claude 'inventory 127.0.0.1 port 2202 user prescryb with identity file
qemu/.state/id_ed25519 (trust_unknown_host is fine, it is a throwaway VM),
check any vulnerabilities and suggest a fix, include compliance mapping if
possible, write the playbook suggestion to /tmp/ and print the file location'
qemu/vm.sh destroy trixie
Pour un hôte déjà accessible via ssh (résolu via ~/.ssh/config,
une clé d'agent, ou le fichier d'identité par défaut), spécifiez directement
le nom d'hôte ; aucune configuration de port ou de fichier d'identité n'est
nécessaire :
Inventorie prod-web-01, vérifie les paquets installés, trouve les CVE et suggère un correctif - Ansible si possible, et indique-moi à quels contrôles de conformité cela correspond.