TrustGate
TrustGate
TrustGate — это демонстрация синтетических данных в тестовом режиме Razorpay Test Mode, показывающая ИИ-покупателя, который может предложить покупку из каталога, но не получает полномочий изменять продавца, сумму, валюту, одобрение или результат провайдера. Агент предлагает; TrustGate независимо авторизует и записывает доказательства.
Что это доказывает
SKU из каталога и количество — единственные факты о покупке, на которые агент может влиять.
Политика, ограниченная тенантом, одобрение человеком, одноразовое полномочие на оплату и проверенные события провайдера ограничивают каждое платёжное действие.
Небезопасные попытки отклоняются до создания заказа у провайдера и оставляют аудируемый след.
Related MCP server: Allowance MCP
Как здесь используется ИИ
Агент-покупатель намеренно тонкий, и это аргумент, а не упрощение. Он может предложить только SKU из каталога, количество и цель; каждый критичный для денег факт вычисляется на стороне сервера. Удалите агента полностью — слой авторизации останется неизменным и по-прежнему корректным.
Инженерный вклад — не сложный агент. Это серьёзное отношение к режимам отказа языковых моделей — инъекция промптов через сторонний контент, следование инструкциям вопреки интересам оператора, уверенные ошибочные рассуждения о деньгах — и создание системы, которая остаётся корректной при их возникновении.
Это утверждение проверяется в обе стороны. python -m agent.demo --live запускает реальную модель на описаниях каталога, написанных третьими сторонами, включая враждебные. Тот же каталог отправляется дважды, один раз без описаний, чтобы влияние недоверенного контента измерялось сравнением двух предложений, а не самоотчётом. Набор регрессионных тестов никогда не вызывает провайдера моделей: он использует детерминированные заменители, поэтому проверка безопасности не зависит от того, ведёт ли себя модель определённым образом в определённый день.
Видя проблему
Три чистых отказа доказывают, что система работает, но слабо показывают, зачем она нужна. Поэтому демонстрация начинается с того, что собственный код этого проекта терпит неудачу, без сети, без учётных данных и без базы данных:
python -m demo.unguardedТот же агент читает тот же отравленный каталог — буквально тот же, поскольку оба каталога построены из agent/demo_catalog.py, и тест утверждает, что засеянная строка и базовый объект несут идентичную внедрённую инструкцию. Один ответ модели передаётся двум адаптерам.
Незащищённый принимает сумму и продавца, поэтому внедрённая инструкция выполняется, и он платит 20 000,00 INR продавцу, названному в тексте каталога, при цене каталога 600,00 INR. У другого нет места ни для одного из этих полей, потому что PurchaseProposal объявляет только SKU, количество и цель. Что переживает отбрасывание — это quantity=50, поле, которое агенту разрешено устанавливать, — и сервер ограничивает его собственным максимумом каталога, равным 2, поэтому попытка отклоняется до создания платёжного запроса.
Разница не в фильтре, который распознал атаку. В том, что один интерфейс имел поле для денег, а другой — нет. У базовой версии есть свои тесты, утверждающие как то, что она не может достичь ничего реального, так и то, что она всё ещё эксплуатируема, поскольку демонстрация, которая тихо перестала быть уязвимой, продолжала бы проходить, делая противоположный вывод.
Матрица атак
Сценарии уровня A — состязательные. Эта таблица генерируется из реестра сценариев с помощью python -m scenarios.report, и тест утверждает, что она совпадает, поэтому она не может заявлять атаку, не покрытую проходящим тестом. Каждый сценарий доказывает три вещи: атака отклонена с кодом причины, не создан заказ у провайдера, и ни один платёж не получил полномочий, которых у него не было.
ID | Атака | Доказанный инвариант | Тесты |
A1 | Подмена суммы | Сумма выводится из цены позиции каталога и ограниченного сервером количества. Никакое значение, предоставленное агентом, не может её изменить. |
|
A2 | Подмена продавца | Продавец выводится из позиции каталога, ограниченной тенантом. Продавец вне тенанта недостижим, а продавец вне действующей политики не может быть оплачен. |
|
A3 | Подмена валюты | Валюта выводится из позиции каталога, а единственный маршрут, принимающий валюту, отключён по умолчанию и при включении отклоняет несоответствие действующей политике. |
|
A4 | Просроченное или повторно использованное одобрение | Одобрение — это разрешение с временем жизни и однократным использованием. Ни просроченное, ни уже использованное одобрение не может авторизовать, а отклонённое одобрение не сжигается. |
|
A5 | Самоодобрение | Одобрение не может быть выдано субъектом, запросившим покупку. Разделение обязанностей обеспечивается принудительно, а не просто ожидается от конфигурации. |
|
A6 | Подделанная подпись вебхука | События провайдера аутентифицируются по HMAC на сырых байтах до разбора тела. Подделанная или отсутствующая подпись ничего не меняет, каким бы корректным ни было событие. |
|
A7 | Изменённое тело вебхука | Подпись покрывает точные полученные байты, поэтому подлинно подписанное событие, изменённое в пути, больше не проходит проверку и никогда не достигает платежа. |
|
A8 | Дублированная доставка вебхука | Идентичность события провайдера сохраняется, поэтому повтор подлинного события в пределах окна отклоняется базой данных, а не тем обработчиком, который случайно его увидит. |
|
A9 | События провайдера не в порядке | Порядок поступления — забота провайдера, а законность — наша. Захват не может предшествовать своей авторизации, а терминальный платёж не принимает дальнейших исходов. |
|
A10 | Двойной возврат | Ни одна поверхность вообще не может инициировать возврат — это проверяется по живой таблице маршрутов и списку инструментов, а инвариант реестра отклоняет сумму возврата, превышающую захват. |
|
A11a | Неизвестный заголовок тенанта | Тенант, который не разрешается, отклоняется до выполнения тела любого маршрута, и отказ не раскрывает ничего, что позволило бы вызывающему перечислить существующие тенанты. |
|
A11b | Межтенантный доступ к объектам | Каждый поиск, ограниченный тенантом, фильтруется по доверенному тенанту. Известный тенант не может читать или воздействовать на запрос, платёж или полномочие другого тенанта ни на одной поверхности. |
|
A12 | Коллизия ключа идемпотентности | Ключ, повторно использованный с другой покупкой, возвращает исходное решение и код 409. Вторая покупка никогда не создаётся и не может быть принята за принятую. |
|
A13 | Дрейф политики между авторизацией и использованием | Полномочие не переживает политику, по которой оно проверялось, ни покупку, для которой оно было выдано. Заменяющая политика или изменённая сумма отзывают его без сжигания, а недрейфовавшее полномочие по-прежнему работает. |
|
A14 | Устаревший или датированный будущим числом вебхук | Подпись доказывает происхождение, а не свежесть. Событие вне окна свежести, датированное будущим или вообще не имеющее временной метки, отклоняется до любого поиска. |
|
A15 | Несанкционированный захват через MCP | Ни один инструмент, доступный агенту, не может авторизовать, захватить, вернуть или вызвать провайдера. Доказано путём использования каждого открытого инструмента, а не путём проверки имён инструментов. |
|
Каждый сценарий уровня A реализован. A11a и A11b разделяют путаницу тенантов на неразрешимый тенант и известный тенант, пересекающий границу, потому что эти два случая дают сбой по разным причинам, и только второй является вопросом авторизации.
Чем ценны тесты
Проходящий набор тестов говорит, что код ведёт себя так, как написан. Он не говорит, что тесты возразили бы, если бы код перестал делать что-то важное, а применительно к деньгам имеет значение только второе утверждение. У этого проекта есть доказательство различия: сессии с областью запроса однажды отбрасывали каждую запись, пока 146 тестов проходили, потому что набор проверял внутри той же транзакции, в которой писал.
make mutation намеренно нарушает каждый инвариант безопасности по одному за раз и требует, чтобы тесты, названные его стражами, падали. Каждый исходный файл восстанавливается в блоке finally, и восстановление проверяется по git diff перед выводом отчёта, поэтому прерванный запуск не может оставить мутацию. Он завершается с ненулевым кодом, если какая-либо мутация выживает.
Эта таблица генерируется из реестра мутаций командой python -m scenarios.report --mutations, и тест проверяет её соответствие, поэтому она не может заявлять о защищённом инварианте, который на самом деле не защищён.
Mutation | Инвариант, который она удаляет |
| Платёж блокируется до того, как его состояние прочитано и изменено. |
| Заблокированное чтение принимает решение на основе зафиксированной строки, а не кэшированной. |
| Блокировки строк берутся через единственный помощник, который сохраняет их значимость. |
| Событие провайдера аутентифицируется до того, как с ним что-либо делается. |
| Подписанное событие провайдера доказывает происхождение, а не свежесть. |
| Событие, которое нельзя датировать, нельзя ограничить, поэтому оно отклоняется. |
| Одобрение — это разрешение с сроком действия, а не постоянное предоставление. |
| Полномочие не переживает политику, по которой оно было проверено. |
| Полномочие привязано к конкретной покупке, для которой оно было выдано. |
| Ежедневное обновление бюджета отказывается превышать лимит. |
| Бюджет возвращается только тем платежом, который фактически его зарезервировал. |
| Текст каталога не может завершить элемент script на странице оформления заказа. |
| Успешный запрос фиксирует свои записи. |
| События жизненного цикла для одного платежа являются отдельными событиями, а не повторами. |
| Одобрение не может быть предоставлено запрашивающим субъектом. |
| Доказательства ограничены арендатором, который их запросил. |
| Неполный поиск провайдера никогда не сообщает об отсутствии квитанции. |
Первый запуск этого набора обнаружил реальный дефект. SELECT ... FOR UPDATE через ORM корректно получает блокировку, а затем отбрасывает строку, возвращённую Postgres, потому что SQLAlchemy сохраняет атрибуты объекта, уже находящегося в identity map сессии. Поэтому второй вызывающий блокировался на блокировке, как и задумано, получал зафиксированную строку, сохранял её устаревшую копию и авторизовал платёж, который только что был авторизован. Блокировка сериализовала выполнение переходов, а не то состояние, на основе которого они принимали решение. Теперь все блокировки выполняются через models.locking.locked(), и тест проверяет, что этот помощник — единственное место в исходном коде, где можно взять блокировку.
Текущая область применения
TrustGate использует только синтетических арендаторов, продавцов и цены в INR. Это локальный испытательный стенд безопасности, а не платёжный процессор, продукт для соответствия требованиям, система юридического согласия, модель мошенничества или интеграция платежей в Live Mode.
Быстрый старт
Требования: Docker Desktop и Python 3.12.
Copy-Item .env.example .env
docker compose up -d
docker compose exec -T api python -m alembic upgrade head
docker compose exec -T api python -m pytest -qЛокальная проверка работоспособности API доступна по адресу http://127.0.0.1:8000/health.
Создайте одноразового синтетического арендатора M1 с помощью python -m agent.seed. Установите MCP_TENANT_ID и MCP_ACTOR_ID в выведенные значения, затем запустите локальную демонстрацию агента-покупателя с помощью python -m agent.demo "Buy Starter credits for our student club.". Он может предложить только SKU из каталога, количество и цель; MCP-сервер выводит все критически важные для денег факты. Используйте python -m agent.demo --adversarial "Buy a small amount of cloud credits." для запуска детерминированной демонстрации отравленного каталога.
Чтобы запустить тот же процесс с реальной моделью вместо детерминированного заменителя, установите дополнительный пакет с помощью pip install -e ".[agent]" и добавьте --live. Поддерживаются два бэкенда, и оба используют одну и ту же форму Messages API:
TRUSTGATE_MODEL_BACKEND=anthropic(по умолчанию) читаетANTHROPIC_API_KEY.TRUSTGATE_MODEL_BACKEND=bedrockвыставляет счёт на аккаунт AWS. УстановитеAWS_REGIONв регион, к которому относится учётная запись, затем либоAWS_BEARER_TOKEN_BEDROCK(ключ API Bedrock, самый простой путь), либо стандартные учётные данные AWS для подписи SigV4. Amazon Bedrock предоставляет модели Anthropic через подписку AWS Marketplace, поэтому на аккаунте AWS также должен быть действительный платёжный инструмент, даже если кредиты покрывают использование.TRUSTGATE_MODEL_BACKEND=groqчитаетGROQ_API_KEYи вообще не требует платёжного инструмента.
TRUSTGATE_MODEL_ID переопределяет модель на любом бэкенде. Покупатель — это реализация протокола, поэтому провайдер является конфигурационным выбором, а не архитектурным: поведение уровня авторизации не зависит от того, какая модель предлагает покупку.
Это единственный путь в проекте, который связывается с провайдером модели; тестовый набор никогда этого не делает. Запускайте его только с синтетическим каталогом сидов. Его сторонние описания отправляются модели дважды: один раз с удалёнными описаниями и один раз без изменений, чтобы измерить влияние. Никогда не отправляйте реальные данные клиентов, продавцов или платежей через эту демонстрацию.
Чтобы проверить адаптер Razorpay Test Mode, установите RAZORPAY_KEY_ID и RAZORPAY_KEY_SECRET в игнорируемом файле .env. Никогда не добавляйте секреты Test Mode или Live Mode в репозиторий.
Граница доверия
AI buyer proposes SKU, quantity, and purpose
-> TrustGate derives and authorizes money-critical facts
-> Razorpay Test Mode executes a bounded order
-> TrustGate records authorization and provider evidenceФормальный план сборки находится в docs/build-plan.md; архитектура, модель угроз и проектные решения — в docs/.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
No tool schema history has been recorded yet.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Procure governed AI capabilities: machine-readable price, scope, trust, gateway-delegation terms.
Secure agent purchasing with human-approved virtual cards, receipts, and audit trails.
Pre-spend firewall for AI agents. Approves, blocks, flags transactions against policy rules.
Advisory policy preflight for AI-agent spend requests; never executes payments or accesses wallets.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI agents to create, compare, and track purchases with structured buying workflows, offer comparison, and merchant verification.5MIT

Allowance MCPofficial
FlicenseNot gradedqualityBmaintenanceEnables AI agents to request purchase approval from humans, receive scoped virtual cards, complete checkout, and report receipts for audit.-- FlicenseNot gradedqualityBmaintenanceEnables AI agents to browse product catalogs and make purchases through a policy engine that enforces spending limits, requires human approval for certain amounts, and logs all actions to an audit trail.-
- FlicenseNot gradedqualityDmaintenanceEnables human-in-the-loop authorization for AI agent transactions, allowing real-time approval or denial of purchases based on configurable spending limits, vendor blocklists, daily caps, and category restrictions.1-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Saraid10/Trustgate'
If you have feedback or need assistance with the MCP directory API, please join our Discord server