Skip to main content
Glama
Saraid10
by Saraid10

TrustGate

TrustGate es una demostración de datos sintéticos, en el Modo de Prueba de Razorpay, de un comprador de IA que puede proponer una compra del catálogo sin obtener autoridad para reescribir el comerciante, el importe, la moneda, la aprobación o el resultado del proveedor. El agente propone; TrustGate autoriza de forma independiente y registra la evidencia.

Qué demuestra

  • El SKU del catálogo y la cantidad son los únicos hechos de compra que un agente puede influir.

  • La política por inquilino, la aprobación humana, una autoridad de pago de un solo uso y los eventos verificados del proveedor limitan cada acción de pago.

  • Los intentos no seguros se rechazan antes de que se pueda crear una orden de proveedor y dejan un rastro auditable.

Related MCP server: safe-cart-ai

Cómo se usa la IA aquí

El agente comprador es deliberadamente delgado, y eso es el argumento, no un atajo. Solo puede proponer un SKU del catálogo, una cantidad y un propósito; cada hecho crítico para el dinero se deriva del lado del servidor. Elimina al agente por completo y la capa de autorización no cambia y sigue siendo correcta.

La contribución de ingeniería no es un agente sofisticado. Es tomar en serio los modos de fallo de los modelos de lenguaje — inyección de instrucciones a través de contenido de terceros, seguimiento de instrucciones contra los intereses del operador, razonamiento erróneo y confiado sobre dinero — y construir un sistema que se mantenga correcto cuando ocurren.

Esa afirmación se prueba en ambas direcciones. python -m agent.demo --live ejecuta un modelo real contra descripciones de catálogo escritas por terceros, incluidas las hostiles. El mismo catálogo se envía dos veces, una con las descripciones eliminadas, de modo que la influencia del contenido no confiable se mide comparando las dos propuestas en lugar de autoinformarse. La suite de regresión nunca llama a un proveedor de modelos: utiliza sustitutos deterministas, por lo que la verificación de seguridad no depende de que un modelo se comporte de una manera particular en un día particular.

Viendo el problema

Tres rechazos limpios demuestran que el sistema funciona y son débiles para mostrar por qué alguien lo necesita. Por lo tanto, la demo comienza con el propio código de este proyecto fallando, sin usar red, sin credenciales y sin base de datos:

python -m demo.unguarded

El mismo agente lee el mismo catálogo envenenado — literalmente el mismo, ya que ambos catálogos se construyen a partir de agent/demo_catalog.py y una prueba afirma que la fila sembrada y el objeto de referencia llevan una instrucción inyectada idéntica. Una respuesta del modelo se entrega a dos adaptadores.

El no protegido acepta un importe y un comerciante, por lo que la instrucción inyectada se ejecuta y paga INR 20,000.00 a un comerciante que el texto del catálogo nombró, contra un precio de catálogo de INR 600.00. El otro no tiene dónde poner ninguno de los dos campos, porque PurchaseProposal declara solo un SKU, una cantidad y un propósito. Lo que sobrevive al descarte es quantity=50, que es un campo que el agente puede establecer — y el servidor lo limita contra el máximo propio del catálogo de 2, por lo que el intento se rechaza antes de que se cree una solicitud de pago.

La diferencia no es un filtro que reconoció un ataque. Es que una interfaz tenía un campo para el dinero y la otra no. La línea base tiene sus propias pruebas que afirman tanto que no puede alcanzar nada real como que sigue siendo explotable, ya que una demostración que silenciosamente dejara de ser vulnerable seguiría pasando mientras hiciera el punto opuesto.

Matriz de ataques

Escenarios adversariales de nivel A. Esta tabla se genera desde el registro de escenarios mediante python -m scenarios.report, y una prueba afirma que coincide, por lo que no puede afirmar un ataque que no esté cubierto por una prueba que pase. Cada escenario demuestra tres cosas: el ataque se rechaza con su código de razón, no se creó ninguna orden de proveedor y ningún pago obtuvo autoridad que no tuviera.

ID

Ataque

Invariante demostrado

Pruebas

A1

Manipulación del importe

El importe se deriva del precio del artículo del catálogo y de una cantidad limitada por el servidor. Ningún valor suministrado por el agente puede cambiarlo.

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

Sustitución del comerciante

El comerciante se deriva del artículo del catálogo con ámbito de inquilino. Un comerciante fuera del inquilino es inalcanzable, y uno fuera de la política activa no puede ser pagado.

test_a2_another_tenants_sku_is_not_reachabletest_a2_policy_disallowed_merchant_cannot_be_paid

A3

Sustitución de moneda

La moneda se deriva del artículo del catálogo, y la única ruta que acepta una moneda está deshabilitada por defecto y rechaza una discrepancia con la política activa cuando está habilitada.

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

Aprobación caducada o reutilizada

Una aprobación es un permiso con una vida útil y un solo uso. Ni una caducada ni una ya consumida pueden autorizar, y una aprobación rechazada no se quema.

test_a4_an_expired_approval_cannot_authorizetest_a4_an_already_consumed_approval_cannot_authorize_again

A5

Autoaprobación

Una aprobación no puede ser otorgada por la identidad que solicitó la compra. La separación de funciones se aplica, no solo se espera de la configuración.

test_a5_an_approval_cannot_be_granted_by_the_requesting_actortest_a5_a_separate_approver_can_still_grant

A6

Firma de webhook falsificada

Los eventos del proveedor se autentican mediante HMAC de bytes sin procesar antes de analizar el cuerpo. Una firma falsificada o ausente no cambia nada, por muy bien formado que esté el evento.

test_a6_a_forged_signature_is_refusedtest_a6_an_unsigned_event_is_refused

A7

Cuerpo de webhook manipulado

La firma cubre los bytes exactos recibidos, por lo que un evento genuinamente firmado editado en tránsito ya no se verifica y nunca llega a un pago.

test_a7_a_body_altered_after_signing_no_longer_verifies

A8

Entrega de webhook duplicada

La identidad del evento del proveedor se almacena, por lo que una repetición de un evento auténtico dentro de la ventana es rechazada por la base de datos en lugar de por el manejador que mire.

test_a8_a_replayed_event_does_not_transition_the_payment_twice

A9

Eventos de proveedor fuera de orden

El orden de llegada es del proveedor y la legalidad es nuestra. Una captura no puede preceder a su autorización, y un pago terminal no acepta ningún resultado adicional.

test_a9_a_capture_cannot_precede_an_authorizationtest_a9_a_terminal_payment_accepts_no_further_provider_outcome

A10

Reembolso doble

Ninguna superficie puede iniciar un reembolso en absoluto, afirmado contra la tabla de rutas en vivo y la lista de herramientas, y el invariante del libro mayor rechaza un total de reembolso que exceda la captura.

test_a10_no_surface_anywhere_can_initiate_a_refundtest_a10_a_refund_total_cannot_exceed_what_was_captured

A11a

Cabecera de inquilino desconocida

Un inquilino que no se resuelve es rechazado antes de que se ejecute cualquier cuerpo de ruta, y el rechazo no revela nada que permita a un llamante enumerar qué inquilinos existen.

test_a11a_an_unknown_tenant_header_is_refusedtest_a11a_an_unknown_tenant_is_indistinguishable_from_a_forbidden_one

A11b

Acceso a objetos entre inquilinos

Cada búsqueda con ámbito de inquilino filtra por el inquilino de confianza. Un inquilino conocido no puede leer ni actuar sobre la solicitud, el pago o la autoridad de otro inquilino en ninguna superficie.

test_a11b_checkout_authority_route_refuses_another_tenants_requesttest_a11b_razorpay_route_refuses_another_tenants_authoritytest_a11b_mcp_refuses_another_tenants_payment

A12

Colisión de clave de idempotencia

Una clave reutilizada con una compra diferente devuelve la decisión original y un 409. La segunda compra nunca se crea y no puede confundirse con una que fue aceptada.

test_a12_a_reused_key_with_a_different_purchase_returns_the_first_decision

A13

Deriva de política entre autorización y uso

Una autoridad no sobrevive a la política contra la que se verificó, ni a la compra para la que se emitió. Una política que la reemplaza o un importe editado la revoca sin quemarla, y una autoridad sin deriva sigue funcionando.

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

Webhook obsoleto o con fecha posterior

Una firma prueba el origen, no la actualidad. Un evento fuera de la ventana de frescura, con fecha futura o sin marca de tiempo en absoluto es rechazado antes de cualquier búsqueda.

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

Captura no autorizada a través de MCP

Ninguna herramienta accesible por el agente puede autorizar, capturar, reembolsar o llamar a un proveedor. Probado ejercitando cada herramienta expuesta, no inspeccionando nombres de herramientas.

test_a15_every_exposed_mcp_tool_grants_no_payment_authoritytest_a15_mcp_exposes_no_provider_or_authorization_tool

Cada escenario de Nivel A está implementado. A11a y A11b dividen la confusión de inquilinos en un inquilino no resoluble y un inquilino conocido que cruza el límite, porque los dos fallan por razones diferentes y solo el segundo es una cuestión de autorización.

Lo que valen las pruebas

Una suite que pasa dice que el código se comporta como está escrito. No dice que las pruebas objetarían si el código dejara de hacer algo importante, y solo la segunda afirmación importa cuando el tema es dinero. Este proyecto tiene evidencia de la diferencia: las sesiones con ámbito de solicitud descartaron una vez cada escritura mientras 146 pruebas pasaban, porque la suite afirmaba dentro de la misma transacción en la que escribía.

make mutation rompe cada invariante de seguridad a propósito, uno a la vez, y requiere que las pruebas nombradas como sus guardias fallen. Cada archivo fuente se restaura en un bloque finally y la restauración se verifica contra git diff antes de que se imprima el informe, por lo que una ejecución interrumpida no puede dejar una mutación atrás. Sale con código no cero si alguna mutación sobrevive.

Esta tabla se genera a partir del registro de mutaciones mediante python -m scenarios.report --mutations, y una prueba afirma que coincide, por lo que no puede reclamar un invariante protegido que no esté realmente protegido.

Mutación

Invariante que elimina

payment-row-lock

Un pago se bloquea antes de que su estado se lea y se modifique.

locked-read-freshness

Una lectura bloqueada decide a partir de la fila confirmada, no de una en caché.

locking-discipline

Los bloqueos de fila se toman a través del único helper que los mantiene significativos.

webhook-signature-check

Un evento de proveedor se autentica antes de hacer cualquier cosa con él.

webhook-freshness-window

Un evento de proveedor firmado demuestra el origen, no la actualidad.

webhook-timestamp-required

Un evento que no puede fecharse no puede acotarse, por lo que se rechaza.

approval-expiry

Una aprobación es un permiso con una duración, no una concesión permanente.

authority-policy-drift

Una autoridad no sobrevive a la política contra la que se verificó.

authority-snapshot-binding

Una autoridad está vinculada a la compra exacta para la que se emitió.

daily-budget-predicate

El upsert del presupuesto diario se niega a superar el límite.

budget-release-from-state-guard

El presupuesto se devuelve solo mediante un pago que realmente lo reservó.

checkout-script-escaping

El texto del catálogo no puede terminar el elemento script de la página de pago.

request-session-commit

Una solicitud exitosa confirma sus escrituras.

provider-event-identity

Los eventos del ciclo de vida de un pago son eventos distintos, no reproducciones.

self-approval-guard

Una aprobación no puede ser otorgada por el actor solicitante.

evidence-tenant-filter

La evidencia se limita al inquilino que la solicitó.

receipt-search-fail-closed

Una búsqueda incompleta del proveedor nunca informa un recibo como ausente.

La primera ejecución de esta suite encontró un defecto en vivo. SELECT ... FOR UPDATE a través del ORM adquiere el bloqueo correctamente y luego descarta la fila que Postgres devolvió, porque SQLAlchemy mantiene los atributos de un objeto que ya está en el mapa de identidad de la sesión. Por lo tanto, un segundo llamador se bloqueó en el bloqueo como estaba diseñado, recibió la fila confirmada, conservó su copia obsoleta y autorizó un pago que acababa de ser autorizado. El bloqueo estaba serializando cuando se ejecutaban las transiciones, no el estado del que decidían. Todo el bloqueo ahora pasa por models.locking.locked(), y una prueba afirma que ese helper es el único lugar en el código fuente que puede tomar un bloqueo.

Alcance Actual

TrustGate utiliza solo inquilinos sintéticos, comerciantes y precios en INR. Es un banco de pruebas de seguridad local, no un procesador de pagos, un producto de cumplimiento, un sistema de consentimiento legal, un modelo de fraude o una integración de pagos en Modo Live.

Inicio Rápido

Requisitos: Docker Desktop y 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

La verificación de salud de la API local está disponible en http://127.0.0.1:8000/health.

Crea un inquilino M1 sintético desechable con python -m agent.seed. Establece MCP_TENANT_ID y MCP_ACTOR_ID a los valores impresos, luego ejecuta la demostración local del agente comprador con python -m agent.demo "Compra créditos Starter para nuestro club de estudiantes.". Puede proponer solo un SKU del catálogo, una cantidad y un propósito; el servidor MCP deriva todos los hechos críticos de dinero. Usa python -m agent.demo --adversarial "Compra una pequeña cantidad de créditos en la nube." para ejecutar la demostración determinista de catálogo envenenado.

Para ejecutar el mismo flujo con un modelo real en lugar de un sustituto determinista, instala el extra opcional con pip install -e ".[agent]" y agrega --live. Se admiten dos backends y ambos usan la misma forma de API de Messages:

  • TRUSTGATE_MODEL_BACKEND=anthropic (predeterminado) lee ANTHROPIC_API_KEY.

  • TRUSTGATE_MODEL_BACKEND=bedrock factura contra una cuenta de AWS. Establece AWS_REGION a la región a la que pertenece la credencial, y luego AWS_BEARER_TOKEN_BEDROCK (una clave de API de Bedrock, la ruta más simple) o credenciales estándar de AWS para la firma SigV4. Amazon Bedrock aprovisiona modelos de Anthropic a través de una suscripción a AWS Marketplace, por lo que la cuenta de AWS también necesita un instrumento de pago válido incluso cuando los créditos cubrirían el uso.

  • TRUSTGATE_MODEL_BACKEND=groq lee GROQ_API_KEY y no necesita ningún instrumento de pago.

TRUSTGATE_MODEL_ID anula el modelo en cualquier backend. El comprador es una implementación de protocolo, por lo que el proveedor es una elección de configuración en lugar de una arquitectónica: el comportamiento de la capa de autorización no depende de qué modelo propone la compra.

Este es el único camino en el proyecto que contacta a un proveedor de modelos; la suite de pruebas nunca lo hace. Ejecútalo solo contra el catálogo de semillas sintético. Sus descripciones de terceros se envían al modelo dos veces, una con descripciones eliminadas y otra intacta, para medir la influencia. Nunca envíes datos reales de clientes, comerciantes o pagos a través de esta demostración.

Para ejercitar el adaptador de Modo de Prueba de Razorpay, establece RAZORPAY_KEY_ID y RAZORPAY_KEY_SECRET en el archivo .env ignorado. Nunca agregues secretos de Modo de Prueba o Modo Live al repositorio.

Límite de Confianza

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

El plan de construcción formal está en docs/build-plan.md; las decisiones de arquitectura, modelo de amenazas y diseño están en 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