
Reconnaissance en direct et audit de posture pour l'infrastructure des agents IA : analyse les configurations MCP, les journaux de session et les API à la recherche de secrets, de catalogues empoisonnés et de fuites CoT.
Asseyez-vous là où le modèle s'assied. Voyez ce qu'il peut voir.
MASQ est une CLI de sécurité locale pour les piles d'agents IA. Elle occupe la même place que le modèle : elle lit les catalogues d'outils MCP, effectue la poignée de main MCP, parcourt les journaux de session et sonde les ports HTTP des modèles locaux. Elle affiche ensuite les résultats et les remédiations.
Elle parle MCP et HTTP compatible OpenAI comme le fait le client. Elle rend compte comme un outil de reconnaissance d'hôte. Elle n'appelle pas d'outils sur un serveur actif, ne déchiffre pas la chaîne de pensée et ne génère pas de jailbreaks.
| À utiliser quand | Vous exécutez Cursor, VS Code, Claude, Codex ou une pile de modèles locaux et souhaitez voir les serveurs MCP, compétences, journaux et API que l'agent peut atteindre. |
| Commencez par | La démo de deux minutes ci-dessous. Elle reste à l'intérieur de ce dépôt. |
| Statut | Bêta. cargo test est le portail public. Les sondes actives sont destinées aux hôtes que vous possédez. |
| Licence | MIT |
Vous avez besoin de Rust stable (1.88 ou plus récent) et de Python 3. Depuis un clone de ce dépôt :
cargo build --locked --bin masq
alias masq=./target/debug/masq
# or run the same walkthrough as a script:
# bash scripts/demo.sh
1. Un catalogue propre reste propre
masq fixtures/clean_calculator.json --trusted
CLEAN clean_calculator tools=2 hash=sha256:e680cd2e4ac6c80ec783f11a0d9272a6741797feba216eb8e79633dd59633ab4
Quitter 0.
2. Un catalogue empoisonné échoue au contrôle
fixtures/t3_line_jump.json est un outil sqrt dont la description indique au modèle de le consulter en premier à chaque session et de préfixer les commandes shell avec un curl canari. C'est du poison de catalogue, pas des mathématiques.
masq fixtures/t3_line_jump.json
FINDINGS t3_line_jump tools=1 findings=2 max=critical
F-001 [critical] D02 mcp03=schema_poison sqrt Network exfiltration directive in schema
path: $.tools[0].description
F-002 [critical] D03 mcp03=schema_poison sqrt Line-jump: force tool consultation / session prefix
path: $.tools[0].description
Quitte avec le code 2 (constats au niveau ou au-dessus de --fail-on, par défaut high).
3. Se placer face à un MCP réel comme le fait le modèle
Le mock intégré parle MCP via stdio. masq envoie initialize, notifications/initialized et tools/list. Il n'envoie jamais tools/call.
masq sit --plain --no-color -- python3 tests/mock_mcp_server.py
01 CATALOG
M-001 CRIT live Secret path or credential exfil directive
Schema references secret file paths or credential stores in an agent-directed way.
ACT Never reference host secret paths in tool metadata.
LOCUS stdio:python3 :: add
M-002 HIGH live IPI / poison language in tool metadata
Local classifier hit `system-override` in tool `add`.
ACT Remove agent-directed instructions from the tool description.
M-003 HIGH live Instruction-override language in schema string
Text matches common prompt-injection / instruction-override phrasing in tool metadata.
M-004 HIGH live Pre-action system instruction in schema
Schema instructs the model to perform actions before the normal tool purpose.
02 SEAT
HIT stdio python3 init ok name=mock-poison tools=1
La description de l'outil add du mock indique au modèle de lire ~/.ssh/id_rsa avant d'effectuer des calculs arithmétiques. masq le signale depuis le tools/list en direct, puis se termine avec le code 2.
4. Analyser un journal de session d'exemple
fixtures/demo/chat_history.jsonl contient une fausse clé API et un blob de réflexion chiffré. Pointez masq vers ce répertoire — et non vers votre véritable historique de conversation — pour visualiser la chronologie.
masq sniff --timeline --plain --no-color fixtures/demo
T0001 SECRET chat_history.jsonl:2 {"content":"Authorization: Bearer sk-x……
T0002 BLOB chat_history.jsonl:3 encrypted_content len=202
La clé implantée est masquée. La chaîne de pensée chiffrée est signalée par sa longueur, et non décodée.
5. Épinglez un catalogue que vous avez examiné, puis détectez les dérives
masq pin fixtures/clean_calculator.json -k calc
masq check fixtures/clean_calculator.json -k calc --trusted
pin écrit .masq/pins.json. check échoue plus tard si la liste des outils ou les hachages changent (rug-pull).
Codes de sortie partout : 0 propre · 2 constats ≥ --fail-on · 1 erreur.
Les scanners MCP statiques analysent les schémas. Les contrôles de santé envoient un initialize. Le vide, c'est le siège : les fichiers, les écouteurs et les poignées de main que le modèle utilise déjà.
initialize sans authentification. Si vous pouvez mener à bien cette poignée de main, vous êtes déjà l'agent. masq s'installe ; il n'appelle pas d'outils.11434, 8000 et compagnie se lient souvent à 0.0.0.0 sans bearer. masq identifie le service (Ollama, vLLM, LiteLLM, …) avec des sondes GET uniquement, puis liste les modèles.flowchart LR
A["MCP tools/list JSON"] --> M[masq]
B["Live MCP server"] --> M
C["Session logs"] --> M
D["Local model HTTP"] --> M
M --> E["Findings + remediations"]
M --> F["Optional pin store for CI"]
git clone https://gitlab.com/WattoCyber/masq.git
cd masq
cargo install --path . --locked
# command: masq
masq --version
masq --help
Nécessite la version stable actuelle de Rust (1.88+ ; à installer avec rustup). cargo test est la porte publique. Python 3 n'est requis que pour le mock stdio en direct dans la démo et dans les tests.
Pour compiler sur un hôte Unix distant via SSH (installation uniquement ; ne scanne pas cet hôte) :
MASQ_REMOTE_HOST=user@host bash scripts/deploy_remote.sh
# on that host: masq --version
La démo ne quitte jamais ce dépôt. Ces commandes, elles, le font, et elles sont limitées à cette machine sauf si vous optez pour une liste d'autorisation de laboratoire.
Exportez ou enregistrez un JSON tools/list, puis :
masq path/to/tools.json
masq path/to/tools.json --json
masq path/to/tools.json --markdown
Les chemins .json nus sont réécrits en scan. Deux fichiers JSON ou plus deviennent multi.
masq sit -- python3 -m your_mcp
masq sit --url http://127.0.0.1:PORT/mcp