Skip to main content
Glama
Saraid10
by Saraid10

TrustGate

TrustGate ist eine Demonstration mit synthetischen Daten im Razorpay-Testmodus eines KI-Käufers, der einen Katalogkauf vorschlagen kann, ohne die Befugnis zu erhalten, Händler, Betrag, Währung, Genehmigung oder Anbieterergebnis zu überschreiben. Der Agent schlägt vor; TrustGate autorisiert und protokolliert Beweise unabhängig.

Was es beweist

  • Katalog-SKU und Menge sind die einzigen Kaufdaten, die ein Agent beeinflussen kann.

  • Mandantenbezogene Richtlinien, menschliche Genehmigung, eine einmalige Checkout-Befugnis und verifizierte Anbieterereignisse begrenzen jede Zahlungsaktion.

  • Unsichere Versuche werden abgelehnt, bevor eine Anbieterbestellung erstellt werden kann, und hinterlassen eine prüfbare Spur.

Related MCP server: safe-cart-ai

Wie KI hier eingesetzt wird

Der Käuferagent ist bewusst dünn gehalten, und genau das ist das Argument und keine Abkürzung. Er kann nur eine Katalog-SKU, eine Menge und einen Zweck vorschlagen; jede geldkritische Tatsache wird serverseitig abgeleitet. Löschen Sie den Agenten vollständig, und die Autorisierungsebene bleibt unverändert und weiterhin korrekt.

Der technische Beitrag ist kein ausgeklügelter Agent. Es geht darum, die Ausfallmodi von Sprachmodellen ernst zu nehmen – Prompt-Injection durch Inhalte Dritter, Befolgung von Anweisungen gegen die Interessen des Betreibers, selbstsichere falsche Überlegungen über Geld – und ein System zu bauen, das korrekt bleibt, wenn diese auftreten.

Diese Behauptung wird in beide Richtungen getestet. python -m agent.demo --live führt ein echtes Modell gegen Katalogbeschreibungen aus, die von Dritten geschrieben wurden, einschließlich feindseliger. Derselbe Katalog wird zweimal gesendet, einmal ohne Beschreibungen, sodass der Einfluss nicht vertrauenswürdiger Inhalte durch den Vergleich der beiden Vorschläge gemessen wird, statt durch Selbstauskunft. Die Regressionssuite ruft niemals einen Modellanbieter auf: Sie verwendet deterministische Ersatzstoffe, sodass die Sicherheitsverifikation nicht davon abhängt, dass sich ein Modell an einem bestimmten Tag auf eine bestimmte Weise verhält.

Das Problem erkennen

Drei saubere Ablehnungen beweisen, dass das System funktioniert, und sind schwach darin, zu zeigen, warum jemand es braucht. Die Demo beginnt daher damit, dass der eigene Code dieses Projekts fehlschlägt, ohne Netzwerk, ohne Anmeldedaten und ohne Datenbank:

python -m demo.unguarded

Derselbe Agent liest denselben vergifteten Katalog – buchstäblich denselben, da beide Kataloge aus agent/demo_catalog.py aufgebaut sind und ein Test bestätigt, dass die gesetzte Zeile und das Basisobjekt eine identische injizierte Anweisung tragen. Eine Modellantwort wird zwei Adaptern übergeben.

Der ungeschützte akzeptiert einen Betrag und einen Händler, sodass die injizierte Anweisung ausgeführt wird und er INR 20.000,00 an einen Händler zahlt, den der Katalogtext nannte, gegen einen Katalogpreis von INR 600,00. Der andere hat für keines der beiden Felder einen Platz, weil PurchaseProposal nur eine SKU, eine Menge und einen Zweck deklariert. Was die Verwerfung übersteht, ist quantity=50, ein Feld, das der Agent setzen darf – und der Server begrenzt es gegen das eigene Maximum des Katalogs von 2, sodass der Versuch abgelehnt wird, bevor eine Zahlungsanforderung erstellt wird.

Der Unterschied ist kein Filter, der einen Angriff erkannt hat. Es ist, dass eine Schnittstelle ein Feld für das Geld hatte und die andere nicht. Die Basislinie hat ihre eigenen Tests, die sowohl bestätigen, dass sie nichts Echtes erreichen kann, als auch, dass sie weiterhin ausnutzbar ist, da eine Demonstration, die stillschweigend aufhörte, verwundbar zu sein, weiterhin bestehen würde, während sie das Gegenteil aussagt.

Angriffsmatrix

Tier-A-Adversarial-Szenarien. Diese Tabelle wird aus dem Szenarioregister von python -m scenarios.report generiert, und ein Test bestätigt, dass sie übereinstimmt, sodass sie keinen Angriff behaupten kann, der nicht durch einen bestandenen Test abgedeckt ist. Jedes Szenario beweist drei Dinge: Der Angriff wird mit seinem Grundcode abgelehnt, es wurde keine Anbieterbestellung erstellt, und keine Zahlung erhielt eine Befugnis, die sie nicht hatte.

ID

Angriff

Bewiesene Invariante

Tests

A1

Betragsmanipulation

Der Betrag wird aus dem Preis des Katalogeintrags und einer serverseitig begrenzten Menge abgeleitet. Kein vom Agenten gelieferter Wert kann ihn ändern.

test_a1_supplied_amount_field_is_refused_at_the_boundarytest_a1_mcp_surface_has_no_amount_parametertest_a1_quantity_cannot_be_used_to_escalate_the_amount

A2

Händlerersetzung

Der Händler wird aus dem mandantenbezogenen Katalogeintrag abgeleitet. Ein Händler außerhalb des Mandanten ist unerreichbar, und einer außerhalb der aktiven Richtlinie kann nicht bezahlt werden.

test_a2_another_tenants_sku_is_not_reachabletest_a2_policy_disallowed_merchant_cannot_be_paid

A3

Währungsersetzung

Die Währung wird aus dem Katalogeintrag abgeleitet, und die einzige Route, die eine Währung akzeptiert, ist standardmäßig deaktiviert und verweigert bei Aktivierung eine Abweichung von der aktiven Richtlinie.

test_a3_the_agent_surface_derives_currency_and_cannot_be_told_onetest_a3_the_only_currency_accepting_route_is_disabled_by_defaulttest_a3_an_enabled_legacy_route_still_denies_a_currency_outside_the_policy

A4

Abgelaufene oder wiederverwendete Genehmigung

Eine Genehmigung ist eine Berechtigung mit einer Lebensdauer und einer einmaligen Verwendung. Weder eine abgelaufene noch eine bereits verbrauchte kann autorisieren, und eine verweigerte Genehmigung wird nicht verbraucht.

test_a4_an_expired_approval_cannot_authorizetest_a4_an_already_consumed_approval_cannot_authorize_again

A5

Selbstgenehmigung

Eine Genehmigung kann nicht von der Identität erteilt werden, die den Kauf angefordert hat. Funktionstrennung wird erzwungen, nicht nur von der Konfiguration erwartet.

test_a5_an_approval_cannot_be_granted_by_the_requesting_actortest_a5_a_separate_approver_can_still_grant

A6

Gefälschte Webhook-Signatur

Provider-Ereignisse werden per Rohbyte-HMAC authentifiziert, bevor der Body geparst wird. Eine gefälschte oder fehlende Signatur ändert nichts, egal wie wohlgeformt das Ereignis ist.

test_a6_a_forged_signature_is_refusedtest_a6_an_unsigned_event_is_refused

A7

Manipulierter Webhook-Body

Die Signatur deckt die exakt empfangenen Bytes ab, sodass ein echt signiertes, während der Übertragung verändertes Ereignis nicht mehr verifiziert und niemals eine Zahlung erreicht.

test_a7_a_body_altered_after_signing_no_longer_verifies

A8

Doppelte Webhook-Zustellung

Die Identität von Provider-Ereignissen wird gespeichert, sodass eine Wiedergabe eines authentischen, im Zeitfenster liegenden Ereignisses von der Datenbank abgelehnt wird, nicht von dem Handler, der zufällig darauf schaut.

test_a8_a_replayed_event_does_not_transition_the_payment_twice

A9

Außerhalb der Reihenfolge eintreffende Provider-Ereignisse

Die Ankunftsreihenfolge ist Sache des Providers, die Rechtmäßigkeit unsere. Eine Erfassung kann ihrer Autorisierung nicht vorausgehen, und eine abgeschlossene Zahlung akzeptiert kein weiteres Ergebnis.

test_a9_a_capture_cannot_precede_an_authorizationtest_a9_a_terminal_payment_accepts_no_further_provider_outcome

A10

Doppelte Rückerstattung

Keine Oberfläche kann überhaupt eine Rückerstattung auslösen, geprüft gegen die Live-Routentabelle und die Werkzeugliste, und die Ledger-Invariante verweigert eine Rückerstattungssumme, die die Erfassung übersteigt.

test_a10_no_surface_anywhere_can_initiate_a_refundtest_a10_a_refund_total_cannot_exceed_what_was_captured

A11a

Unbekannter Mandanten-Header

Ein Mandant, der nicht aufgelöst werden kann, wird abgelehnt, bevor irgendein Routen-Body ausgeführt wird, und die Ablehnung gibt nichts preis, was einem Aufrufer erlauben würde, aufzuzählen, welche Mandanten existieren.

test_a11a_an_unknown_tenant_header_is_refusedtest_a11a_an_unknown_tenant_is_indistinguishable_from_a_forbidden_one

A11b

Mandantenübergreifender Objektzugriff

Jede mandantenbezogene Suche filtert nach dem vertrauenswürdigen Mandanten. Ein bekannter Mandant kann auf keiner Oberfläche die Anfrage, Zahlung oder Berechtigung eines anderen Mandanten lesen oder darauf einwirken.

test_a11b_checkout_authority_route_refuses_another_tenants_requesttest_a11b_razorpay_route_refuses_another_tenants_authoritytest_a11b_mcp_refuses_another_tenants_payment

A12

Kollision des Idempotenzschlüssels

Ein mit einem anderen Kauf wiederverwendeter Schlüssel gibt die ursprüngliche Entscheidung und einen 409 zurück. Der zweite Kauf wird nie erstellt und kann nicht mit einem akzeptierten verwechselt werden.

test_a12_a_reused_key_with_a_different_purchase_returns_the_first_decision

A13

Richtlinienabweichung zwischen Autorisierung und Verwendung

Eine Berechtigung überlebt weder die Richtlinie, gegen die sie geprüft wurde, noch den Kauf, für den sie ausgestellt wurde. Eine ersetzende Richtlinie oder ein geänderter Betrag widerruft sie, ohne sie zu verbrauchen, und eine nicht abweichende Berechtigung funktioniert weiterhin.

test_a13_an_authority_is_valid_until_the_policy_under_it_movestest_a13_a_policy_published_after_authorization_revokes_the_authoritytest_a13_an_amount_edited_after_authorization_breaks_the_snapshot_hash

A14

Veralteter oder nachdatierter Webhook

Eine Signatur beweist die Herkunft, nicht die Aktualität. Ein Ereignis außerhalb des Frischefensters, in die Zukunft datiert oder ganz ohne Zeitstempel wird vor jeder Suche abgelehnt.

test_a14_a_stale_signed_event_is_refusedtest_a14_a_post_dated_event_cannot_extend_its_own_validitytest_a14_an_event_with_no_timestamp_is_refused_rather_than_exempted

A15

Nicht autorisierte Erfassung über MCP

Kein für den Agenten erreichbares Werkzeug kann autorisieren, erfassen, erstatten oder einen Provider aufrufen. Bewiesen durch Ausübung jedes exponierten Werkzeugs, nicht durch Inspektion von Werkzeugnamen.

test_a15_every_exposed_mcp_tool_grants_no_payment_authoritytest_a15_mcp_exposes_no_provider_or_authorization_tool

Jedes Tier-A-Szenario ist implementiert. A11a und A11b teilen die Mandantenverwechslung in einen nicht auflösbaren Mandanten und einen bekannten Mandanten, der die Grenze überschreitet, weil die beiden aus unterschiedlichen Gründen fehlschlagen und nur das zweite eine Autorisierungsfrage ist.

Was die Tests wert sind

Eine erfolgreiche Testsuite sagt, dass sich der Code wie geschrieben verhält. Sie sagt nicht, dass die Tests Einspruch erheben würden, wenn der Code aufhört, etwas Wichtiges zu tun, und nur die zweite Behauptung zählt, wenn es um Geld geht. Dieses Projekt hat Belege für den Unterschied: Anforderungsbezogene Sitzungen verwarfen einst jeden Schreibvorgang, während 146 Tests bestanden, weil die Suite innerhalb derselben Transaktion prüfte, in die sie schrieb.

make mutation bricht jede Sicherheitsinvariante absichtlich, eine nach der anderen, und verlangt, dass die als Wächter benannten Tests fehlschlagen. Jede Quelldatei wird in einem finally-Block wiederhergestellt, und die Wiederherstellung wird vor dem Drucken des Berichts gegen git diff geprüft, sodass ein unterbrochener Lauf keine Mutation hinterlassen kann. Es beendet sich mit einem Nicht-Null-Exitcode, wenn irgendeine Mutation überlebt.

Diese Tabelle wird aus dem Mutationsregister von python -m scenarios.report --mutations generiert, und ein Test stellt sicher, dass sie übereinstimmt, sodass sie keine bewachte Invariante behaupten kann, die nicht tatsächlich bewacht ist.

Mutation

Invariant it removes

payment-row-lock

Eine Zahlung wird gesperrt, bevor ihr Zustand gelesen und geändert wird.

locked-read-freshness

Ein gesperrter Lesevorgang entscheidet anhand der committeten Zeile, nicht anhand einer gecachten.

locking-discipline

Zeilensperren werden über den einen Helfer erworben, der sie sinnvoll hält.

webhook-signature-check

Ein Provider-Ereignis wird authentifiziert, bevor irgendetwas damit geschieht.

webhook-freshness-window

Ein signiertes Provider-Ereignis beweist die Herkunft, nicht die Aktualität.

webhook-timestamp-required

Ein Ereignis, das nicht datiert werden kann, kann nicht begrenzt werden, daher wird es abgelehnt.

approval-expiry

Eine Genehmigung ist eine Berechtigung mit einer Lebensdauer, keine dauerhafte Erteilung.

authority-policy-drift

Eine Autorität überlebt nicht die Richtlinie, gegen die sie geprüft wurde.

authority-snapshot-binding

Eine Autorität ist an den genauen Kauf gebunden, für den sie ausgestellt wurde.

daily-budget-predicate

Das tägliche Budget-Upsert weigert sich, das Limit zu überschreiten.

budget-release-from-state-guard

Budget wird nur von einer Zahlung zurückgegeben, die es tatsächlich reserviert hat.

checkout-script-escaping

Katalogtext kann das Skriptelement der Checkout-Seite nicht beenden.

request-session-commit

Eine erfolgreiche Anfrage committet ihre Schreibvorgänge.

provider-event-identity

Lebenszyklus-Ereignisse für eine Zahlung sind eigenständige Ereignisse, keine Wiederholungen.

self-approval-guard

Eine Genehmigung kann nicht vom anfragenden Akteur erteilt werden.

evidence-tenant-filter

Beweise sind auf den Mandanten beschränkt, der sie angefordert hat.

receipt-search-fail-closed

Eine unvollständige Provider-Suche meldet eine Quittung nie als fehlend.

Der erste Lauf dieser Suite fand einen echten Defekt. SELECT ... FOR UPDATE über das ORM erwirbt die Sperre korrekt und verwirft dann die Zeile, die Postgres zurückgegeben hat, weil SQLAlchemy die Attribute eines Objekts, das sich bereits in der Identitätskarte der Sitzung befindet, beibehält. Ein zweiter Aufrufer blockierte daher wie vorgesehen an der Sperre, erhielt die committete Zeile, behielt seine veraltete Kopie und autorisierte eine Zahlung, die gerade erst autorisiert worden war. Die Sperre serialisierte, wann Übergänge liefen, nicht, von welchem Zustand sie ausgingen. Alle Sperrungen laufen jetzt über models.locking.locked(), und ein Test stellt sicher, dass dieser Helfer die einzige Stelle im Quellcode ist, die eine Sperre übernehmen kann.

Current Scope

TrustGate verwendet nur synthetische Mandanten, Händler und INR-Preise. Es ist ein lokales Sicherheits-Testfeld, kein Zahlungsabwickler, kein Compliance-Produkt, kein System für rechtliche Einwilligungen, kein Betrugsmodell und keine Live-Mode-Zahlungsintegration.

Quickstart

Voraussetzungen: Docker Desktop und 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

Der lokale API-Health-Check ist unter http://127.0.0.1:8000/health verfügbar.

Erstellen Sie einen wegwerfbaren synthetischen M1-Mandanten mit python -m agent.seed. Setzen Sie MCP_TENANT_ID und MCP_ACTOR_ID auf die ausgegebenen Werte und führen Sie dann die lokale Buyer-Agent-Demo mit python -m agent.demo "Buy Starter credits for our student club." aus. Sie kann nur eine Katalog-SKU, Menge und Zweck vorschlagen; der MCP-Server leitet alle geldkritischen Fakten ab. Verwenden Sie python -m agent.demo --adversarial "Buy a small amount of cloud credits.", um die deterministische Demonstration des vergifteten Katalogs auszuführen.

Um denselben Ablauf mit einem echten Modell anstelle eines deterministischen Ersatzes auszuführen, installieren Sie das optionale Extra mit pip install -e ".[agent]" und fügen Sie --live hinzu. Zwei Backends werden unterstützt und beide verwenden dieselbe Messages-API-Form:

  • TRUSTGATE_MODEL_BACKEND=anthropic (Standard) liest ANTHROPIC_API_KEY.

  • TRUSTGATE_MODEL_BACKEND=bedrock rechnet gegen ein AWS-Konto ab. Setzen Sie AWS_REGION auf die Region, zu der die Anmeldedaten gehören, und dann entweder AWS_BEARER_TOKEN_BEDROCK (einen Bedrock-API-Schlüssel, den einfachsten Weg) oder Standard-AWS-Anmeldedaten für die SigV4-Signierung. Amazon Bedrock stellt Anthropic-Modelle über ein AWS-Marketplace-Abonnement bereit, daher benötigt das AWS-Konto auch ein gültiges Zahlungsmittel, selbst wenn Guthaben die Nutzung abdecken würde.

  • TRUSTGATE_MODEL_BACKEND=groq liest GROQ_API_KEY und benötigt überhaupt kein Zahlungsmittel.

TRUSTGATE_MODEL_ID überschreibt das Modell auf jedem Backend. Der Käufer ist eine Protokollimplementierung, daher ist der Anbieter eine Konfigurationsentscheidung und keine architektonische: Das Verhalten der Autorisierungsschicht hängt nicht davon ab, welches Modell den Kauf vorschlägt.

Dies ist der einzige Pfad im Projekt, der einen Modellanbieter kontaktiert; die Testsuite tut das nie. Führen Sie ihn nur gegen den synthetischen Seed-Katalog aus. Seine Drittanbieter-Beschreibungen werden zweimal an das Modell gesendet, einmal ohne Beschreibungen und einmal intakt, um den Einfluss zu messen. Senden Sie niemals echte Kunden-, Händler- oder Zahlungsdaten durch diese Demonstration.

Um den Razorpay-Testmodus-Adapter zu testen, setzen Sie RAZORPAY_KEY_ID und RAZORPAY_KEY_SECRET in der ignorierten .env-Datei. Fügen Sie niemals Testmodus- oder Live-Modus-Geheimnisse zum Repository hinzu.

Trust Boundary

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

Der formale Build-Plan befindet sich in docs/build-plan.md; Architektur, Bedrohungsmodell und Designentscheidungen finden Sie in 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.

Maintenance

ActivityMaintained
ResponsivenessNo issues

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

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables 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.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables 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

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