Aller au contenu principal

Sécurité MCP

Cette page liste ce que la passerelle MCP du Control Plane applique à chaque appel MCP, comment les identifiants, la provenance et la suspension sont traités, les menaces ainsi couvertes, et les étapes qu'un développeur et un administrateur du tenant suivent pour durcir un serveur MCP. Elle s'adresse aux développeurs, aux administrateurs du tenant et aux responsables sécurité.

Contrôles de la passerelle​

POST /v1/mcp/gateway/{server_id} applique les contrôles ci-dessous dans cet ordre, pour chaque message d'un lot. Un refus n'atteint jamais le serveur et est audité.

OrdreContrôleRefus
1Authentification de l'appelant, relation OpenFGA can_invoke sur le serveur, rôle d'exploitationHTTP 401 ou 403
2Message JSON-RPC 2.0-32600
3Serveur active-32003 "MCP server disabled"
4Isolation par projet (ADR-0165)-32003 mcp_server_project_mismatch
5Liste d'accès du serveur (allowed_principals ; propriétaire et agents pour une instance du Runtime MCP)-32003 mcp_principal_not_allowed
6Identifiant lié à une application : le serveur doit faire partie de ses mcp_servers-32003 avec le code du refus
7Méthode parmi initialize, tools/list, tools/call, resources/list, resources/read, prompts/list, ping-32601
8tools/call : outil dans allowed_tools (glob), portée tools:invoke-32003
9tools/call : DLP des arguments avec les règles du tenant ; une règle de blocage refuse-32003 dlp_blocked
10Décision de politique mcp.call (OPA) avec method et target, coupe-circuits du SOCHTTP 403
11tools/call : réservation de quota d'un appel d'outilHTTP 429 quota_exceeded
12resources/read : URI dans allowed_resources (glob)-32003
13Sortie réseau : adresse interne uniquement, revérifiée à la connexionHTTP 403 mcp_online_forbidden
14Réponse : tools/list et resources/list filtrés par les listes d'autorisation ; résultat de tools/call masqué par la DLP ; résultats de tools/call et resources/read analysés contre l'injection de prompt-32003 dlp_blocked ou prompt_injection_blocked
15Événement d'usage (appel d'outil, durée) et événement d'audit mcp.<method> avec la cible et les détections de la DLP
remarque

Quand la Tool Gateway appelle un outil MCP (POST /v1/tools/{name}/invoke), elle évalue tool.invoke et compte l'appel elle-même ; la passerelle MCP saute alors sa propre décision de politique, son quota et son événement d'usage.

Sortie réseau : serveurs internes uniquement​

  • Un serveur n'est atteint qu'à une adresse interne (ADR-0170) : un hôte interne de EAI_MCP_INTERNAL_HOSTS, un serveur hébergé par le Navin Manager (ses instances nommées dans EAI_EGRESS_PRIVATE_ALLOWLIST), ou une instance du Runtime MCP à l'adresse de son proxy dans le cluster.
  • L'adresse est vérifiée à l'enregistrement du serveur et de nouveau à chaque appel : chaque adresse vers laquelle l'hôte se résout doit être privée. Une destination publique répond 403 mcp_online_forbidden, est auditée en security.egress.denied et comptée dans eai_mcp_online_refused_total.
  • La restriction de sortie du tenant (hôtes autorisés) s'applique toujours.
  • L'adresse d'une instance du Runtime MCP est écrite par le contrôleur de cycle de vie, jamais par un tenant, et doit correspondre au motif des proxys du cluster ; la CiliumNetworkPolicy de l'instance limite qui atteint le proxy et où le conteneur MCP peut aller.

Identifiants par le broker​

  • L'enregistrement ne prend que des références : credential_ref vaut openbao://... ou env://... ; auth.type connector nomme un connecteur dont le Credential Broker détient les identifiants.
  • La passerelle résout le secret au moment de l'appel, côté serveur, et le place uniquement dans l'en-tête (bearer, api_key) ou dans le paramètre de requête (query_param) de la requête sortante. Les réponses renvoient auth.type, header, param, credential_ref et connector, jamais une valeur.
  • Un serveur hébergé par le Navin Manager reçoit son propre jeton, gardé à openbao://mcp/hosted/<id> ; aucune réponse et aucun événement d'audit ne le contient.
  • Une instance du Runtime MCP reçoit un JWT court par appel (sujet l'appelant, audience l'instance) et ses propres identifiants temporaires, révoqués quand elle se met en veille ou se termine. Voir Runtime MCP par utilisateur et par projet.

Signature et provenance​

ContenuPreuve
Schémas des outilssha256 de la description, des schémas d'entrée et de sortie par outil ; chaque schéma nouveau ou modifié est une version du catalogue avec une approbation (mcp_tool_version)
Packs de la marketplace avec des serveurs MCPContrôles de publication : signature, SBOM, analyse de vulnérabilités, provenance, licence, permissions, tests (Marketplace)
Images du Runtime MCPRegistre interne de EAI_MCP_RUNTIME_IMAGE_REGISTRIES, épinglées par empreinte ; Kyverno refuse un MCPServer sans empreinte
Préréglages de la bibliothèque NavinEmpreinte sha256 de chaque élément dans catalog/navin/index.json, vérifiée par python tools/navin_library/sync.py --check

Quarantaine et suspension​

MécanismeEffetComment
Désactiver un serveurLes appels répondent "MCP server disabled" tout de suite ; la réactivation est une demande de promotion approuvée par une seconde personnePOST /v1/mcp/servers/{server_id}/status
Suspendre une installation de la marketplaceSes outils bloqués, ses agents suspendus, ses serveurs MCP désactivés ; la reprise demande une approbation à quatre yeuxPOST /v1/marketplace/installations/{installation_id}/status
Coupe-circuit d'un paquetToutes les installations du paquet suspenduesPOST /v1/marketplace/packages/{name}/status
Ordre SOC DISABLE_TOOL sur la cible mcpDécisions de politique qui touchent le serveur refusées, y compris après le redémarrage de chaque réplicaPOST /v1/soc/orders (procédure SOC)
Détection mcp_compromisedSévérité sev1, playbook DISABLE_TOOL sur la cible MCPDétections du SOC
Serveur hébergé qui ne l'est plusDésactivé à la synchronisation suivantePOST /v1/mcp/hosted/sync
Instance du Runtime MCP en panneDétruite tout de suite, identifiants révoquésContrôleur de cycle de vie

Menaces​

MenaceContrôlePreuve
Données d'un projet envoyées à un service MCP en ligneAdresses internes uniquement, vérifiées à l'enregistrement et à chaque appelAudit security.egress.denied, eai_mcp_online_refused_total
Agent d'un projet qui appelle un serveur d'un autre projetIsolation par projet, refus avant tout appel au serveurAudit mcp.call avec deny et la raison
Membre d'un projet qui utilise les identifiants d'un autre membreListe d'accès par serveur, une instance du Runtime MCP par utilisateur avec ses propres identifiants et sa politique CedarAudit mcp.call principal_not_allowed
Rug pull : un serveur change la description ou le schéma d'un outilNouvelle version du catalogue avec approbation à chaque découverte ; allowed_tools appliqué par la passerellenew_versions de la découverte, approbations
Empoisonnement d'outil ou injection de prompt dans un résultatAnalyse du contenu non fiable des résultats de tools/call et resources/readprompt_injection_blocked
Exfiltration de données sensibles dans les arguments ou les résultatsDLP avec les règles du tenant : arguments inspectés (règles de blocage), résultats masquésChamp dlp de l'événement d'audit
Fuite de secret par le registreRéférences uniquement ; secrets résolus côté serveur au moment de l'appelauth des réponses sans valeur
Rejeu d'un jeton sur une autre instanceUne audience par instance, durée de vie courteEAI_MCP_RUNTIME_TOKEN_TTL_SECONDS
Abus d'appelsRéservation de quota par appel d'outil, événements d'usage429 quota_exceeded, usage
Serveur compromisDésactivation, coupe-circuit du SOC, suspension de la marketplaceÉtat du coupe-circuit, audit
Image ou pack falsifiéÉpinglage par empreinte, contrôles de signature et de provenanceContrôles de la marketplace, Kyverno

Durcir un serveur et son projet​

  1. Garder des listes d'autorisation courtes. Enregistrez le serveur avec les allowed_tools et allowed_resources exacts dont il a besoin, jamais * en production.

    Résultat attendu : GET /v1/mcp/servers/{server_id}/tools ne liste que ces outils.

    En cas d'échec : la liste ne se modifie pas en place ; supprimez le serveur et enregistrez-le de nouveau.

  2. Restreindre les appelants. PUT /v1/mcp/servers/{server_id}/access avec les utilisateurs et les agents qui en ont besoin.

    client.mcp.set_access("files-server", ["agent:support-bot", "user:alice"])

    Résultat attendu : tout autre appelant reçoit mcp_principal_not_allowed.

    En cas d'échec : 409 mcp_instance_access_managed pour une entrée du Runtime MCP (propriétaire et agents uniquement).

  3. Rattacher le serveur à son projet. Enregistrez-le avec project ; un serveur sans projet est partagé par tout le tenant.

    Résultat attendu : le serveur n'est pas listé depuis un autre projet.

    En cas d'échec : 403 mcp_project_forbidden quand le corps et la requête nomment des projets différents.

  4. Fixer des règles DLP de blocage pour les données que l'outil ne doit jamais recevoir. Utilisez les règles DLP du tenant (GET /v1/dlp/rules, POST /v1/dlp/rules) ; la passerelle les applique aux arguments et aux résultats.

    Résultat attendu : un tools/call avec une valeur bloquée répond dlp_blocked.

    En cas d'échec : testez la règle avec POST /v1/dlp/inspect.

  5. Écrire une politique pour mcp.call. Refus par défaut, autorisez les méthodes et les outils dont le projet a besoin, testez chaque règle (Développement de politiques).

    Résultat attendu : un outil non listé est refusé en HTTP 403 par la décision de politique.

    En cas d'échec : lancez les tests de politique (enterprise-ai test authz).

  6. Approuver les versions d'outils après une revue. Lisez les schémas de chaque version pending_approval dans GET /v1/mcp/catalog avant d'approuver.

    Résultat attendu : chaque version utilisée est approved.

    En cas d'échec : rejetez la version et désactivez le serveur jusqu'à sa correction.

  7. Surveiller les signaux. Suivez eai_mcp_calls_total par résultat, eai_mcp_online_refused_total et les événements d'audit mcp.* ; vérifiez l'intégrité de la chaîne d'audit avec enterprise-ai audit verify.

    Résultat attendu : les refus s'expliquent par une modification connue.

    En cas d'échec : ouvrez un incident et suivez la procédure SOC.

danger

Ne mettez jamais une valeur secrète dans un corps d'enregistrement, un manifeste ou un champ de préréglage : les champs secrets n'acceptent que des références, et une valeur écrite là serait lisible par chaque lecteur du registre.

Vérifier​

  • Un appel à un outil hors de allowed_tools répond -32003 et GET /v1/audit/events contient mcp.tools.call avec deny et not in allow list.
  • Un enregistrement avec une URL publique répond 403 mcp_online_forbidden.

Étapes suivantes​

Dépannage​

SymptômeCauseCorrection
-32003 dlp_blocked sur un appel légitimeUne règle de blocage du tenant correspond aux arguments ou au résultatLisez les détections dans l'événement d'audit ; ajustez la règle avec le responsable sécurité
-32003 prompt_injection_blockedLe résultat du serveur contient des instructions destinées au modèleCorrigez le contenu servi par l'outil
HTTP 403 sur chaque appel après un incidentCoupe-circuit du SOC ou suspension actifLisez GET /v1/soc/kill-switches ; le rétablissement suit la procédure SOC
HTTP 403 mcp_online_forbiddenHôte publicHébergez le serveur en interne
-32003 "scope tools:invoke required"Clé ou jeton sans la portéeÉmettez une clé avec tools:invoke