Обеспечение безопасности ИИ-агентов с помощью инструментов 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». Он не должен сообщать агенту, что данные существуют, но принадлежат кому-то другому.
Относитесь к каждому ИИ-инструменту как к недоверенному эндпоинту. Дисциплина — единственный способ обеспечить безопасность ваших данных.
