MCP Fusion/Security and governance/Pipeline de sécurité

Pipeline de sécurité

Demandez à l’IA à propos de Vinkius

Toutes les couches entre un agent et vos données, dans l’ordre : firewall d’entrée, validation stricte, middleware de tenant, Presenters, le moteur de masquage, le limiteur de sortie, le firewall de prompt et le sandbox.

MCP Fusion applique la sécurité comme un pipeline de couches, chacune avec une position claire dans la requête. Cette page est la carte technique : qu’est-ce qui s’exécute, dans quel ordre, avec quelles garanties.

L’ordre, de bout en bout

1 contextFactory      tenant and identity resolution
2 rate limiter        sliding window, key from ctx
3 input firewall      LLM-as-Judge on the arguments
4 validate            strict Zod per action, unknown keys rejected
5 middleware chain    auth, audit, custom, precompiled and frozen
6 handler             your business logic
7 Presenter           schema shape → _select → redact → serialize
8 rules and UI        computed on the full object, never on the wire copy
9 egress guard        byte budget on the text response
10 audit + telemetry  every stage emits if a sink is configured

Couche par couche

Rate limiter

rateLimit({ windowMs, limit, keyFn }) est un middleware qui utilise une fenêtre glissante sur des listes d’horodatages. Deux appels comptent : increment() compte sans enregistrer, et record() ne journalise que les requêtes acceptées, donc le trafic rejeté ne peut pas gonfler sa propre fenêtre. keyFn(ctx) est le crochet d’identité : limitez par token, par tenant ou par utilisateur. Le store est une interface ; le store en mémoire est documenté comme mono-processus uniquement, la production utilise votre Redis ou KV derrière la même interface.

Firewall d’entrée

inputFirewall({ judge }) s’exécute après la validation Zod, avant votre handler. Les arguments sont sérialisés dans un prompt de juge (les backticks sont neutralisés pour empêcher l’évasion de fence) et un SemanticProbeAdapter interchangeable renvoie { safe, threats }. Sur !safe, le handler n’est jamais appelé : la réponse est un toolError('INPUT_REJECTED', ...) auto-réparant. Cette couche vise les entrées de type injection : « ignore les instructions précédentes », charges d’exfiltration, chemins de fichiers contrebandés.

Masquage par le Presenter (le firewall d’égress)

.redactPII(paths, censor?) compile des chemins fast-redact en une seule fonction, mise en cache sur le Presenter. L’ordre du pipeline dans Presenter.make() est précis : tronquer, valider, appliquer _select, cloner les données du wire, masquer, les sérialiser en chaîne, puis rendre les blocs d’UI et les règles depuis l’objet complet non masqué. Conséquences :

  • le texte du modèle ne contient jamais de champs masqués ; [REDACTED] n’est même pas sur le wire pour les clés masquées par _select
  • les blocs ui.table() conservent les valeurs réelles (ils sont construits depuis l’objet complet en mémoire, et le texte du wire est déjà figé)
  • si structuredClone ou le masqueur lève une exception, le pipeline lève aussi : Data withheld to prevent PII leak. Le masquage est fail-closed à ce stade.

fast-redact est un peer optionnel. S’il n’est pas installé, le masqueur se dégrade en no-op avec un avertissement console. Considérez-le comme une dépendance requise pour les connecteurs qui détiennent des données personnelles.

Firewall de prompt

Les règles elles-mêmes sont une surface d’attaque : les règles dynamiques sont générées à partir de données, et les données viennent du monde de l’agent. presenter.promptFirewall({ judge }) envoie les règles système accumulées à un juge avant que l’une d’elles n’atteigne le modèle. La stratégie est fail-closed et par règle : si le juge signale le lot mais nomme certaines règles, celles qui ne sont pas nommées sont bloquées aussi. Le mode consensus (tous les juges sont d’accord) n’a pas de fail-open. Configurer un firewall force le chemin asynchrone : make() lève, makeAsync() est le contrat.

Sandbox

sandboxed() sur un tool annonce la délégation de calcul : l’agent envoie une fonction fléchée JS, SandboxEngine l’exécute dans un contexte isolated-vm neuf avec les données injectées comme copie externe, et seule la valeur renvoyée revient. Valeurs par défaut : timeout de 5s, isolate de 128MB, plafond de sortie de 1MB, plafond de code de 64KB. process, require, fs, globalThis et Buffer n’existent pas dans le contexte ; la garde qui rejette les motifs évidents relève du DX seulement et n’est explicitement pas la frontière. En cas d’annulation, le moteur détruit l’isolate (ou ne libère que le contexte quand d’autres requêtes le partagent) et le recrée à l’appel suivant.

Kill switch et halt

L’arrêt d’urgence vit dans la console, voir Connector policy : le halt global et la politique par connecteur. Sur l’Edge, les connecteurs interrompus cessent de servir les appels sans redéploiement.

Ce que le framework ne fait pas

Honnêteté plutôt que marketing : le middleware d’audit du framework émet des événements vers votre sink (empreintes SHA-256 des arguments, classification de statut, pas de signature, pas de chaîne). La chaîne d’audit signée infalsifiable est une fonction d’hébergement de Vinkius Cloud : déployez avec mcpfusion deploy et la plateforme l’enregistre pour vous. La même répartition s’applique aux stores de rate limit : l’interface est la vôtre, l’Edge l’exécute.

Prochaines étapes