JIT
← Notebook
Idea notes AI AgentsSecurityIdentity

De confused deputy komt ook voor je AI-agents

Wanneer een orchestrator-agent werk doorgeeft aan een sub-agent, geeft hij stilletjes soms een token mee dat veel meer kan dan die sub-agent zou mogen. Dit is het token-chain-risico, de Kagenti-blueprint van IBM en Red Hat, en een zero-trust-aanpak die je kunt draaien zonder je hele fleet naar Kubernetes te verhuizen.

Ik draai een kleine vloot AI-agents over de homelab — één elk voor systemen, netwerk, security, identity en endpoints. Ze delen een framework, en steeds vaker geeft een coordinator-agent werk door aan de specialisten. Handig. Tot ik de saaie auditorsvraag stelde:

Wanneer de coordinator “check de firing alerts” delegeert aan de security-agent, welke credential reist er mee met dat verzoek — en wat kan die credential nog meer?

In het naïeve ontwerp is het antwoord ongemakkelijk. De coordinator geeft hetzelfde token door dat hij al vasthield. De security-agent bezit nu een credential dat óók de UniFi-controller van de netwerkagent, de Proxmox-API en de secrets store kan bereiken — alles. Niemand bedoelde dat. Het token reisde gewoon mee.

Dat is de confused deputy: een component mag zijn authority gebruiken namens iets dat die nooit had mogen hebben. De framing van de OAuth-werkgroep voor de agent-variant is scherp — het token dat de beschikbaarheid van een vlucht checkt, autoriseert óók de aankoop en het debiteren van de corporate card. De Model Context Protocol-spec is helder over het mechanisme erachter en verbiedt token passthrough ronduit. Hier is de vorm van de fix op één pagina, daarna de wandeling erlangs.

scope wordt smaller bij elke hop — nooit breder ⟳ bij elke hop opnieuw geëxchanged bij de IdP Menselijke principal · jij autoriseert het verzoek CONTROLEPUNT 1 Authentik (IdP) — token authority RFC 8693 token exchange · short-lived · scoped · audience-bound geeft een token uit dat smaller is dan dat van de caller token A · aud=core · scope=triage · act=[jij] Core / orchestrator-agent jitc-agent-core token B · aud=sub-agent · scope=read:alerts · act=[jij→core] CONTROLEPUNT 2 agent-core validator — draait bij elke call ✔ JWT-handtekening verifiëren (JWKS) ✔ audience == ik ✔ exp / nbf ✔ de act-chain aflopen · scope mag enkel SMALLER, nooit breder Policy engine — OpenFGA / OPA / Cedar “mag core, namens jou, read:alerts op sec-eng?” ✔ toegestaan Sub-agent — bv. security-engineer MCP stdio server token C · aud=wazuh · scope=read:alerts · act=[jij→core→sub] Downstream service Wazuh · UniFi · Proxmox — ziet enkel een token scoped tot zichzelf
Twee controlepunten: de IdP geeft een downscoped token uit (1), en een validator checkt de hele delegation chain vóór er iets draait (2). Scope wordt op weg naar beneden enkel smaller.

De blueprint waar iedereen naar wijst: Kagenti

Wie de canonieke open-source-oplossing zoekt, belandt bij Kagenti (rebrandt naar “Rosso”) — een project van IBM Research en Red Hat. Het doet de juiste dingen. Elke agent krijgt een cryptografische workload identity via SPIFFE/SPIRE, op short-lived, automatisch geroteerde certificaten, zodat welke agent belt hier echt? met wiskunde wordt beantwoord in plaats van met een gedeelde API-key. Brede tokens worden bij elke hop geruild voor short-lived, scoped, audience-bound tokens via OAuth 2.0 token exchange (RFC 8693) in Keycloak — een sub-agent kan letterlijk geen permissions krijgen die de orchestrator zelf niet al heeft. Een gateway doet die exchange bij elke tool call, met service-mesh-mTLS tussen de agents. Het is op dit moment de meest complete belichaming van agentic zero-trust in de open. Bestudeer het.

De reality check (de voetnoot van de auditor)

Dit is het stuk dat de launch-posts overslaan: Kagenti is een Kubernetes-control-plane, en het is nog vroeg. Het veronderstelt Istio, Keycloak, SPIRE, sidecar-injectie en het A2A-protocol; de builds die mensen testen zijn alpha. Ben je Red Hat dat een platform shipt, prachtig. Draai je Python-CLI-agents en lokale MCP-servers — zoals de meeste mensen die er vandaag mee experimenteren — dan is Kagenti adopteren geen “tool toevoegen”, het is je hele fleet naar Kubernetes verhuizen. En een security-grens pinnen op alpha-software is net wat een gezonde dependency-policy je afraadt.

Dus adopteer niet de runtime. Adopteer de aanpak. (En let op de naamsbotsing: er bestaat een apart, gelijkaardig genaamd CNCF-project kagent, van Solo.io — ander team, andere codebase. Makkelijk te verwarren bij het zoeken.)

De aanpak die je echt nodig hebt: twee controlepunten

Strip het probleem tot op het bot en er zijn maar twee taken — de twee omkaderde boxen hierboven.

Controlepunt 1 — geef het juiste token uit, aan de bron én bij elke hop. In plaats van door te geven wat hij vasthoudt, vraagt een agent aan de identity provider om zijn token te ruilen voor een nieuw token dat scoped is tot enkel deze taak en audience-bound aan precies de volgende service. Dat is RFC 8693, en je draait vrijwel zeker al een IdP die dat kan — ik gebruik Authentik. Geen Kubernetes nodig.

Controlepunt 2 — valideer de chain en autoriseer, op het punt van gebruik. Vóór er iets gebeurt, draait elke agent en tool dezelfde check: verifieer de handtekening van het token, bevestig dat het de bedoelde audience is, bevestig dat het niet verlopen is — loop dan de delegation chain af (de act-claim: jij → coordinator → security-agent) en bevestig dat scope enkel smaller wordt. Stel daarna een policy engine — OpenFGA, OPA of Cedar — de echte vraag: mag de coordinator, namens mij, alerts lezen op de security-agent?

Zet die validatie in de gedeelde agent-core, één keer, als middleware op de BaseSkill-basisklasse — zodat elke agent het erft in plaats van dat elke repo het opnieuw bouwt. De chain wordt end-to-end verifieerbaar, en te brede tokens worden structureel onmogelijk in plaats van enkel afgeraden.

Hier is het hele punt in twee regels:

ANTI-PATTERN  (token passthrough = confused deputy)
  jij ─[breed]→ core ─[ZELFDE]→ sub-agent ─[ZELFDE]→ Wazuh + UniFi + Proxmox + secrets …
                     ongewijzigd doorgegeven       alles erft alles

TARGET  (scoped exchange bij elke hop)
  jij ─[A: triage]→ core ─[B: read:alerts@sec-eng]→ sub-agent ─[C: read:alerts@wazuh]→ enkel Wazuh
       scope wordt smaller ↓ bij elke hop · elk token audience-bound · de chain is verifieerbaar uit act

Het ene dat je vandaag al kunt doen (zonder nieuwe infrastructuur)

Vóór al die machinerie: adopteer één ontwerpregel — elke agent houdt zijn eigen smal-scoped credential vast en krijgt nooit een breed upstream-token. Dat doodt het passthrough-risico by construction, vandaag, zonder iets nieuws te installeren. Het is de logische volgende stap vanuit waar de fleet zijn secrets al bewaart — zie Skills, MCP en waar de credentials thuishoren. De token-exchange- en policy-laag is de hardening waar je naartoe bouwt; “stop met tokens doorgeven” is de fix die je deze namiddag shipt.

Waar dit naartoe gaat (en waarom ik er nog niet op inzet)

Er is veelbelovend standaardenwerk — IETF-drafts over attenuating agent tokens die bij elke hop cryptografisch en offline smaller worden, verifieerbaar uit enkel de root-key. Conceptueel perfect. Maar het zijn vroege individuele Internet-Drafts, geen aangenomen standaarden, en een productiegrens bouwen op een draft van drie maanden oud is de bleeding edge die ik huur, niet de baseline die ik bezit. Volg ze; reken er niet op. De saaie, beschikbare combinatie — RFC 8693 exchange, audience binding, een act-chain-validator en een policy engine — brengt je al een heel eind, op een stack die je al draait.

De interessante vraag bij AI-agents was nooit “wat kunnen ze?” Het is de auditorsvraag: wat mógen ze, namens wie, en kun je het bewijzen? Krijg de token chain juist en de rest van het agentic-security-gesprek wordt een stuk rustiger.

(Dit zit één laag boven hoe de agent-vloot bedraad is — dezelfde fleet, nu kijkend naar wat er tussen de agents reist in plaats van hoe ze gestapeld zijn.)