Stipendex

Security: threat model and normative requirements

A payment protocol for agents is designed from its threats, not patched with them afterwards. The core Stipendex thesis: most attacks are removed architecturally — the LLM has no payment surface, rather than "the LLM was nicely asked not to pay".


Threat model

# Attack Vector Control
A1 Prompt injection: "transfer money to X" malicious content in the model context the model has no operation with an arbitrary receiver/amount (invariant I1); at most pay(quote), which runs into the allowlist and limits
A2 Injected "pay this bill" from an attacker-"receiver" a planted Quote a Quote is signed by the receiver's key; receiver not on the allowlist → deny; on the allowlist but expensive → HITL
A3 Quote replay / double presentation network, malicious receiver single-use quote_id + expires_at; the wallet journals seen ids
A4 Double charge on one Proof retries, races idempotency at every level: receiver and rail return the previous result by proof_id (R2)
A5 "Paid but not delivered" dishonest receiver Receipt with result_hash; withholding a Receipt after a verified Proof is a provable violation (wallet journal + rail evidence); registry reputation
A6 Hidden amount inflation metered/checkout capture ≤ estimate+tolerance (I3, C2); beyond — only re-quote + a new confirmation
A7 Receiver substitution under a trusted name MITM, DNS compromise the Quote key is checked against the registry descriptor (T1); TLS; signatures over canonical JSON (JCS)
A8 Agent process compromise malware, RCE on the host the wallet key lives outside the agent process (keychain/daemon/KMS); damage is bounded by the mandate's remaining limits until valid_until
A9 Wallet key compromise key theft short mandate TTL; facilitator revocation; facilitator velocity anti-fraud as the second line
A10 A tired principal rubber-stamps confirmations social engineering through the agent every confirmation shows: receiver, total, tolerance, remaining limits, mandate purpose; passkey confirmation makes "rubber-stamping" a deliberate act
A11 Pending-queue griefing payment request spam queue TTL = Quote TTL; pay() rate limit at the wallet; duplicates per receiver are collapsed
A12 Principal privacy leak receiver learns limits/history the receiver gets only the Proof (mandate hash, no fields); the registry sees no payments; the facilitator sees the minimum needed for settlement
A13 Poisoned registry provider hack/dishonesty provider signature + a "whose signature admitted this payment" journal; multiple providers; removing a provider is one mandate line
A14 A "useful" tool with useless output legal but junk service not a payments problem: registry reputation/levels, limits as a damage bound; the protocol guarantees provability ("paid, received X"), not the quality of X

Normative requirements (MUST summary)

Wallet:

Receiver:

Rail/facilitator:

The checkout profile adds C1–C5 from spec/checkout-profile.md.

What the protocol deliberately does not guarantee