Zabezpieczanie agentów AI za pomocą narzędzi Laravel MCP

Przyznanie agentowi AI dostępu do Twojej aplikacji za pomocą MCP jest jak wręczenie komuś pęku kluczy. Jeśli nie ustalisz zasad, może on otworzyć niewłaściwe drzwi.

Niedawno zbudowałem narzędzia MCP dla aplikacji Laravel typu multi-tenant. Miałem jeden cel: pozwolić agentowi sterować aplikacją, nie pozwalając mu jednocześnie na wgląd w dane innych użytkowników.

Problem z narzędziami MCP

Każde narzędzie MCP to punkt końcowy (endpoint). Agent wywołuje narzędzie, a Twój serwer wykonuje kod. W aplikacji typu multi-tenant każde narzędzie musi odpowiedzieć na dwa pytania:

  • Czy masz uprawnienia, aby to zrobić?
  • Czy masz uprawnienia, aby zrobić to w tej konkretnej organizacji?

Jeśli pominiesz jedno z nich, dojdzie do wycieku danych.

Dlaczego standardowy model multi-tenancy tutaj zawodzi

W normalnej aplikacji webowej masz sesje. Używasz globalnych zakresów (global scopes), aby filtrować dane według ID organizacji. Działa to dlatego, że „aktualna organizacja” jest zawsze zapisana w sesji.

Narzędzia MCP nie korzystają z sesji. Korzystają z tokenów. Nie ma middleware, który ustawiałby kontekst najemcy (tenant context). Jeśli polegasz na globalnym zakresie, który szuka sesji, nie znajdzie on niczego. W rezultacie może zwrócić wszystkie wiersze z Twojej bazy danych. To cichy wyciek danych.

Rozwiązanie: Jawne filtrowanie

Nigdy nie polegaj na kontekście otoczenia (ambient scope) przy uwierzytelnianiu tokenem. Zawsze stosuj jawne filtrowanie.

Stworzyłem jedną cechę (trait), aby tym zarządzać:

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();
    }
}

To podejście opiera się na czterech zasadach:

  • Używaj UUID: Nigdy nie używaj ID z automatycznym inkrementem. Agenci nie powinni móc zgadywać ID poprzez zmianę liczby.
  • Pojedyncze źródło prawdy (Single Source of Truth): Filtr organizacji znajduje się w jednym traicie. Każde narzędzie go używa.
  • Ponowne wykorzystanie uprawnień: Nie wymyślaj nowych uprawnień dla agentów. Używaj tych samych ciągów znaków uprawnień, których używa Twoja aplikacja webowa. Zapobiega to sytuacji, w której agent ma większą władzę niż użytkownik-człowiek.
  • Oznaczanie efektów ubocznych: Używaj adnotacji, aby wskazać, czy narzędzie jest tylko do odczytu, czy umożliwia zapis.

Testowanie granic

Musisz przetestować ścieżkę negatywną. Nie testuj tylko tego, czy narzędzie działa. Przetestuj, czy użytkownik z Organizacji A nie może zobaczyć danych z Organizacji B.

Jeśli agent spróbuje uzyskać dostęp do UUID innego najemcy, narzędzie powinno zwrócić „not found”. Nie powinno informować agenta, że dane istnieją, ale należą do kogoś innego.

Traktuj każde narzędzie AI jako niezaufany punkt końcowy. Dyscyplina to jedyny sposób na utrzymanie bezpieczeństwa danych.

Źródło: https://dev.to/nasrulhazim/giving-an-ai-agent-the-keys-without-giving-it-the-building-rbac-org-scoped-mcp-tools-in-laravel-43oi