Sécuriser pi de l’intérieur : Guards, Scanners et Audit avec pi-secured-setup
Il y a quelques jours, je présentais Greywall — un sandbox kernel-level qui contient pi grâce à une approche deny-by-default. C’est votre mur extérieur. Mais qu’en est-il des menaces à l’intérieur de la frontière ? L’agent qui écrit accidentellement dans le mauvais projet, le fichier .env qui se retrouve dans le contexte LLM, le skill dont le SKILL.md a été silencieusement modifié. C’est un problème différent, qui nécessite un outil différent.
Aujourd’hui je publie pi-secured-setup — une extension pi qui ajoute des Guards, des Scanners et un audit trail directement dans l’agent. Pas de modules kernel, pas de conteneurs, pas de dépendances externes. Un simple pi install et vous êtes protégé.
Modèle de menaces — que protège-t-on concrètement ?
pi-secured-setup n’est pas conçu pour arrêter un attaquant déterminé. C’est le boulot de Greywall. Il cible cinq scénarios réalistes que tout utilisateur de pi rencontrera tôt ou tard :
| Menace | Exemple | Sévérité |
|---|---|---|
| Dommages accidentels inter-projets | write vers /home/user/autre-projet/file.ts | Élevée |
| Exposition de fichiers sensibles | L’agent lit votre .env et son contenu atteint le contexte LLM | Élevée |
| Commandes destructrices | rm -rf /, sudo, git push --force | Élevée |
| Chaîne d’approvisionnement (skills) | Un SKILL.md de skill est modifié pour injecter des instructions malveillantes | Moyenne |
| Exfiltration de données | Commandes curl ou aws envoyant des données à l’extérieur | Moyenne |
| Aucune traçabilité | Quelque chose a planté, mais vous ne savez pas quoi | Moyenne |
Chacun de ces scénarios m’est arrivé. Le dernier est le plus sournois — sans audit trail, vous ne pouvez même pas diagnostiquer le problème.
Architecture — trois couches, une extension
pi-secured-setup est une seule extension pi avec trois couches distinctes :
Guards — évaluent les appels d’outils avant l’exécution et peuvent les bloquer ou demander confirmation. Ils s’exécutent dans un pipeline fixe avec un handler unique combiné — pas de doubles dialogues, pas de race conditions.
Scanners — observent les données sans bloquer. Ils détectent les secrets dans le payload provider et vérifient l’intégrité des skills. Ils ne bloquent jamais l’exécution d’un outil.
Audit — enregistre tout dans un fichier JSONL en append-only avec rotation automatique.
La décision de conception clé : Guards et Scanners sont séparés par intention. Les Guards peuvent bloquer. Les Scanners peuvent seulement observer et rapporter. Ça signifie que le scanner de secrets ne bloquera jamais accidentellement votre workflow — il rédacte silencieusement et vous notifie a posteriori.
Le pipeline de Guards
Les trois modules Guard (boundary, protected paths, bash gate) sont évalués par un handler tool_call unique dans un ordre fixe :
boundary → protected-paths → bash-gate
Le premier bloc gagne. Si boundary bloque une écriture, protected paths et bash gate ne s’exécutent pas. Si boundary autorise, protected paths prend la main. Si les deux autorisent et que l’outil est bash, la commande est classifiée. Un verdict par appel d’outil, une entrée d’audit.
Guards en action — ce qui est bloqué
Application de la frontière (Boundary)
La frontière est votre répertoire projet (cwd). Les opérations fichiers via read, write et edit sont vérifiées par rapport à cette frontière. Bash est explicitement exclu — on ne peut pas extraire fiablement des chemins d’une commande shell arbitraire.
| Situation | Outil | Verdict |
|---|---|---|
| Écriture dans le projet | write, edit | ✅ Autorisé |
| Lecture dans le projet | read | ✅ Autorisé |
| Écriture hors projet | write, edit | 🚫 Bloqué |
| Lecture hors projet | read | ⚠️ Confirmation |
| Lecture/écriture sur chemin externe autorisé | any | ✅ Autorisé |
| Toute commande bash | bash | ✅ Autorisé (géré par bash gate) |
La liste allowed-external permet de whitelist des chemins comme ~/.agents/skills ou /tmp qui sont hors projet mais nécessaires au fonctionnement normal.
Chemins protégés (Protected Paths)
Même à l’intérieur de la frontière, certains fichiers méritent une protection supplémentaire. Les chemins protégés utilisent des patterns glob comparés au fichier cible :
.env, .env.*, *.key, *.pem, id_rsa*, *secret*, *credential* ...
Write ou edit vers un chemin protégé → blocage. Read depuis un chemin protégé → confirmation (configurable en allow ou block). Les patterns sont entièrement configurables par projet.
Bash Gate
Chaque commande bash est classifiée dans l’une des quatre catégories selon des règles regex :
| Catégorie | Exemples | Verdict |
|---|---|---|
| SAFE | ls, cat, grep, git status | ✅ Auto-approuvé |
| MODERATE | npm install, mkdir, git commit | ✅ Auto-approuvé (loggé) |
| DANGEROUS | rm -rf, sudo, eval, dd if= | ⚠️ Confirmation |
| EXTERNAL | curl, ssh, aws, gcloud | ⚠️ Confirmation |
| Inconnue | tout ce qui ne matche pas | ⚠️ Confirmation |
Les pipes sont gérés correctement : cat file | rm -rf / est classifié DANGEROUS car le pipeline prend le composant le plus dangereux. Les sous-shells comme $(whoami) sont extraits et classifiés indépendamment.
Voici ce que donne le dialogue de confirmation en pratique :
🔒 Bash Command
⚠️ Dangerous command — allow execution?
rm -rf node_modules
Classification: DANGEROUS
Scanners — secrets et skills
Scanner de secrets
Le scanner de secrets s’exécute sur before_provider_request — il voit le payload exact sur le point d’être envoyé au LLM, avant qu’il ne quitte votre machine. Il parcourt récursivement chaque chaîne de caractères du payload (provider-agnostic — fonctionne avec Anthropic, OpenAI, Google, n’importe quel provider) et la compare à plus de 15 patterns :
- Clés d’accès AWS (
AKIA...), clés secrètes AWS - Clés API Anthropic, OpenAI, Gemini
- En-têtes de clés privées (
-----BEGIN RSA PRIVATE KEY-----) - Clés API génériques, bearer tokens, mots de passe
- Chaînes de connexion base de données (
postgres://,mongodb://,redis://) - Tokens GitHub (
ghp_,ghs_), tokens Slack, tokens Discord - Détection d’entropie élevée en fallback
Quand un secret est trouvé, il est remplacé par ***REDACTED:{pattern-name}***. L’agent conserve le type de secret sans la valeur, ce qui lui permet de raisonner sur votre configuration.
DATABASE_URL=postgres://user:supersecret@db.example.com:5432/prod
devient :
DATABASE_URL=***REDACTED:db-connection***
Pourquoi scanner uniquement la requête et pas la réponse ? Si les secrets sont rédactés avant d’atteindre le modèle, le modèle ne peut jamais les répéter dans une réponse. La rédaction côté input est suffisante.
La mitigation des faux positifs est intégrée : les placeholders comme YOUR_API_KEY, xxx, REPLACE_... sont ignorés. Les lignes de commentaires (#, //, --) sont ignorées entièrement. Et les en-têtes PEM de clés privées (qui commencent par -----) sont correctement distinguées des commentaires SQL (qui commencent par -- ).
Scanner de skills
Les skills sont puissants — un fichier SKILL.md entre directement dans le contexte LLM. Si quelqu’un modifie le SKILL.md d’un skill, il peut injecter des instructions arbitraires dans votre agent. Le scanner de skills :
- Découvre tous les skills dans les répertoires standards (
~/.agents/skills/,~/.pi/agent/skills/,.pi/skills/,.agents/skills/) - Hash chaque
SKILL.mden SHA-256 - Compare avec
skill-approvals.json - Skills nouveaux ou modifiés → prompt d’approbation (une seule fois)
- Précédemment non approuvés → notification uniquement (pas de dialogue bloquant)
Seul SKILL.md est hashé — les scripts et assets annexes ne le sont pas. Le bash gate couvre l’exécution des scripts. Ça garde la vérification rapide (un fichier par skill) et concentrée sur la surface d’attaque LLM réelle.
Installation et configuration
Installation en une commande
pi install git:github.com/mwolff44/pi-secured-setup
C’est tout. Au premier lancement, l’extension crée ~/.pi/agent/security/ avec les configs par défaut et scanne vos skills pour approbation.
Première exécution
🔒 Skill Review: grill-me
Skill: grill-me
Source: ~/.agents/skills/
Path: /home/user/.agents/skills/grill-me/SKILL.md
🆕 New skill detected.
--- SKILL.md preview ---
# Grill Me
Interview the user relentlessly about a plan or design...
---
Approve
> Deny
Skip
Chaque skill reçoit un seul prompt. Les sessions suivantes affichent uniquement une notification pour les skills non approuvés.
Configuration en trois couches
La configuration est chargée depuis trois couches, fusionnées par ordre de priorité :
1. defaults/ — livré avec le package (ne pas éditer)
2. ~/.pi/agent/security/ — overrides spécifiques à la machine
3. .pi/security/ — overrides spécifiques au projet
Les listes de patterns sont additives. Un préfixe ! exclut un pattern hérité :
// .pi/security/protected-paths.json
{
"patterns": [
"!*secret*", // Retirer le pattern *secret* hérité pour ce projet
"config/prod.yaml" // Ajouter un pattern spécifique au projet
],
"readAction": "allow" // Ne pas confirmer les lectures de fichiers protégés dans ce projet
}
Ça signifie que vous pouvez durcir la sécurité par projet sans toucher à votre config globale, ou assouplir des règles spécifiques là où elles n’ont pas de sens.
Exemple par projet
mkdir -p .pi/security
// .pi/security/command-rules.json
{
"dangerous": [
"terraform destroy",
"kubectl delete namespace"
]
}
// .pi/security/allowed-external.json
{
"paths": [
"../shared-libs"
]
}
Le dashboard /security et les commandes
/security — Dashboard
🔒 Security Dashboard — Session m5x8k2-abc123
This session:
🔴 Blocked: 3 actions
🟡 Confirmed: 5 actions
🔵 Auto-approved: 42 actions
⚠️ Secrets redacted: 2
Skill status:
✅ 18 approved, ⚠️ 0 pending, 🚫 0 denied
Recent events:
10:28 [BLOCKED] write → /home/user/other-project/file.ts (outside boundary)
10:25 [CONFIRMED] bash → curl https://api.example.com (external)
10:22 [REDACTED] secret (anthropic-key) in read → .env
Log file: ~/.pi/agent/security/audit.jsonl
Référence complète des commandes
| Commande | Description |
|---|---|
/security | Dashboard avec compteurs, événements récents, statut des skills |
/security:skills | Re-déclencher le flux d’approbation pour tous les skills |
/security:trust <name> | Approuver un skill par nom, persister dans la config |
/security:allow <path> | Ajouter un chemin externe à la liste autorisée |
/security:clean [jours] | Élaguer les entrées d’audit plus anciennes que N jours (défaut : 30) |
Audit log
Chaque action est enregistrée en JSONL dans ~/.pi/agent/security/audit.jsonl :
{
"timestamp": "2026-05-07T10:28:15.123Z",
"sessionId": "m5x8k2-abc123",
"type": "boundary.block",
"severity": "warning",
"details": {
"tool": "write",
"path": "/home/user/autre-projet/file.ts",
"boundary": "/home/user/mon-projet",
"reason": "write outside project boundary"
}
}
Le log rotate automatiquement — par défaut 10MB par fichier, 3 fichiers conservés. Configurable via ~/.pi/agent/security/audit-config.json.
Greywall + pi-secured-setup : défense en profondeur
Ces deux outils résolvent des problèmes différents. Ils se complètent.
| Préoccupation | Greywall | pi-secured-setup |
|---|---|---|
| Containment kernel-level | ✅ | ❌ |
| Application de frontière fichier | ❌ | ✅ |
| Rédaction de secrets dans le contexte LLM | ❌ (filtre les destinations, pas le contenu) | ✅ |
| Classification de commandes | ✅ (niveau syscall kernel) | ✅ (patterns regex, dialogues utilisateur) |
| Vérification d’intégrité des skills | ❌ | ✅ |
| Audit trail | ❌ (logs de violations) | ✅ (JSONL, dashboard, rotation) |
| Matching glob de chemins protégés | ❌ | ✅ |
| Filtrage réseau | ✅ (proxy SOCKS5) | ❌ |
| Substitution de credentials | ✅ (proxy HTTP) | ❌ (rédacte dans le payload) |
| Nécessite modules kernel / root | ✅ | ❌ |
| Fonctionne sur tout OS | ❌ (spécifique Linux/macOS) | ✅ (tourne dans pi, cross-platform) |
Setup recommandé : Greywall pour le mur extérieur — containment kernel-level, filtrage réseau, protection des credentials. pi-secured-setup pour le mur intérieur — guards applicatifs, rédaction de secrets, vérification des skills, audit trail. Ensemble, ils fournissent une défense en profondeur significative sans point de défaillance unique.
Conclusion
La sécurité, c’est des couches, pas des silver bullets. Greywall contient pi au niveau kernel. pi-secured-setup ajoute de la conscience à l’intérieur de l’agent lui-même — bloquant les dommages accidentels, rédactant les secrets avant qu’ils n’atteignent le LLM, vérifiant l’intégrité des skills, et conservant un audit trail complet.
L’extension est open source, testée (98 tests unitaires), et installable en une seule commande. Chaque guard est une fonction pure sans dépendance pi, ce qui rend la logique principale indépendamment testable et auditable.
Si vous utilisez pi au quotidien — surtout avec accès à des projets sensibles — je dirais que ce n’est pas optionnel. C’est le minimum vital de sécurité.
pi install git:github.com/mwolff44/pi-secured-setup
Les sources sont sur GitHub. Contributions, retours et bug reports sont les bienvenus.
Quelles sont vos préoccupations de sécurité avec les agents de code IA ? Y a-t-il des menaces que je n’ai pas couvertes ici ? Dites-le-moi en commentaire !