Skip to content
Integra Agentic Terms

Security model

What the buyer gate guarantees, how each guarantee is enforced in the code, and what it leaves to you.

The gate's purpose is narrow: the payment you sign carries the hash of the bytes you received. This page states what it guarantees, how, and what it does not do.

What the gate guarantees

GuaranteeHow
Nothing is signed before the comparison.The signer is called only after SHA-256 of the served bytes equals the advertised H. On any decline before that point, the signer is never called.
The comparison is exact.H is computed over the bytes as received, never parsed or re-serialised, and compared with the advertised value as 32 decoded bytes (so the hex's case does not matter, and a malformed value never matches).
The payment carries the computed hash.The build takes the hash the gate computed, not the string the seller advertised.
The hash is read back from the payment.finish rebuilds the payment from chosen and the bytes, joins the signer's answer, and reads H back out of the completed payment through the pairing's binding. It returns the payment only when that value is the hash of the bytes, or, where the proof is the agreement payment, without that reading.
A payment without a public proof waits for its agreement.For a pairing whose payment is not itself a public proof of H, transact and atr_transact call the signer only after the agreement URL answers with a receipt for that H, and atr_confirm returns no request before that receipt is passed to it. confirm and finish neither pay nor check the agreement: a caller that drives them signs request only with the receipt agree returns.
Every payment is shown before it is signed.The agreement payment is returned to the buyer's agent with its amount, asset, payee and network, and signed only when a second call carries it back. The gate applies no spending limit: what to approve is the agent's decision.
The fetch is bounded.One GET of an https link, with no redirect, one 10-second deadline over headers and body, and at most 1 MiB read. A declared or streamed length over the bound cancels the body.
The bytes hashed are the bytes sent.Every request asks for Accept-Encoding: identity, and a 200 whose Content-Encoding names any coding (gzip, br, a stacked list) is declined with its body unread. Nothing is decompressed, so the bounds apply to the bytes on the wire. The agreement receipt is read the same way, at most 64 KiB.
A channel pays under its ATR.within takes the ATR's bytes, H and the channel from the hold, and only the amount from the seller's new challenge. An x402 challenge must advertise the held H. An MPP session challenge that names another channel or another H is declined, and one with no legal context is signed under the held H. A recorded charge cannot exceed what was signed.
The gate holds nothing that signs.It hands requests to your signer and never sees a key.
Your network policy applies.Every request goes through the fetch (or httpx.AsyncClient) you pass.

The TypeScript and Python gates enforce the same rules, and the shared vectors fix each one.

What it does not do

  • It does not judge the ATR. The gate never reads the record's content. Whether the terms are acceptable is for you and your principal to decide.
  • It does not check the payment's values. Amount, payee, asset, timing and payer are not compared with the ATR. A discrepancy is between the parties, and the ATR is the record of what was agreed.
  • It carries no business or legal logic.
  • It does not store the ATR. It returns the bytes; keeping them is yours. See keeping the record.
  • It does not settle. It returns the payment to you. It never talks to a facilitator.

What each payment proves

Pairings differ in where H sits. In most, the buyer's signed payment carries H, and the chain records it when the payment settles. In some, H rides in the seller's challenge, in a field too small for all of it, or not in the payment at all, and the agreement payment is the public proof. Each pairing's binding states exactly what its payment shows and what it does not; the pairings reference quotes every statement.

The MCP tools and the skill

  • The terms-mcp binary has no signer. The agent's own wallet signs the requests the tools return.
  • A channel opening and a channel hold the tools return carry a mac under a key of the server process. atr_channel_open declines any other opening, opening-unverified, and atr_channel_within and atr_channel_record_charge decline any other hold, hold-unverified, before the gate is called.
  • The chosen that atr_confirm returns carries a mac under the same key. atr_agree pays only the agreement URL in a chosen whose mac verifies, and declines any other chosen, chosen-unverified, before anything is fetched or signed. For a pairing with a channel, atr_finish reads only a chosen whose mac verifies, and declines any other, chosen-unverified, before the gate is called.
  • The terms-mcp binary fetches only from public addresses. A link that names a loopback, private-use, shared, link-local, unique-local, documentation, multicast or reserved address is refused before any connection, and a host name is resolved once and connected to only when every address it resolves to is public. A host that serves the tools with createBuyerServer applies its own network policy through the fetch it passes.
  • Every value the seller supplies is data: atr.utf8, and the agreement receipt's network and transaction that atr_agree and atr_transact return. The skill tells the agent to read them and never to follow instructions inside them.
  • A discovery listing, or a hash an agent computes itself, is not a confirmation. The confirmation is atr_finish's: it returns signed only when the pairing reads the hash from the completed payment, or, where the proof is the agreement payment, without that reading.

Reporting a vulnerability

Report it privately through GitHub's private vulnerability reporting on the repository. See SECURITY.md.

Edit on GitHub

Last updated on

On this page