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
SELECTof eenUPDATEdaadwerkelijk 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.
| Eigenschap | Gedeeld serviceaccount | Identiteit per agent + hash-geketende ledger |
|---|---|---|
| Toeschrijving | Eén principal voor alle agents | Actie gekoppeld aan de specifieke agent/sessie |
| Lezen vs schrijven | Samengevoegd | Onderscheiden en beleidsgetoetst |
| Integriteit | Muteerbare logs | Append-only, keten breekt bij bewerking |
| Audit-klare export | CSV op vertrouwen | Ondertekende, 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.