Le moteur qui ne sait que lire et répondre
Le moteur d'analyse ne fait que deux choses : lire le modèle et répondre sur localhost. Rien d'autre — et c'est le noyau du système d'exploitation qui l'impose, pas notre code.
Pourquoi ce composant est le plus enfermé
Quand PoisonZero analyse un changement on-device, le moteur est le composant qui lit le texte contrôlé par l'attaquant — le memory-diff même que quelqu'un a pu concevoir pour s'évader. Nous le traitons donc comme la surface la plus exposée du système et l'enfermons en conséquence : c'est le composant le plus enfermé que nous livrons. L'objectif de conception est net : un exploit du moteur doit devenir un plantage de processus sans conséquence, pas une tête de pont. Et si le moteur plante, le daemon ne hausse pas les épaules : il annule le changement suspect (fail-closed).
Notez la séparation volontaire. Le daemon tourne privilégié à dessein — en tant que service root (LaunchDaemon / systemd) —, parce qu'il doit surveiller des fichiers de memory qui ne lui appartiennent pas et les annuler sur place ; ce travail est impossible sans privilèges. Le moteur, c'est l'exact opposé : il ne touche à rien de ce que le daemon protège, il ne lit que l'entrée suspecte, et il est donc réduit à presque rien. Cette asymétrie est l'architecture : le composant le plus exposé est le plus enfermé, et le casser n'atteint pas le daemon privilégié.
macOS : la sandbox du noyau
Sous macOS, le moteur s'exécute dans la sandbox du noyau (Seatbelt / sandbox-exec) avec un profil deny-by-default : tout est interdit sauf autorisation explicite. Le profil voyage avec le daemon et réside comme un fichier auditable à côté du modèle — vous pouvez lire exactement ce que le moteur a le droit de faire. Si le service tourne en root, le moteur lui-même retombe sur un utilisateur non privilégié (nobody).
Vérifié en conditions réelles sur Apple Silicon — et la sandbox ne coûte aucune latence mesurable : une évaluation à chaud tourne en environ 1,1 seconde dans tous les cas.
Linux : Landlock, imposé par le noyau
Sous Linux, la cage est Landlock, un module de sécurité du noyau (LSM), de nouveau deny-by-default. Le moteur peut :
- lire uniquement le fichier du modèle — rien d'autre sur le disque ;
- exécuter uniquement son propre binaire — il ne peut lancer aucun autre programme ;
- se lier au seul port local sur lequel il répond — et à aucun autre.
Les connexions sortantes sont refusées par le noyau avec « permission denied » — avant qu'un seul octet ne quitte le système. Ce n'est pas une promesse dans notre code ; c'est prouvé sur un vrai noyau en CI à chaque build. Aucune écriture sur le disque, aucun lancement de programme tiers, aucun egress réseau.
« Lire uniquement le fichier du modèle » n'est vrai que si le moteur n'a réellement besoin de rien d'autre sur le disque. C'est pourquoi le moteur Linux est compilé entièrement statiquement contre musl — sans chargeur dynamique, sans libc partagée — sur les deux architectures (amd64 et arm64). Un binaire lié normalement devrait lire et exécuter /lib64/ld-linux et la libc système au démarrage, forçant ces chemins dans l'allowlist ; le moteur statique lit exactement un fichier et exécute exactement un binaire, lui-même.
Windows : jeton restreint + Job Object
Sous Windows, le moteur tourne sous un jeton restreint avec un Job Object du noyau — et c'est en production et vérifié, fail-closed exactement comme macOS et Linux. Le jeton est créé de sorte que tous les privilèges sont retirés (seul subsiste l'inoffensif privilège « notifier au changement »), et le processus tourne en intégrité basse (low integrity), donc il ne peut écrire d'objets à intégrité normale. Le Job Object laisse le moteur exécuter exactement un processus — il ne peut engendrer aucun enfant, le noyau le bloque — et plafonne sa mémoire. Il se lie toujours à localhost uniquement, sans connexion sortante.
Vérifié en conditions réelles sur GitHub Actions windows-latest : le lancement de processus enfants est bloqué par le noyau, et le vrai moteur Windows charge et évalue correctement sous les contraintes de jeton et de Job. (Une étape encore plus stricte avec AppContainer est sur la feuille de route ; le profil actuel est déjà livré, en production et fail-closed.)
Strictement fail-closed : pas de sandbox, pas d'analyse
Sur toutes les plateformes, la règle est la même et elle est stricte : si la sandbox n'est pas disponible, le moteur ne démarre pas. Il n'y a pas de dégradation silencieuse vers une exécution sans sandbox. À la place, les changements suspects sont annulés plutôt que laissés passer sans évaluation. L'analyse on-device sans la cage du noyau n'a tout simplement pas lieu.
C'est une limite honnête — et c'est tout l'intérêt. « Fail-closed » signifie : sans Landlock (ou Seatbelt), il n'y a pas d'analyse on-device sur cet hôte. Nous préférons vous protéger en annulant plutôt que d'exposer le composant le plus exposé à l'attaquant sans sa cage. La limite est la fonctionnalité.
Ce qu'il demande à vos machines
macOS : rien de particulier — la sandbox du noyau est toujours présente.
Linux : un noyau ≥ 5.13 avec Landlock actif. Cela couvre Ubuntu ≥ 22.04, Debian ≥ 12 et RHEL ≥ 9.6 d'origine ; sur d'autres distributions, vous l'activez avec le paramètre de démarrage lsm=landlock,…. Dans les conteneurs, le profil seccomp par défaut de Docker bloque les appels système Landlock — il faut alors un profil adapté.
Windows : rien de particulier — le jeton restreint et le Job Object sont des fonctions standard du noyau.
Pour les environnements où Landlock ne peut être activé, il existe une alternative opt-in : l'évaluation dans le cloud comme filet de sécurité distant. La protection reste en place ; le flux de données est documenté de façon transparente plutôt que caché.
En bref
- Lire le modèle, répondre sur localhost — rien d'autre, imposé par le noyau du système d'exploitation.
- Un exploit du moteur devient un plantage de processus ; le daemon annule fail-closed.
- Pas de sandbox → le moteur ne démarre pas → les changements suspects sont annulés, jamais laissés passer.
La conception complète, y compris le contrat d'egress vérifiable, figure dans le livre blanc technique. À lire aussi : Pourquoi le fail-closed l'emporte et Memory Poisoning.
Une analyse qu'on ne peut retourner contre vous.
PoisonZero exécute le moteur on-device dans une cage imposée par le noyau — lire le modèle, répondre sur localhost, rien d'autre.
Sign me upÀ lire aussi : Pourquoi le Fail-closed l'emporte · Qu'est-ce que le Memory Poisoning ? · Claude, MCP & tool poisoning