Naar inhoud

MCP

Claude Code en MCP-servers auditen in self-hosted omgevingen

Door Olivares AI 6 min leestijd

Een platformteam rolt Claude Code uit naar een dozijn engineers. Om het bruikbaar te maken, koppelen ze het aan een paar MCP-servers: één die de monorepo leest, één die een reporting-replica bevraagt, één die tickets aanmaakt. Binnen een week leest een agent broncode, raakt een database aan en roept interne tools aan — en niemand kan de vraag beantwoorden die een auditor uiteindelijk zal stellen: welke agent deed wat, met welke resource, en kunt u bewijzen dat het achteraf niet is gewijzigd?

Dit is geen hypothetisch gat. Onafhankelijk branche-onderzoek (CSA/Token, n=418) wees uit dat rond de 82% van de organisaties AI-agents heeft draaien waarvan ze het bestaan niet kennen, terwijl slechts ongeveer 21% er een realtime inventaris van bijhoudt. Claude Code en MCP zijn precies het soort capaciteit dat snel landt en het auditverhaal voorbijstreeft. Het goede nieuws: een verdedigbaar controlespoor is volledig binnen uw eigen perimeter haalbaar, zonder dat er payloads of secrets uit verdwijnen.

Waarom de voor de hand liggende opzet een audit niet doorstaat

De gebruikelijke eerste uitrol deelt één credential. Elke Claude Code-instantie authenticeert zich bij de MCP-laag en bij downstream-databases als hetzelfde serviceaccount — mcp-runner, ci-bot, iets generieks. Het werkt, en het vernietigt stilletjes alle toeschrijving.

Wanneer tien agents als één principal handelen, toont het database-auditlog tien schrijfacties van mcp-runner en niets meer. U kunt niet zien welke sessie van welke engineer de UPDATE heeft uitgegeven, of die uit een interactieve Claude Code-prompt kwam dan wel uit een onbewaakte job, of welke MCP-tool in het pad zat. Onafhankelijk onderzoek (Optro) becijfert het aandeel organisaties dat de actie van een agent kan herleiden tot een persoon op ongeveer 28%. Een gedeeld serviceaccount is een structurele reden waarom toeschrijving instort: het auditlog kan tonen wat er gebeurde, maar nooit welke agent het deed.

Het tweede falen is integriteit. Zelfs teams die per actie loggen, schrijven doorgaans naar een muteerbare opslag. Als de logs in hetzelfde systeem leven dat een aanvaller (of een agent met een bug) kan bereiken, is “we hebben logs” niet hetzelfde als “we hebben bewijs”. Een auditor maakt dat onderscheid scherp.

Identiteit per agent is het fundament

Alles stroomafwaarts hangt af van toeschrijving, dus regel identiteit eerst. In plaats van één gedeeld token geeft u een aparte, kortlevende identiteit per agent uit — idealiter per sessie. De identiteit reist mee met het verzoek de MCP-server in en naar elke resource die de agent bereikt, zodat de principal die bij de database wordt vastgelegd de agent is en niet een generieke runner.

Dit is wat least-privilege betekenisvol maakt. Een reporting-agent kan worden vastgepind op alleen-lezen op de reporting-replica; een release-agent krijgt schrijfrechten alleen op de artefacten die hij bezit. Nu is één waargenomen schrijfactie buiten die envelop een precies, toeschrijfbaar signaal in plaats van ruis in een gedeeld account. Uitgedrukt als beleid is de bedoeling onomwonden:

agent "reporting-assistant" {
  # Claude Code session via the reporting MCP server
  resource "prod-postgres/reporting_replica" {
    access     = "read"      # SELECT only
    deny       = ["write", "ddl"]
  }
  resource "s3://billing-exports" {
    access = "read"
  }
  on_violation {
    action = "block_and_alert"   # refuse at access time, not just log
  }
}

Het gaat niet om de syntaxis — het gaat erom dat het beleid de agent benoemt, de resource benoemt en lezen van lezen/schrijven scheidt. Die scheiding is waar het om draait.

Behandel MCP-annotaties als niet-vertrouwde signalen

MCP-tools kunnen zichzelf beschrijven met annotaties zoals readOnlyHint en destructiveHint. Die zijn werkelijk nuttig voor triage — een tool die zichzelf als destructief aanmerkt, verdient een strakker beleid. Maar de MCP-specificatie is expliciet dat het hints zijn, en clients mogen er niet op vertrouwen voor beveiligingsbeslissingen. Ze zijn afkomstig van de server, en dat is nu juist datgene wat u audit. Een tool kan readOnlyHint: true declareren en toch een schrijfactie uitvoeren, of dat nu door een bug, een verkeerde configuratie of opzettelijke ontwijking gebeurt.

De juiste houding is dus staving, geen vertrouwen. Neem de annotatie als een bewering en toets die vervolgens tegen de grondwaarheid uit een laag die de tool niet beheerst:

  • Database-auditlogs (bijvoorbeeld PostgreSQL pgAudit) vertellen u of een SELECT of een UPDATE daadwerkelijk is uitgevoerd.
  • OpenTelemetry-spans van de MCP-server en downstream-services tonen de call graph en de uitgevoerde operaties.
  • eBPF-signalen op kernelniveau vormen het anti-ontwijkingsvangnet: een write-syscall naar een bestand of socket is op kernelniveau waarneembaar, ongeacht wat de tool in user space beweerde.

Wanneer de annotatie zegt alleen-lezen en de kernel een schrijfactie zag, is die tegenstrijdigheid de kernbevinding — een readOnlyHint-tool die naar prod-postgres schreef is precies de least-privilege-drift die het waard is om iemand voor wakker te maken. Het verschil tussen wat het beleid toestond en wat de collectors waarnamen is waar het echte risico zit.

De ledger die een auditor accepteert

Een controlespoor is alleen bewijs als het manipulatiebestendig is. Schrijf elke gebeurtenis naar een append-only, hash-geketende ledger: elk record bevat de hash van het vorige, zodat elke bewerking of verwijdering stroomafwaarts de keten breekt en detecteerbaar is. Elke regel schrijft de actie toe aan de specifieke agent, benoemt de resource, legt lezen versus lezen/schrijven vast en draagt een betrouwbaarheidsniveau — attributed wanneer identiteit en uitkomst beide gestaafd zijn, approximate wanneer iets afgeleid moest worden. De betrouwbaarheid wordt eerlijk getoond; een approximatieve match wordt nooit voorgesteld als een bewezen match.

ts=2026-06-08T09:14:02Z agent=reporting-assistant@s3f1 tool=sql-read     resource=prod-postgres/reporting_replica  op=R   outcome=allow   conf=attributed   prev=8a1c…
ts=2026-06-08T09:14:05Z agent=reporting-assistant@s3f1 tool=export-writer resource=s3://billing-exports          op=R   outcome=allow   conf=attributed   prev=2f90…
ts=2026-06-08T09:17:48Z agent=data-export-job@b22e     tool=sql-write     resource=prod-postgres/customers          op=RW  outcome=DENY    conf=attributed   prev=c7d3…  policy=read_only_violation

Die derde regel is waar een auditor om geeft: een schrijfpoging op een tabel waarvoor de agent geen schrijfrecht had, geweigerd op het moment van toegang, toegeschreven aan een benoemde agent en verankerd in de keten. Omdat het beleid wordt afgedwongen wanneer de toegang plaatsvindt — en niet pas achteraf wordt gelogd — is de weigering een control, geen post-mortem.

Nog twee eigenschappen maken dat het controlespoor standhoudt. Geprivilegieerde inzagen worden zelf geaudit: het bekijken van de toegangskaart wordt vastgelegd, zodat “wie zag wat” beantwoordbaar is. En bewijsexport is manipulatiebestendig — u overhandigt een auditor een ondertekende doorsnede van de keten die hij onafhankelijk kan verifiëren, in plaats van een CSV die hij op goed vertrouwen moet aannemen.

EigenschapGedeeld serviceaccountIdentiteit per agent + hash-geketende ledger
ToeschrijvingEén principal voor alle agentsActie gekoppeld aan de specifieke agent/sessie
Lezen vs schrijvenSamengevoegdOnderscheiden en beleidsgetoetst
IntegriteitMuteerbare logsAppend-only, keten breekt bij bewerking
Audit-klare exportCSV op vertrouwenOndertekende, onafhankelijk verifieerbare doorsnede

Waarom self-hosted hier van belang is

Dit alles werkt zonder dat er iets uw netwerk verlaat. De collector observeert — logs, OpenTelemetry, eBPF als vangnet op kernelniveau — in plaats van in het datapad van de agent te zitten, zodat hij bij uitval nooit de agent of het productieverzoek daarachter breekt. De ledger slaat toegangsrelaties op, geen payloads: hij legt vast dat reporting-assistant de reporting_replica las, niet de rijen die werden teruggegeven. Invoer die secrets of persoonsgegevens kan bevatten, wordt geredigeerd en op secrets gescand voordat er iets wordt weggeschreven. Voor air-gapped, AVG-gebonden of door dataresidentie beperkte omgevingen is dat het verschil tussen een auditverhaal dat u kunt verdedigen en een dat u niet kunt verdedigen: niets over uw gebruik van Claude Code en MCP belt naar huis, omdat het systeem de data om te beginnen nooit ziet.

Claude Code en MCP zijn het waard om uit te rollen. Ze hebben alleen een controlespoor nodig dat op dezelfde manier is gebouwd als u dat voor elke andere geprivilegieerde automatisering zou doen — identiteit eerst, uitkomsten gestaafd, bewijs verankerd. Wilt u zien hoe de toegangskaart en de manipulatiebestendige ledger samenkomen, dan gaan het beveiligingsmodel en het productoverzicht dieper op elk in.

Veelgestelde vragen

Kan ik de readOnlyHint van een MCP-tool vertrouwen als bewijs dat een actie alleen-lezen was?

Nee. De MCP-specificatie stelt dat toolannotaties zoals readOnlyHint en destructiveHint hints zijn en als niet-vertrouwd moeten worden behandeld, omdat ze van de server komen en niet van een afdwingingslaag. Gebruik ze om te triëren en om tegenstrijdigheden te signaleren, maar bewijs de werkelijke lees-/schrijfuitkomst met telemetrie of signalen op kernelniveau (OpenTelemetry-spans, database-auditlogs, eBPF). Vertrouw op de gestaafde uitkomst, niet op de annotatie.

Hoe schrijf ik een Claude Code-actie toe aan een specifieke agent in plaats van aan een gedeeld serviceaccount?

Geef een aparte, kortlevende identiteit per agent of per sessie uit in plaats van één gedeeld token. Wanneer de agent een database of een MCP-server bereikt, reist die identiteit mee met het verzoek, zodat de auditledger vastlegt welke agent wat heeft gedaan. Een gedeeld serviceaccount klapt elke agent samen tot één principal en maakt least-privilege per agent en manipulatiebestendige toeschrijving achteraf onmogelijk.

Bekijk wat uw agents kunnen bereiken

Olivares AI is het open, self-hosted platform voor uw AI-landschap. Implementeer het op uw eigen infrastructuur en krijg de toegangskaart waar uw security- en platformteams al om vragen.