AI-agenten beveiligen met Laravel MCP-tools
Een AI-agent toegang geven tot je app via MCP is als het overhandigen van een sleutelbos aan iemand. Als je geen regels instelt, openen ze misschien de verkeerde deuren.
Onlangs heb ik MCP-tools gebouwd voor een multi-tenant Laravel-app. Ik had één doel: de agent de app laten aansturen zonder dat deze de gegevens van iemand anders kan inzien.
Het probleem met MCP-tools
Elke MCP-tool is een endpoint. Een agent roept een tool aan, en je server voert code uit. In een multi-tenant-app moet elke tool twee vragen beantwoorden:
- Mag je dit doen?
- Mag je dit doen binnen deze specifieke organisatie?
Als je er één mist, lek je gegevens.
Waarom standaard multi-tenancy hier tekortschiet
In een normale web-app werk je met sessies. Je gebruikt global scopes om gegevens te filteren op basis van een organisatie-ID. Dit werkt omdat de "huidige organisatie" altijd in de sessie zit.
MCP-tools gebruiken geen sessies. Ze gebruiken tokens. Er is geen middleware om de tenant-context in te stellen. Als je vertrouwt op een global scope die naar een sessie zoekt, vindt deze niets. Het kan vervolgens elke rij in je database teruggeven. Dat is een stilzwijgend datalek.
De oplossing: expliciete filtering
Vertrouw nooit op ambient scope bij token-authenticatie. Filter elke keer expliciet.
Ik heb een enkele trait gemaakt om dit af te handelen:
trait ResolvesOrgEvents
{
protected function resolveOrgEvent(Authenticatable $user, string $uuid): ?Event
{
if (empty($user->organization_id)) {
return null;
}
return Event::query()
->withOrganization($user->organization_id)
->where('uuid', $uuid)
->first();
}
}
Deze aanpak volgt vier regels:
- Gebruik UUID's: Gebruik nooit auto-increment ID's. Agents mogen ID's niet kunnen raden door een getal te veranderen.
- Single Source of Truth: De organisatie-filter staat in één trait. Elke tool gebruikt deze.
- Hergebruik permissies: Verzin geen nieuwe permissies voor agents. Gebruik dezelfde permission strings als je web-app. Dit voorkomt dat de agent meer macht krijgt dan de menselijke gebruiker.
- Markeer side effects: Gebruik annotaties om aan te geven of een tool alleen-lezen of schrijfbaar is.
De grenzen testen
Je moet het negatieve pad testen. Test niet alleen of de tool werkt. Test of een gebruiker van Organisatie A de gegevens van Organisatie B niet kan zien.
Als een agent probeert een UUID van een andere tenant te benaderen, moet de tool "not found" teruggeven. Het mag de agent niet vertellen dat de gegevens bestaan, maar aan iemand anders toebehoren.
Behandel elke AI-tool als een onbetrouwbaar endpoint. Discipline is de enige manier om je gegevens veilig te houden.
