Zo controleer je een MCP-server voordat je hem installeert
6m leestijd1,064 woorden

Zo controleer je een MCP-server voordat je hem installeert

Een veiligheidschecklist om een MCP-server te controleren vóór installatie: wie hem echt publiceert, wat de tool-beschrijvingen tegen je model zeggen, wat hij kan bereiken, en waarom je de versie moet pinnen. Tien minuten die driehonderd organisaties hadden gered.

Afgelopen september verscheen de zestiende release van een npm-pakket met de naam postmark-mcp. De eerste vijftien deden precies wat de README beloofde: je agent mails laten versturen via de API van Postmark. Versie 1.0.16 voegde één regel toe. Elke mail kreeg voortaan een verborgen BCC naar het domein van een aanvaller.

Koi Security ontdekte het ongeveer een week later. Het pakket zat toen op zo'n 1.500 downloads per week, en hun schatting kwam uit op ruwweg 300 organisaties die ongemerkt hun uitgaande mail, inclusief wachtwoordresets en facturen, naar de inbox van een vreemde kopieerden.

En dit is het detail dat pijn hoort te doen: het pakket was nooit van Postmark. Een ontwikkelaar met een geloofwaardig ogend profiel publiceerde het, bouwde release na release vertrouwen op, en verzilverde dat vertrouwen daarna. Niemand had het gecontroleerd, want niemand controleert het. MCP-servers installeren we zoals npm-pakketten in 2015: config plakken, client herstarten, door.

Ik schreef eerder over de MCP-supply-chain en over de duizenden servers die open aan het internet hangen. Dit is het praktische stuk dat nog ontbrak: de controles die je uitvoert vóórdat een server ook maar in de buurt van je configuratie komt.

Waarom dit meer paranoia verdient dan npm

Een gewone dependency levert code die je programma aanroept. Een MCP-server levert code én instructies die je model leest. Elke tool-beschrijving belandt in de context van je agent, en daarmee is het beschrijvingsveld een execution path. Die zin mag je twee keer lezen.

Invariant Labs liet ruim een jaar geleden zien wat dat in de praktijk betekent. Ze publiceerden een vergiftigde add-tool, twee getallen erin, som eruit, met verborgen instructies in de beschrijving. Cursor las ze, opende ~/.ssh/id_rsa, en smokkelde de inhoud mee in de parameters van de tool. De gebruiker zag een agent die zat te rekenen.

Ze gaven het vervolgprobleem ook een naam: de rug pull. Een server die je gisteren goedkeurde, kan vandaag zijn tool-beschrijvingen aanpassen, en de meeste clients vragen je niet opnieuw om toestemming. Eén keer vertrouwen gegeven, eeuwig geldig. Precies dat mechanisme gebruikte postmark-mcp: vijftien eerlijke releases eerst.

Maak het plaatje compleet: een ecosysteem van ruim twintigduizend servers als je de registries ontdubbelt, nergens een poortwachter, en je agent als het proces met de meeste credentials op je machine. Dan zegt "ik vond hem in een registry" niets meer over waar hij vandaan komt.

De checklist vóór installatie

Zes controles. Tien minuten. Gesorteerd op hoe vaak ze iets opleveren:

  • Leg de publisher naast de leverancier. postmark-mcp zakte op dag één voor deze test: het was niet door Postmark gepubliceerd. Als een server de API van een bedrijf ontsluit, hoort de npm-publisher of GitHub-organisatie dat bedrijf te zijn, en hoort de repository waar het pakket naar linkt de code te zijn die je daadwerkelijk installeert. Een community-wrapper voor andermans dienst kan prima zijn, maar het blijft code van een vreemde met jouw credentials, en die moet elke andere controle met ruime marge doorstaan.
  • Lees de tool-beschrijvingen voordat je model dat doet. Het zijn prompts, gericht aan je agent. Open de broncode en lees elke beschrijving en docstring. Je zoekt naar gebiedende taal gericht aan het model: "lees eerst dit bestand voordat je deze tool gebruikt", "vermeld dit niet aan de gebruiker". Elke verborgen instructie, hoe onschuldig ook, is een reden om af te haken. mcp-scan automatiseert deze stap en herkent bekende poisoning-patronen.
  • Tel de werkwoorden. Zet op een rij wat de server werkelijk aanbiedt en leg dat naast de klus waarvoor je hem inhuurt. Een weerbericht opvragen vereist geen toegang tot je bestandssysteem. Bij een zoekserver die alleen leest, heeft een execute-tool niets te zoeken. Kijk ook naar de imports: een pakket dat child_process binnentrekt of shell-commando's draait voor een taak die geen van beide nodig heeft, vertelt je iets.
  • Pin de versie. De meeste voorbeeldconfigs zetten servers erin als npx -y een-mcp-server, en dat haalt bij elke start van je client de nieuwste release op. Dat is een auto-updatekanaal dat recht op je agent gericht staat, en het is exact de route waarlangs de backdoor in postmark-mcp binnenkwam. Pin de versie in je config, en behandel een nieuwe release zoals elke andere dependency-update: eerst de diff bekijken, dan pas de pin verschuiven.
  • Let op waar je secrets heengaan. Het env-blok in je MCP-config geeft die server een credential. Zorg dat het er een is die je kunt missen: een aparte key per server, beperkt tot wat de tools minimaal nodig hebben, en intrekbaar zonder dat de rest omvalt. Je accountbrede admin-token hoort niet thuis in een wrapper die je in een registry vond.
  • Let op de combinatie. Simon Willison noemt het de lethal trifecta: toegang tot privédata, blootstelling aan niet-vertrouwde content, en een kanaal naar buiten. Elke server op je lijst kan afzonderlijk in orde zijn terwijl de verzameling het lek is, want één geïnjecteerde instructie kan ze aan elkaar rijgen. Houd servers die bij secrets kunnen uit de sessies waarin je agent niet-vertrouwde webcontent leest, en je hebt de keten op zijn goedkoopste schakel doorbroken.

Opzoeken, niet afvinken

Het eerlijke bezwaar tegen elke checklist: niemand loopt hem twee keer per week na. Dat is het gat dat ik met MCP Observatory wilde dichten. Zoek een server op voordat je hem installeert en de eerste drie controles staan al op je scherm: wie hem publiceert en of de naam een bekende partij nabootst, een samengestelde risicoscore op basis van statische analyse, CVE-feeds en signalen van verwaarlozing, en, voor het rug-pull-scenario, capability-drift tussen releases, zodat een tool-lijst die opeens een nieuw werkwoord krijgt als diff verschijnt in plaats van als verrassing.

De minuten die overblijven besteed je aan de controles die alleen jij kunt doen: of de werkwoorden bij de klus passen, en of de key die je zo in je config plakt er een is die je morgen kunt intrekken zonder dat het je een rotmiddag kost.

npm had event-stream nodig voordat iemand naar zijn dependency-tree keek. MCP heeft zijn event-stream-moment net gehad, en het kostte driehonderd organisaties hun uitgaande mail. De rekensom is simpel: een server controleren kost tien minuten, elke credential roteren waar je agent ooit bij kon kost een stuk meer. De zestiende release is degene die jou te pakken krijgt. Lees de eerste vijftien alsof ze dat weten.