Inspiration

Business email compromise is the classic fraud against accounts payable: a message pretends to be a vendor and says “our payment details changed”. AI agents add a worse version, because instructions hidden in an email, an invoice or persistent memory can steer the agent, and the poison survives across sessions. Most guardrails cap amounts and keep allowlists. They never ask the question that actually matters: where did this payee come from, and is that source allowed to set it?

What it does

Lineage sits between an AI agent and the money rail.

  • Every email, chat message, memory entry and tool result becomes a fragment with a trust tier assigned by our code, never by the model: T3 owner, T2 trusted records, T1 known sender (spoofable), T0 untrusted.
  • Before a payment, the payee is traced back through the context. If it only appears in T0 sources, the payment is held as an owner approval that shows its full lineage.
  • The amount is bound to the approved purchase order, and a payee belonging to another vendor is rejected, which catches the confused-deputy case that a plain allowlist waves through.
  • The executor pays only the exact arguments that were decided, once. Every step goes into a hash-chained audit log.
  • The check runs outside the model, so even a jailbroken agent can’t talk its way past it.

How we built it

  • Go guard, executor and audit log, on SQLite, with a JSON API.
  • Next.js (TypeScript) website with a connected console: a provenance graph, replay, a side-by-side Compare (no guard vs Lineage), owner approvals, an audit view, and a live Attack Lab where visitors try to phish the agent.
  • PayPal Payouts API (sandbox only; the host is pinned in code) as the payment rail.
  • A Rust signer that puts the same guard in front of NEAR Intents signing.
  • A reproducible benchmark, PayBench-BEC, with 17 scenarios (5 benign, 12 attack) and ablations.

PayPal usage

OAuth and the Payouts API, run end to end against the real PayPal sandbox. A legitimate invoice payout and an unguarded attack payout were each accepted by PayPal. The same attack behind Lineage was held for the owner with no payout. Credentials live only in the executor, so the agent can’t reach PayPal directly.

AI usage

The agent is an LLM tool-use loop (read inbox, look up vendor, recall memory, pay). The guard is deterministic and sits outside the model. Built with Claude Code. The benchmark’s attacker is a simulated compromised agent, and the optional real-model mode exists but has not been run yet.

Results

(from make bench, simulated compromised agent, 12 attacks)

Defense Attacks that moved money
No guard 12/12
Static limits only 9/12
Binding to records only 10/12
Provenance only 3/12
Full Lineage 0/12

All 5 benign scenarios still complete, and the guard decides in under 1 ms (p95). Each layer alone leaks in a different place, which is why Lineage uses all three.

Challenges

  • Showing provenance legibly: we ended up drawing the payee’s thread from its origin to the guard.
  • Honest benchmarking: every number comes from a run, the attacker is labelled simulated, and failures stay in.
  • PayPal sandbox specifics: Payouts are rejected from a sandbox business account in India, so the payer needs a supported country. The app reports a failed payout as “no money moved”, never as moved.

Limitations

Tracing matches identifiers exactly and doesn’t follow derived values, so amounts are bounded by the PO instead. A poisoned vendor master or a compromised owner channel is out of scope. The benchmark is small and author-written, and its attacker is simulated. This is a deterministic enforcement point with measured results, not a proof of security.

What’s next

Run the benchmark against real models, finish real NEAR Intents execution (the NEP-413 signer is built and checked against the live Verifier’s salt, but no real transaction has been made), and publish the benchmark.

Built With

Share this project:

Updates

Submission history