Обеспечение безопасности ИИ-агентов с помощью инструментов Laravel MCP

Предоставление ИИ-агенту доступа к вашему приложению через MCP — это всё равно что вручить кому-то связку ключей. Если не установить правила, он может открыть не те двери.

Недавно я разрабатывал MCP-инструменты для мультиарендного (multi-tenant) приложения на Laravel. Моя цель была проста: позволить агенту управлять приложением, не давая ему доступа к чужим данным.

Проблема с MCP-инструментами

Каждый MCP-инструмент — это эндпоинт. Агент вызывает инструмент, и ваш сервер выполняет код. В мультиарендном приложении каждый инструмент должен отвечать на два вопроса:

  • Разрешено ли вам это делать?
  • Разрешено ли вам делать это именно в этой организации?

Если упустить один из них, произойдет утечка данных.

Почему стандартная мультиарендность здесь не работает

В обычном веб-приложении используются сессии. Вы используете глобальные области видимости (global scopes) для фильтрации данных по ID организации. Это работает, потому что «текущая организация» всегда хранится в сессии.

MCP-инструменты не используют сессии. Они используют токены. Здесь нет middleware для установки контекста арендатора (tenant context). Если вы полагаетесь на глобальную область видимости, которая ищет сессию, она ничего не найдет. В результате может быть возвращена каждая строка из вашей базы данных. Это скрытая утечка данных.

Решение: Явная фильтрация

Никогда не полагайтесь на неявную область видимости (ambient scope) при использовании токен-аутентификации. Фильтруйте данные явно каждый раз.

Я создал один трейт для обработки этой задачи:

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

Этот подход следует четырем правилам:

  • Используйте UUID: Никогда не используйте автоинкрементные ID. Агенты не должны иметь возможности угадать ID, просто меняя число.
  • Единый источник истины: Фильтр организации находится в одном трейте. Каждый инструмент использует его.
  • Повторное использование прав доступа: Не придумывайте новые разрешения для агентов. Используйте те же строки разрешений, что и ваше веб-приложение. Это предотвратит ситуацию, когда агент получает больше полномочий, чем обычный пользователь.
  • Помечайте побочные эффекты: Используйте аннотации, чтобы показать, является ли инструмент доступным только для чтения или с возможностью записи.

Тестирование границ

Вы должны тестировать негативные сценарии. Не проверяйте только то, работает ли инструмент. Проверьте, что пользователь из Организации А не может видеть данные Организации Б.

Если агент пытается получить доступ к UUID другого арендатора, инструмент должен вернуть «not found». Он не должен сообщать агенту, что данные существуют, но принадлежат кому-то другому.

Относитесь к каждому ИИ-инструменту как к недоверенному эндпоинту. Дисциплина — единственный способ обеспечить безопасность ваших данных.

Source: https://dev.to/nasrulhazim/giving-an-ai-agent-the-keys-without-giving-it-the-building-rbac-org-scoped-mcp-tools-in-laravel-43oi