Как стать автором
Обновить
73.65
Raft
AI решения для бизнеса

Lasso MCP Gateway: щит между AI-агентами, тулами и вашими секретами?

Время на прочтение6 мин
Количество просмотров352

Введение

С развитием AI-агентов и Model Context Protocol (MCP) актуальной становится проблема безопасности при работе с различными инструментами. Что если ваш AI-агент случайно прочитает конфиденциальный файл с токенами доступа и "случайно" поделится ими с вами в своем ответе, а учитывая логирование ваших запросов, он точно попадет на сервер провайдера вашего агента, а возможно еще и IDE, в которой этот агент и обитает, это создаст ряд неприятностей.

Ярким примером тулы, которая выполняет поиск по вашим локальным файлом является mcp-filesystem. Один шаг не туда и вам придется бежать за ревоком токена, а если он еще и от организации, ваши админы явно не скажут вам спасибо.

Не забываем про то, как у XAI токен просто лежал на github пару месяцев: статья

Для решения этой проблемы команда Lasso Security разработала MCP Gateway — прокси-сервер, который встает между AI-агентом и MCP-тулами, обеспечивая санитизацию чувствительной информации.

В этой статье я поделюсь результатами тестирования Lasso MCP Gateway в двух сценариях: интеграция с Cursor IDE и локальная реализация с собственным агентом на PydanticAI.

Что умеет Lasso MCP Gateway

1) Перехватывает вызовы всех MCP-инструментов перед их выполнением
2) Маскирует в basic вариации (бесплатной):

  • azure client secret

  • github tokens

  • github oauth

  • gcp api key

  • aws access token

  • jwt token

  • gitlab session cookie

  • huggingface access token

  • microsoft teams webhook

  • slack app token\

Есть интеграция с presidio и самим lasso. Позволяет логировать вызовы через xetrack

Общий принцип работы

Идея MCP-gateway заключается в том, что он становится неким прокси между агентом и тулами. То есть он подключается не просто как отдельный MCP тул, а как MCP-тул, под которым работают другие тулы. То есть любой вызов плагина по типу read_file create_file и тд будет происходит после того как mcp-gateway дал условное одобрение и провел санитизацию.

схема работы из репозитория на github
схема работы из репозитория на github

Эксперименты

Тестирование в Cursor

Настройка и установка Следуя примеру из readme.md я подключил mcp-gateway к cursor, добавил путь к логированию через xetrack. Как выглядит:

{
  "mcpServers": {
    "mcp-gateway": {
      "command": "uvx",
      "args": [
        "mcp-gateway",
        "--mcp-json-path",
        "/home/user/.cursor/mcp.json",
        "--plugin",
        "basic",
        "--plugin", 
        "xetrack"
      ],
      "env": {
        "XETRACK_LOGS_PATH": "logs/",
        "XETRACK_DB_PATH": "tracing.db"
      },
      "servers": {
        "filesystem": {
          "command": "npx",
          "args": [
            "-y",
            "@modelcontextprotocol/server-filesystem",
            "."
          ]
        }
      }
    }
  }
}

Эксперимент 1: Чтение файла с HuggingFace токеном

Создал файл

echo 'HF_TOKEN = "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"' > tokens.txt

в нем теперь хранится выдуманный токен из Huggingface

Следуя снова же примеру из readme.md пишу запрос

запрос в самом верху
запрос в самом верху

Cursor получил уже очищенный контекст и вернул мне <HUGGINGFACE_TOKEN>.

Подробнее:

в тулу передался параметр:

{
 
"path": "~/lasso-mcp/sts/tokens.txt"
 
}

внутри tokens.txt хранится мой выдуманный hf token

тула произвела очистку:

{ "_meta": null, "content": [
{ "type": "text", "text": "HF_TOKEN = \"<HUGGINGFACE_TOKEN>\n", "annotations": null } ], "isError": false }

затем тула вернула респанс cursor агенту и он вернул очищенный токен:

<HUGGINGFACE_TOKEN>

Эксперимент 2: Обход через контекст агента

Интересный нюанс: когда я попросил агента создать файл с кодом, передав токен непосредственно в чате, MCP Gateway не смог заблокировать эту операцию. Санитизация происходит только при чтении файлов, но не при генерации/обработке моего запроса
(что в принципе и не удивительно).

пишем явно наш ключ в диалоге
пишем явно наш ключ в диалоге
Cursor создал файл и явно вписал туда мой токен
Cursor создал файл и явно вписал туда мой токен

Когда я позже попросил прочитать созданный файл, MCP Gateway снова сработал корректно. Однако Cursor "помнил" о токене из контекста беседы и просто обновил информацию, вернув мой токен мне же обратно.

прочитал файл
прочитал файл
MCP-Gateway подчистил токен, но Cursor то помнит наш диалог
MCP-Gateway подчистил токен, но Cursor то помнит наш диалог
финальный ответ и слитый токен
финальный ответ и слитый токен

Эксперимент 3

Создаем .env файл с выдуманным ключом от OpenAI: ключ:

OPENAIKEY=sk-qwejxakdjruewhjnsvasdj

Результат работы агента с явным вызовом mcp-gateway через наш запрос:

Слитый токен
Слитый токен

В общем говоря, если ваш токен не находится в списке токенов из начала, не надейтесь, что вам повезет и он не будет слит.

Local Implementation

Тестовые данные

Для локальной реализации был создан файл с 5-ю вариациями токенов:

HF_TOKEN = "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"
OPENAI_TOKEN = "sk-proj-SDASDFASDSDDSFDFSDADSdfsdfaHAJKDD5JASMDBXAHEG4123XDLKCXCDFSDFSAZXCN"
JWT_TOKEN ="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik..."
GITHUB_TOKEN_CLASSIC = "ghp_mS5asdaSJASHDqwDSAD4KD"
GITHUB_TOKEN = "github_pat_33SDSDJKJXKCJXIHFGAdfdsfkS4333Nwqe13weqeirurururrrr"

MCP

Не забудьте установить mcp-gateway через uv/pip или используйте uvx

Для запуска MCP-Gateway ему обязательно нужен mcp.json

{
    "mcpServers": {
        "mcp-gateway": {
            "command": "uv",
            "args": [
                "run",
                "mcp-gateway",
                "-p",
                "basic",
                "-p",
                "xetrack"
            ],
            "env": {
                "XETRACK_DB_PATH": "tracing.db",
                "XETRACK_LOGS_PATH": "logs/"               
            },
            "servers": {
                "filesystem": {
                    "command": "npx",
                    "args": [
                        "-y",
                        "@modelcontextprotocol/server-filesystem",
                        "."
                    ]
                }
            }
        }
    }
}

Агент

Реализовал простого агента через pydantic AI, с подключением к Lasso MCP-Gateway в базовой реализации (бесплатной) и логированием через xetrack

from typing import Optional
from pydantic_ai import Agent
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
from pydantic_ai.mcp import MCPServerStdio
import os
from dotenv import load_dotenv
import asyncio
 
load_dotenv()
 
async def get_custom_openai_provider_response(
    model_name: str,
    query: str,
    provider_url: Optional[str] = None,
    system: Optional[str] = "",
    api_key: Optional[str] = None,
) -> str:
    """
    Func to call custom open ai provider, using `provider_url` if needed
    """
    lasso_gateway = MCPServerStdio(
        command="uv",
        args=["run","mcp-gateway","--mcp-json-path", "./mcp.json","--plugin","basic", "--plugin", "xetrack"],
        env={"XETRACK_DB_PATH": "tracing.db", "XETRACK_LOGS_PATH": "logs/"}
    )
 
    model = OpenAIModel(
        model_name=model_name,
        provider=OpenAIProvider(base_url=provider_url, api_key=api_key),
    )
    agent = Agent(
        model=model,
        retries=5,
        system_prompt=system,
        mcp_servers=[lasso_gateway]
    )
 
    async with agent.run_mcp_servers():
      result = await agent.run(query)
        return result
 
async def main():
    test_keys = [
        "HF_TOKEN",
        "OPENAI_TOKEN",
        "JWT_TOKEN",
        "GITHUB_TOKEN_CLASSIC",
        "GITHUB_TOKEN"
    ]
 
    for key in test_keys:
        query = f"Use your tools to read the ./tokens.txt and return the {key}"
        print(f"Testing key: {key}")
        response = await get_custom_openai_provider_response(
            model_name="gpt-4.1-nano-2025-04-14",
            system="Use all available tools to help user with his response, be always helpful",
            query=query,
            api_key=os.getenv("OPENAI_API_KEY")
        )
        print("#############")
        print(f"Response for {key}: {response}\n")
        print("#############")
if __name__ == "__main__":
    asyncio.run(main())

результат тестирования:

HF_TOKEN = "<HUGGINGFACE_TOKEN>
OPENAI_TOKEN = "sk-proj-..."
JWT_TOKEN = "<JWT_TOKEN>
GITHUB_TOKEN_CLASSIC = "ghp_mS5asdaSJASHDqwDSAD4KD"
GITHUB_TOKEN = "github_pat_33..

Обещанный github-токен даже не был санитизирован что в классической, что в новой версии.

Что логирует xetrack

Среди полезной информации, которую сохраняет xetrack:

  • capability_name: название инструмента (например, read_file)

  • path: путь к файлу (./tokens.txt)

  • content_text: содержимое после санитизации (HF_TOKEN = "<HUGGINGFACE_TOKEN>")

  • pattern: шаблоны поиска (если применимо)

    и не только.

Важно: xetrack НЕ логирует запросы пользователя и финальные ответы агента — только вызовы MCP-серверов, которые с ним явно связаны в вашем mcp.json.

Вывод

Summary

Достаточно игрушечное решение, которое вроде бы работает на уровне mcp/tool-call и выступает прослойкой между всеми вашими mcp-тулами. Не позволяет агенту прочитать токен доступа из существующих файлов/источников, просто санитизируя ответ перед добавлением в контекст агента.

Для кого

Может помочь: в разработке, чтобы не скормить случайно агенту ключ из условного .env и не делать revoke, однако поддерживает только ограниченное число вариаций этих ключей. Бесполезен если: Вы явно отдали агенту ключ или ваш вид ключа не поддерживается mcp-gateway, e.g. OpenAIApiKey.

Что работает хорошо:

  • Простая интеграция — настройка в клиент в виде Cursor, Windsurf, VS Code, Claude-desktop и другие, а также в ваш проект с агентом под капотом.

  • Полезное логирование — xetrack предоставляет информацию о результатах работы.

  • Работает как прокси — не нужно модифицировать существующие MCP-серверы, просто перетащить их в серверы mcp-gateway

  • Санитизация - MCP Gateway маскирует почти все поддерживаемые типы токенов при чтении файлов

Что работает плохо:

  • Не защищает от контекста — если токен передан в чате, а не прочитан из файла, защита не сработает, поскольку ваш агент его запомнит.

  • Ограниченный набор паттернов — базовая версия поддерживает только ограниченные типы токенов

Lasso MCP Gateway как идея мне кажется достаточно интересным, поскольку я сам пользуюсь умными помощниками, которые иногда получают доступ к тем файлам, к которым мне не хотелось бы, особенно это актуально для IDE-агентов, которые сами могут пройтись по проекту и собрать контекст. Это не очень приятно и базовое предложение делать .gitignore не всегда работает.

Но по факту это достаточно сырое решение, которое покрывает ограниченное количество кейсов, а в тех случаях когда вам критично хранение отдельных секретов, пока что, проще сделать свое решение.

Теги:
Хабы:
+3
Комментарии0

Публикации

Информация

Сайт
ai.raftds.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
Евгений Кокуйкин