TrustGate
TrustGate
TrustGate 是一个合成数据、Razorpay Test Mode 演示,展示一个 AI 买家可以提出目录购买建议,但无法获得改写商户、金额、货币、审批或提供商结果的权限。代理提出建议;TrustGate 独立授权并记录证据。
它证明了什么
目录 SKU 和数量是代理唯一能影响的购买事实。
租户范围的策略、人工审批、一次性结账权限和已验证的提供商事件约束着每一个支付操作。
不安全的尝试在提供商订单创建之前就被拒绝,并留下可审计的痕迹。
Related MCP server: safe-cart-ai
AI 在这里如何使用
买家代理被刻意设计得很薄,而这正是论点本身,而非捷径。它只能提出目录 SKU、数量和用途;每一个涉及金钱的关键事实都在服务端派生。完全删除代理,授权层保持不变,仍然正确。
工程贡献不是复杂的代理。而是认真对待语言模型的失败模式——通过第三方内容进行提示注入、违背操作者利益的指令遵循、关于金钱的自信错误推理——并构建一个在这些情况发生时仍能保持正确的系统。
这一主张以两种方式得到检验。python -m agent.demo --live 针对由第三方(包括敌意方)编写的目录描述运行真实模型。同一目录被发送两次,一次移除描述,因此不受信任内容的影响通过比较两次提议来衡量,而非自我报告。回归套件从不调用模型提供商:它使用确定性替代品,因此安全验证不依赖于模型在某一天以特定方式表现。
看到问题
三次干净的拒绝证明了系统有效,但很难说明为什么有人需要它。因此演示以本项目自己的代码失败开场,不使用网络、不使用凭据、不使用数据库:
python -m demo.unguarded同一个代理读取同一个被投毒的目录——字面上相同,因为两个目录都构建自 agent/demo_catalog.py,且一个测试断言种子行和基线对象携带相同的注入指令。一个模型响应被交给两个适配器。
未受防护的那个接受金额和商户,因此注入指令得以执行,它向目录文本中指定的商户支付 INR 20,000.00,而目录价格为 INR 600.00。另一个没有地方放置这两个字段,因为 PurchaseProposal 只声明了 SKU、数量和用途。丢弃后幸存的是 quantity=50,这是代理被允许设置的字段——而服务器将其限制在目录自身的最大值 2 以内,因此在支付请求创建之前尝试就被拒绝。
区别不在于识别攻击的过滤器。而是一个接口有金钱字段,另一个没有。基线有自己的测试,既断言它无法触及任何真实事物,也断言它仍然可利用,因为一个悄悄不再易受攻击的演示会继续通过测试,同时传达相反的观点。
攻击矩阵
Tier A 对抗性场景。此表由 python -m scenarios.report 从场景注册表生成,且一个测试断言其匹配,因此它不能声称一个未被通过测试覆盖的攻击。每个场景证明三件事:攻击以其原因代码被拒绝,没有创建提供商订单,没有支付获得其本不具备的权限。
ID | 攻击方式 | 已验证的不变量 | 测试 |
A1 | 金额篡改 | 金额来源于目录项的价格和受服务器约束的数量。任何由代理提供的值都无法改变它。 |
|
A2 | 商户替换 | 商户来源于租户范围内的目录项。租户之外的商户不可达,不在活动策略范围内的商户无法被支付。 |
|
A3 | 货币替换 | 货币来源于目录项,唯一接受货币的路由默认被禁用,启用后若与活动策略不匹配则拒绝。 |
|
A4 | 过期或重复使用的审批 | 审批是一种具有生命周期且只能使用一次的权限。过期的或已被消费的审批都无法授权,被拒绝的审批不会被消耗。 |
|
A5 | 自我审批 | 审批不能由发起购买请求的身份授予。职责分离是被强制执行的,而不仅仅是期望通过配置实现。 |
|
A6 | 伪造的 Webhook 签名 | 提供方事件在解析正文之前通过原始字节 HMAC 进行身份验证。无论事件格式多么规范,伪造或缺失的签名都不会改变任何结果。 |
|
A7 | 被篡改的 Webhook 正文 | 签名覆盖接收到的确切字节,因此一个真实签名的事件在传输途中被修改后将无法通过验证,也永远不会到达支付环节。 |
|
A8 | 重复的 Webhook 投递 | 提供方事件的身份被存储,因此对真实且在窗口期内的事件进行重放会被数据库拒绝,而不是由碰巧处理它的某个处理器来拒绝。 |
|
A9 | 提供方事件乱序到达 | 到达顺序是提供方的事,合法性由我们决定。捕获不能先于授权发生,终态支付不接受任何进一步的结果。 |
|
A10 | 双重退款 | 任何界面都无法发起退款,这一点针对实时路由表和工具列表进行了断言,同时账本不变量拒绝退款总额超过捕获金额。 |
|
A11a | 未知租户请求头 | 无法解析的租户在任何路由主体运行之前就被拒绝,且拒绝响应不会泄露任何能让调用方枚举存在哪些租户的信息。 |
|
A11b | 跨租户对象访问 | 每个租户范围内的查找都按可信租户进行过滤。已知租户无法在任何界面上读取或操作另一个租户的请求、支付或授权。 |
|
A12 | 幂等键冲突 | 使用不同购买请求重复使用同一键时,返回原始决定和 409 状态码。第二次购买永远不会被创建,也不会被误认为是已接受的购买。 |
|
A13 | 授权与使用之间的策略漂移 | 授权不会比其被检查时所依据的策略更长寿,也不会比其为之签发的购买更长寿。后续策略或修改后的金额会撤销授权但不会消耗它,未发生漂移的授权仍然有效。 |
|
A14 | 过期或未来日期的 Webhook | 签名证明来源,而非时效性。超出新鲜度窗口的事件、日期指向未来的事件,或完全不带时间戳的事件,在任何查找之前就被拒绝。 |
|
A15 | 通过 MCP 进行未授权捕获 | 代理可到达的任何工具都无法授权、捕获、退款或调用提供方。这是通过实际调用每个暴露的工具来证明的,而不是通过检查工具名称。 |
|
每个 Tier A 场景都已实现。A11a 和 A11b 将租户混淆拆分为不可解析的租户和已知租户越界访问两种情况,因为两者的失败原因不同,且只有第二种情况属于授权问题。
这些测试的价值
一套通过的测试套件说明代码的行为与所编写的一致。它并不说明当代码停止做某些重要事情时测试会提出异议,而当涉及金钱时,只有第二种说法才重要。本项目有证据证明这种差异:请求作用域的会话曾经在 146 个测试通过的情况下丢弃了每一次写入,因为测试套件是在其写入的同一事务内部进行断言的。
make mutation 会故意一次一个地破坏每个安全不变量,并要求以其命名的测试作为守卫而失败。每个源文件都会在 finally 块中恢复,并且在报告打印之前会通过 git diff 检查恢复结果,因此中断的运行不会留下任何变异。如果任何变异存活,它会以非零状态退出。
此表由 python -m scenarios.report --mutations 从变异注册表生成,并且有一个测试断言其匹配,因此它不能声称某个受守卫的不变量实际上并未受到守卫。
Mutation | 其移除的不变量 |
| 支付在状态被读取和更改之前被锁定。 |
| 锁定读取根据已提交的行做决定,而非缓存的行。 |
| 行锁通过唯一能保持其意义的辅助函数获取。 |
| 提供商事件在对其执行任何操作之前经过身份验证。 |
| 已签名的提供商事件证明来源,而非时效性。 |
| 无法确定日期的事件无法被限定范围,因此被拒绝。 |
| 审批是带有效期的权限,而非永久授权。 |
| 授权不会比其被检查所依据的策略存活更久。 |
| 授权绑定于其签发时对应的具体购买。 |
| 每日预算的 upsert 拒绝超过限额。 |
| 预算仅由实际预留它的支付返还。 |
| 目录文本不能终止结账页面的 script 元素。 |
| 成功的请求提交其写入。 |
| 同一支付的生命周期事件是不同的事件,而非重放。 |
| 审批不能由发起请求的行为者授予。 |
| 证据限定在请求它的租户范围内。 |
| 不完整的提供商搜索绝不会将收据报告为不存在。 |
该套件的首次运行发现了一个实际缺陷。通过 ORM 的 SELECT ... FOR UPDATE 正确获取了锁,但随后丢弃了 Postgres 返回的行,因为 SQLAlchemy 保留了会话身份映射中已有对象的属性。因此,第二个调用者按设计阻塞在锁上,收到已提交的行,保留其过期副本,并授权了一笔刚刚已被授权的支付。锁在转换运行时进行序列化,而非序列化它们所依据的状态。现在所有加锁都通过 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 获取。
使用 python -m agent.seed 创建一个一次性的合成 M1 租户。将 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(Bedrock API 密钥,最简单的路径)或用于 SigV4 签名的标准 AWS 凭证。Amazon Bedrock 通过 AWS Marketplace 订阅提供 Anthropic 模型,因此即使额度足以覆盖使用量,AWS 账户也需要有效的支付工具。TRUSTGATE_MODEL_BACKEND=groq读取GROQ_API_KEY,完全不需要支付工具。
TRUSTGATE_MODEL_ID 在任何后端上覆盖模型。买家是协议实现,因此提供商是配置选择而非架构选择:授权层的行为不依赖于哪个模型提出购买。
这是项目中唯一与模型提供商接触的路径;测试套件从不这样做。仅针对合成种子目录运行它。其第三方描述会发送给模型两次,一次移除描述,一次保持完整,以衡量影响。切勿通过此演示发送真实的客户、商户或支付数据。
要使用 Razorpay Test Mode 适配器,请在被忽略的 .env 文件中设置 RAZORPAY_KEY_ID 和 RAZORPAY_KEY_SECRET。切勿将 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
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-
- AlicenseNot gradedqualityBmaintenanceEnables an AI agent to browse inventory and make purchases under strict human approval, with hard spending caps and auditable on-chain payment records.MIT
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