TrustGate
TrustGate
TrustGate は、Razorpay テストモードを利用した合成データによるデモで、AI バイヤーがカタログ購入を提案できるものの、販売者・金額・通貨・承認・プロバイダー結果を書き換える権限は持たないことを示します。エージェントは提案するだけであり、TrustGate が独立して承認し、証跡を記録します。
これが証明すること
カタログ SKU と数量だけが、エージェントが影響を与えられる唯一の購入事実です。
テナント単位のポリシー、人間による承認、ワンタイムのチェックアウト権限、検証済みのプロバイダーイベントが、すべての支払いアクションを拘束します。
安全でない試行は、プロバイダー注文が作成される前に拒否され、監査可能な証跡を残します。
Related MCP server: safe-cart-ai
ここでの AI の使われ方
バイヤーエージェントは意図的に薄く作られており、それは手抜きではなく、むしろ主張そのものです。エージェントが提案できるのはカタログ SKU、数量、目的のみで、金銭に関わるすべての事実はサーバー側で導出されます。エージェントを完全に削除しても、承認レイヤーは変わらず、依然として正しく機能します。
技術的な貢献は、高度なエージェントではありません。言語モデルの失敗モードを真剣に受け止めること——サードパーティのコンテンツによるプロンプトインジェクション、運用者の利益に反する指示追従、金銭に関する過信した誤った推論——そして、それらが発生しても正しく動作し続けるシステムを構築することです。
この主張は双方向でテストされています。python -m agent.demo --live は、敵対的なものを含むサードパーティが書いたカタログ記述に対して実際のモデルを実行します。同じカタログが2回送信され、1回は記述を削除した状態で送信されるため、信頼できないコンテンツからの影響は自己申告ではなく、2つの提案を比較することで測定されます。回帰テストスイートはモデルプロバイダーを一切呼び出しません。決定的な代替手段を使用するため、安全性の検証は、モデルが特定の日に特定の動作をするかどうかに依存しません。
問題を見る
3つの明確な拒否はシステムが機能することを証明しますが、なぜ誰かがそれを必要とするのかを示すには弱いものです。そのため、デモはこのプロジェクト自身のコードが失敗するところから始まります。ネットワークも、認証情報も、データベースも使用しません。
python -m demo.unguarded同じエージェントが同じ毒入りカタログを読みます——文字通り同じものです。両方のカタログは agent/demo_catalog.py から構築され、テストはシードされた行とベースラインオブジェクトが同一の注入命令を保持していることを検証します。1つのモデル応答が2つのアダプターに渡されます。
ガードのない方は金額と販売者を受け入れるため、注入された命令が実行され、カタログ価格 INR 600.00 に対して、カタログテキストが指定した販売者に INR 20,000.00 を支払います。もう一方は、PurchaseProposal が SKU、数量、目的のみを宣言するため、どちらのフィールドにも入れる場所がありません。破棄を生き残るのは quantity=50 で、これはエージェントが設定できるフィールドです——そしてサーバーはそれをカタログ自身の最大値2に対して制限するため、支払いリクエストが作成される前に試行は拒否されます。
違いは攻撃を認識したフィルターではありません。一方のインターフェースには金銭のフィールドがあり、もう一方にはなかったということです。ベースラインには、現実のものに到達できないことと、依然として悪用可能であることの両方を検証する独自のテストがあります。なぜなら、静かに脆弱でなくなったデモは、反対の主張をしながらテストを通過し続けることになるからです。
攻撃マトリックス
Tier A の敵対的シナリオ。この表は python -m scenarios.report によってシナリオレジストリから生成され、テストが一致することを検証するため、合格するテストでカバーされていない攻撃を主張することはできません。すべてのシナリオは3つのことを証明します。攻撃が理由コード付きで拒否されること、プロバイダー注文が作成されないこと、そして支払いが持っていなかった権限を獲得していないことです。
ID | 攻撃 | 証明された不変条件 | テスト |
A1 | 金額の改ざん | 金額はカタログ商品の価格とサーバー側で制限された数量から導出される。エージェントが提供する値では変更できない。 |
|
A2 | 加盟店のすり替え | 加盟店はテナントスコープのカタログ商品から導出される。テナント外の加盟店には到達できず、アクティブなポリシー外の加盟店には支払いできない。 |
|
A3 | 通貨のすり替え | 通貨はカタログ商品から導出され、通貨を受け付ける唯一のルートはデフォルトで無効化されており、有効化された場合もアクティブなポリシーとの不一致を拒否する。 |
|
A4 | 期限切れまたは再利用された承認 | 承認は有効期限と単回使用を持つ権限である。期限切れのものも既に消費されたものも承認できず、拒否された承認は消費されない。 |
|
A5 | 自己承認 | 購入を要求した本人は承認を付与できない。職務分離は設定で期待されるだけでなく、強制される。 |
|
A6 | 偽造されたWebhook署名 | プロバイダーイベントは、ボディが解析される前に生バイトのHMACで認証される。偽造された署名や欠落した署名は、イベントがどれだけ整形式でも何も変更しない。 |
|
A7 | 改ざんされたWebhookボディ | 署名は受信した正確なバイトを対象とするため、署名後に送信中に編集されたイベントは検証に失敗し、支払いに到達することはない。 |
|
A8 | 重複したWebhook配信 | プロバイダーイベントの識別情報が保存されるため、真正でウィンドウ内のイベントのリプレイは、たまたま参照するハンドラーではなくデータベースによって拒否される。 |
|
A9 | 順序が乱れたプロバイダーイベント | 到着順はプロバイダーのものであり、合法性はこちら側のものである。キャプチャは承認に先行できず、終端状態の支払いはそれ以上の結果を受け付けない。 |
|
A10 | 二重返金 | どのサーフェスも返金を開始できず、これは稼働中のルートテーブルとツールリストに対して検証される。また、台帳の不変条件はキャプチャ額を超える返金合計を拒否する。 |
|
A11a | 不明なテナントヘッダー | 解決できないテナントは、ルートボディが実行される前に拒否され、その拒否は呼び出し元がどのテナントが存在するかを列挙できるような情報を一切開示しない。 |
|
A11b | クロステナントオブジェクトアクセス | すべてのテナントスコープのルックアップは、信頼されたテナントでフィルタリングされる。既知のテナントは、どのサーフェスでも別のテナントのリクエスト、支払い、または権限を読み取ったり操作したりできない。 |
|
A12 | 冪等性キーの衝突 | 異なる購入で再利用されたキーは、元の決定と409を返す。2番目の購入は決して作成されず、受け入れられたものと誤認されることはない。 |
|
A13 | 承認と使用の間のポリシードリフト | 権限は、それが照合されたポリシーや発行された購入よりも長く存続しない。後続のポリシーや編集された金額は、それを消費せずに失効させ、ドリフトしていない権限は引き続き機能する。 |
|
A14 | 古いまたは先日付のWebhook | 署名は発信元を証明するものであり、新しさを証明するものではない。鮮度ウィンドウ外のイベント、未来の日付のイベント、またはタイムスタンプをまったく持たないイベントは、ルックアップの前に拒否される。 |
|
A15 | MCP経由の不正なキャプチャ | エージェントが到達可能なツールは、承認、キャプチャ、返金、プロバイダー呼び出しのいずれもできない。これはツール名を検査するのではなく、公開されたすべてのツールを実行して証明される。 |
|
すべてのTier Aシナリオが実装されている。A11aとA11bは、テナントの混同を「解決できないテナント」と「境界を越えて到達する既知のテナント」に分割している。両者は異なる理由で失敗し、後者のみが認可の問題だからである。
テストの価値
テストスイートが成功することは、コードが書かれたとおりに動作することを示す。コードが重要な何かをしなくなった場合にテストが異議を唱えることを示すものではなく、お金が関わる場合に重要なのは後者の主張だけである。このプロジェクトにはその違いの証拠がある。リクエストスコープのセッションが、146のテストが成功している間にすべての書き込みを破棄していたことがある。スイートが書き込みを行ったのと同じトランザクション内で検証していたからである。
make mutationは、各安全不変条件を意図的に一度に1つずつ破壊し、その守護者として指定されたテストが失敗することを要求する。すべてのソースファイルはfinallyブロックで復元され、レポートが出力される前にgit diffで復元が確認されるため、中断された実行でもミューテーションが残ることはない。ミューテーションが生き残った場合は非ゼロで終了する。
このテーブルはpython -m scenarios.report --mutationsによってミューテーションレジストリから生成され、テストが一致を検証するため、実際には守られていない不変条件が守られていると主張することはできない。
ミューテーション | それが除去する不変条件 |
| 支払いは、その状態が読み取られ変更される前にロックされます。 |
| ロックされた読み取りは、キャッシュされた行ではなく、コミットされた行から決定します。 |
| 行ロックは、それらを意味のあるものにする唯一のヘルパーを通じて取得されます。 |
| プロバイダーイベントは、何かを行う前に認証されます。 |
| 署名されたプロバイダーイベントは、発信元を証明し、新しさは証明しません。 |
| 日付を付けることができないイベントは制限できないため、拒否されます。 |
| 承認は、永続的な許可ではなく、有効期限のある許可です。 |
| 権限は、それがチェックされたポリシーよりも長く存続しません。 |
| 権限は、それが発行された正確な購入に結び付けられています。 |
| 日次予算のアップサートは、制限を超えることを拒否します。 |
| 予算は、実際にそれを予約した支払いによってのみ返されます。 |
| カタログテキストは、チェックアウトページのスクリプト要素を終了できません。 |
| 成功したリクエストは、その書き込みをコミットします。 |
| 1つの支払いのライフサイクルイベントは、リプレイではなく、個別のイベントです。 |
| 承認は、要求元のアクターによって付与されることはできません。 |
| 証拠は、それを要求したテナントに限定されます。 |
| 不完全なプロバイダー検索は、領収書を不存在として報告することはありません。 |
このスイートの最初の実行で、実際の欠陥が見つかりました。ORMを介したSELECT ... FOR UPDATEはロックを正しく取得しますが、Postgresが返した行を破棄します。これは、SQLAlchemyがセッションのアイデンティティマップに既にあるオブジェクトの属性を保持するためです。そのため、2番目の呼び出し元は設計どおりロックでブロックされ、コミットされた行を受け取り、古いコピーを保持し、ちょうど承認されたばかりの支払いを承認しました。ロックは、遷移が実行されるタイミングを直列化していましたが、遷移が決定する状態を直列化していませんでした。現在、すべてのロックはmodels.locking.locked()を介して行われ、テストはそのヘルパーがソース内でロックを取得できる唯一の場所であることを検証します。
現在のスコープ
TrustGateは、合成テナント、マーチャント、およびINR価格のみを使用します。これはローカルな安全性テストベッドであり、決済処理業者、コンプライアンス製品、法的同意システム、不正モデル、またはライブモードの決済統合ではありません。
クイックスタート
要件: 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 を追加します。2つのバックエンドがサポートされており、両方とも同じ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 は任意のバックエンドでモデルを上書きします。買い手はプロトコル実装であるため、プロバイダーはアーキテクチャ上の選択ではなく構成上の選択です。承認レイヤーの動作は、どのモデルが購入を提案するかに依存しません。
これはプロジェクト内でモデルプロバイダーに接触する唯一の経路であり、テストスイートは決して接触しません。合成シードカタログに対してのみ実行してください。そのサードパーティの説明は、影響を測定するために、説明を削除した状態とそのままの状態の2回モデルに送信されます。実際の顧客、マーチャント、または支払いデータをこのデモを通じて送信しないでください。
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.-