
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.
Mascarade de la Renaissance. Asseyez-vous dans le siège de l'agent.
Asseyez-vous dans le siège de l'agent.
Un CLI qui parle MCP et compatible OpenAI comme le fait le modèle, puis rapporte à la façon de linpeas. Constats plus remédiations. Aucune charge utile d'exploitation. Aucun déchiffrement CoT.
| Quoi | Reconnaissance en direct de l'infra des agents : configurations MCP, écouteurs, journaux de session, écho de chaîne de pensée chiffrée, API non authentifiées, empoisonnement de catalogue, arbres de compétences. |
| Qui | Opérateurs d'Hermes, Grok, Claude, Cursor, VS Code, Codex et de piles de modèles locales qui ont besoin de voir ce que l'agent peut voir. |
| Ce que ce n'est pas | Pas un générateur de jailbreak. Pas le décodeur de modèle plus faible arXiv:2608.09867. Pas une passerelle d'exécution. |
| Statut | Bêta. Le cargo test hors ligne est la porte publique. Le --lab en direct est pour les hôtes que vous possédez. |
| Licence | MIT |
Les scanners MCP statiques (Invariant mcp-scan, mcp-security-scan) lintent les schémas et les configurations. Les contrôleurs de santé pingent initialize. Le trou, c'est le siège :
initialize, vous êtes l'agent.:11434, :8000) se lient souvent à 0.0.0.0 sans bearer.Des roues que nous enfourchons, pas que nous réécrivons : détecteurs de catalogue existants + pin/check, netstat, ureq en GET uniquement, OWASP MCP Top 10 comme taxonomie des constats. Nous n'avons pas cloné mcp-scan ni mcp-security-scan.
git clone https://gitlab.com/WattoCyber/masq.git
cd masq
cargo install --path .
# binary: masq
cargo test
# expect: exit 0
Suite World (binaire contre des fixtures, mocks locaux, recon de cet hôte) :
python scripts/world_suite.py
# field = ~/.grok/sessions lab = allowlisted hosts bench = frozen-corpus wall
python scripts/world_suite.py --lanes all
Boîte distante façon Kali, depuis le poste de travail :
MASQ_REMOTE_HOST=user@host bash scripts/deploy_kali.sh
# on the box:
~/.local/bin/masq --plain
MASQ_LAB_HOSTS=... ~/.local/bin/masq --lab --plain
masq # live stream + posture report (includes skills)
masq --lab # same, plus allowlisted homelab hosts
masq tui # boxed TUI, stays until Ctrl+C
masq --plain # report only, no live stream
masq --json # machine report
masq recon # same dump, recon only
masq sniff ~/.grok/sessions # CoT / secrets in session logs
masq sniff --timeline PATH # file-order blob/secret/reason lines (no decrypt)
masq api # GET /v1/models on local (and --lab) ports
masq sit --url http://127.0.0.1:4443/mcp
masq chameleon --url http://127.0.0.1:4443/mcp -o /tmp/chameleon
masq chameleon --url ws://127.0.0.1:9000/mcp -o /tmp/chameleon
masq chameleon --url unix:///tmp/mcp.sock -o /tmp/chameleon
masq chameleon --token-file ~/.secrets/mcp.txt --url http://127.0.0.1:9/mcp -o /tmp/chameleon
masq chameleon -- python -m their_mcp -o /tmp/chameleon
# then: npx -y @copilotkit/aimock --config /tmp/chameleon/aimock.json
masq discover # find VS Code / Cursor / Claude / Grok / Hermes MCP configs
masq proxy --upstream http://127.0.0.1:4443/mcp --block
masq sast ./server # local sinks (semgrep if present)
masq classify --url http://127.0.0.1:4443/mcp --lab
masq overnight --lab --hours 6
masq map --from reports/overnight-YYYYMMDD/latest.json
# catalog
masq fixtures/t3_line_jump.json
masq fixtures/clean_calculator.json --trusted
masq pin fixtures/clean_calculator.json -k calc
masq check fixtures/clean_calculator.json -k calc
masq detectors
Sortie : 0 propre · 2 constats ≥ --fail-on (défaut high) · 1 erreur.
La TUI est facultative (masq tui ou --tui). Par défaut, sur un tty, un flux en direct façon linpeas, puis le rapport. Cron utilise --plain / --no-color.
Alias : doctor / audit → scan. chameleon → mimic. posture → seat.
sit / chameleon parlent :
http://)ws://unix: et npipe:--framing auto essaie NDJSON puis Content-Length)Authentification (jamais déversée dans le rapport) :
--token-file PATH (la première ligne devient Authorization: Bearer …)--token-env VAR--header "Name: value" (répétable)wss:// n'est pas intégré. Stunnel vers ws:// ou utilisez HTTP. HTTP ne suit aucune redirection.
L'initialize stdio n'annonce pas sampling. Signalez sampling / elicitation du serveur. Les URL de documentation (model-catalog.json, /docs/) sont ignorées à dessein.
Racines de configuration + skills sous $HOME / %USERPROFILE% :
VS Code, Cursor, Windsurf, Claude Desktop, Claude Code, Grok, Hermes, Codex, Continue, Gemini CLI, Amp, Kiro, OpenCode, Amazon Q, Antigravity, OpenClaw.
Plus le .mcp.json du répertoire courant et MASQ_EXTRA_CONFIG (liste de chemins OS).
--lab)--lab est une liste autorisée, pas un scan /24. Elle est configurée par l'opérateur. Rien n'est compilé au-delà du loopback.
MASQ_LAB_HOSTS : hôte:port ou hôtes séparés par des virgules, des espaces ou des retours à la ligne..masq/lab-hosts : un hôte par ligne, commentaires #.Exemple :
export MASQ_LAB_HOSTS="192.0.2.10,192.0.2.11"
masq --lab
MASQ_LAB_HOSTS est lu pour les sondes API et le regroupement de flotte TUI. MASQ_SIT_URLS (ou un --mcp-url) fournit les URL MCP sur lesquelles s'asseoir avec --lab.
sit --url hors loopback nécessite --lab et un hôte en liste autorisée. Un initialize non authentifié sur loopback est High. Hors de la machine est Critical.
Ne pointez pas proxy vers un hôte sur lequel vous ne vous assiériez pas.
Priorité de sniff : chat_history.jsonl d'abord, puis Hermes request_dump_*, puis les autres jsonl. Le parcours va jusqu'au bout. Il ne conserve pas les 300 premières occurrences WalkDir. Pointez masq sniff <un-dossier-de-session> pour aller plus loin.
masq overnight --lab --hours 6 --interval-mins 20
# writes <cwd>/reports/overnight-YYYYMMDD/{latest.json,latest.md,latest.txt,delta.txt}
Ne modifie pas les configurations. N'émet pas de tools/call vers le serveur en direct. delta.txt est baseline / no_change / CHANGE, plus + titre de sévérité et - titre de sévérité.
classify --llm et le module complémentaire de triage TUI sont les seuls POST de complétions (Grok /v1/chat/completions, confirmation de l'opérateur). Sans clé : remédiations locales uniquement. Clé depuis XAI_API_KEY ou ~/.secrets/xai.txt. Jamais déversée.
CLI (clap) masq
→ seat | recon | sniff | api | sit | chameleon
→ discover | proxy | sast | classify | overnight | map
→ scan | multi | pin | check | detectors | tui
→ client (HTTP / SSE / ws / unix / npipe / stdio)
→ normalize (full-schema walk, caps)
→ detectors + sniff + recon + sit findings
→ report (text / JSON / Markdown) + optional TUI
Crate de bibliothèque : masq (scan_from_tools_list, scan_stdio, run_seat, PostureReport).
Ne déversez pas ~/.secrets. Recon compte les fichiers. Chemin + « loaded ».
cargo test
cargo clippy --all-targets -- -D warnings
Sortie attendue : 0.
Fixtures : T1 empoisonnement de description, T3 saut de ligne, T6 noms de paramètres, T8 ANSI, T13 noms dupliqués, rugpull d'épingles, multi-liste, mock NDJSON en direct sous tests/mock_mcp_server.py.
Les secrets restent hors de git (reports/, data/, .env, *.key, secrets/, .masq/).
MIT. Copyright 2026 SamsonCyber.
| Commande | Ce qu'elle fait |
|---|
seat (défaut) | Posture complète : recon + sniff + api + skills + sit facultatif. |
recon | Fichiers de configuration, écouteurs, URL fantômes, argv sudo, npx/uvx non épinglés. |
sniff | Journaux de session pour secrets, raisonnement en clair, écho CoT chiffré. |
sniff --timeline | Lignes T0001 dans l'ordre des fichiers. Pas de déchiffrement. Plafonne à 200 événements/fichier. |
api | /v1/models (et apparentés) en GET uniquement sur loopback ; --lab ajoute les pairs en liste autorisée. |
sit | Parle MCP : initialize, notifications/initialized, tools/list, prompts/list, resources/list. N'émet jamais tools/call. |
chameleon / mimic | S'assoit sur un catalogue en direct ou depuis fichier, écrit catalog.json + aimock.json + calls.json. Les enveloppes d'exemple tools/call sont pour aimock uniquement. |
discover | Affiche les chemins de configuration MCP connus des agents. Aucun lancement. |
proxy | Transfère le JSON-RPC de l'agent. --block refuse les paramètres/résultats tools/call en forme de secret. Écoute par défaut sur 127.0.0.1:9877. |
sast | Puits de code source locaux. Utilise semgrep s'il est installé. |
classify | Revue locale IPI / empoisonnement d'un tools/list en direct. --llm demande à Grok (clé de l'opérateur). |
overnight | Répète seat jusqu'à épuisement de --hours. Écrit des rapports. Ne modifie pas les configurations. |
map | Requêtes textuelles de chemins d'attaque sur un JSON de posture enregistré. Pas de diagramme. |
scan / multi | Lint statique de catalogue (les chemins .json nus y sont réécrits). |
pin / check | Magasin d'épingles à empreinte de contenu (.masq/pins.json) pour une CI anti-rugpull. |
detectors | Affiche le pack de règles du catalogue. |
tui | Seat en boîte. Reste jusqu'à Ctrl+C. |
| Module | Couvre |
|---|
| recon | MCP01 chemin des secrets, MCP04 npx/uvx non épinglés, MCP07/09 écouteurs et URL fantômes, MCP05 argv sudo |
| catalog | MCP03 empoisonnement de schéma / shadowing / rugpull |
| skills | Mêmes détecteurs de catalogue sur SKILL.md (Hermes, Grok, Claude, Cursor, Codex, Gemini, Amp, Kiro, OpenCode, OpenClaw). Pas de Snyk cloud. |
| sit | MCP02 dérive du périmètre, MCP03 tools/list en direct, MCP07 initialize non authentifié, annonce de sampling/elicitation par le serveur, Streamable HTTP (2025-06-18) puis HTTP+SSE (2024-11-05), rebinding DNS d'origine |
| sniff | MCP01 + MCP10 + écho CoT chiffré arXiv:2608.09867 (y compris thinkingSignature) |
| api | MCP07 /v1/models non authentifié, MCP09 liaison LAN |
| watch | diff d'épingles sur .masq/pins.json + skills. Overnight le configure. Pas un proxy. |
| fleet | regroupement de la liste autorisée lab dans une section FLEET |
| map | Requêtes textuelles de chemins sur un rapport de posture |
| Limite | Valeur |
|---|
| fichier tools/list | 8 MiB |
| fichier sniff | 8 MiB (2 premiers MiB échantillonnés si plus grand) |
| fichiers sniff / racine | 300 (mtime le plus récent dans la priorité) |
| événements de timeline / fichier | 200, puis timeline truncated |
| lignes T de timeline | 500 (inspect et collapse s'exécutent quand même) |
| profondeur de parcours de schéma | 64 |
| outils par inventaire | 5_000 |
| sonde HTTP | GET uniquement, 2 s API / 5 s sit |
| poignée de main sit | délai d'attente + arrêt |
| Cet outil | Pas cet outil |
|---|
| S'asseoir en client de l'agent (initialize + list) | Émettre tools/call vers un serveur en direct |
| Détecter l'écho CoT chiffré dans les journaux | Déchiffrer CoT ou le rejouer dans un modèle plus faible |
GET /v1/models | POST de complétions (sauf triage TUI facultatif / classify --llm) |
| Rugpull à empreinte épinglée sur un catalogue | PKI signée / coffre d'épingles d'entreprise |
Transférer le tools/call de l'agent dans proxy --block | Passerelle DLP complète à l'exécution / plan de contrôle SaaS |
| Lint local d'arbre de compétences | Snyk / SCA cloud |
| Vérification | Attendu |
|---|
masq fixtures/clean_calculator.json --trusted | sortie 0 |
masq fixtures/t3_line_jump.json | sortie 2 |
masq fixtures/t13_duplicate_names.json | sortie 2 (shadowing d'outils) |
masq sniff --timeline fixtures/ (non-TTY / --json) | T0001 uniquement avec le drapeau |
masq chameleon fixtures/clean_calculator.json -o <tmpdir> | catalog.json, aimock.json, calls.json |
masq --no-color en direct | jetons masqués (…, pas le sk- complet) |