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/。
This server cannot be deployed
Maintenance
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 gradedqualityDmaintenanceEnables 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.-
- 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
- FlicenseNot gradedqualityAmaintenanceEnables AI buyers to discover products, create orders, and complete payments across any merchant implementing the protocol, with enforced spending limits, consent checks, prompt-injection sanitization, and an immutable audit trail.-