Inspiration

AI agents are quickly moving from suggesting actions to taking them, and spending money is the riskiest action of all. The common approach today is to hand an agent payment credentials and hope the system prompt keeps it in line. But prompts fail under indirect prompt injection: a poisoned invoice, a lookalike payee, or a runaway retry loop can drain a budget in seconds.

We asked a simple question: what if the agent never had financial authority in the first place? That became PayGuard, a firewall that sits between untrusted AI agents and PayPal.

What it does

PayGuard is a deterministic MCP policy firewall for autonomous AI agent payments, built on PayPal Sandbox.

  • Four tools only. Agents connect over a Model Context Protocol (MCP) gateway that exposes exactly four tools: request_payment, get_payment_status, get_budget, and list_vendors. Agents can never approve, capture, void, refund, or edit policy.
  • Deterministic policy engine. Every request is evaluated against vendor allowlists, categories, currencies, rolling 24-hour budgets, velocity limits, and duplicate windows. The rule is DENY > HOLD > ALLOW.
  • Human-in-the-loop approvals. Payments under the auto-approve limit ($15) execute instantly. Larger ones are authorized and held for the owner to approve or void. Unapproved holds fail closed and expire automatically.
  • Stricter-only AI advisor. Google Gemini screens for prompt injection, explains risk in plain English, and drafts policies from natural language. It can only make a decision stricter, never looser, and can never move money.
  • Owner dashboard. A React console with Overview, Payments, Approvals, AI Agents, Policies, Vendors, Audit Log, and Settings pages.
  • Tamper-evident audit log. Every state change is written to an append-only, SHA-256 hash-chained log.

How we built it

  • Backend: Node.js, TypeScript (strict), Express 5, and the official MCP SDK using Streamable HTTP.
  • Storage: SQLite in WAL mode with BEGIN IMMEDIATE transactions, an ACID ledger (RESERVE / SPEND / RELEASE), and abort triggers that block updates and deletes on the audit table.
  • Payments: PayPal Sandbox APIs. Vault v3 for buyer wallets, Orders v2 for CAPTURE (allow) and AUTHORIZE (hold), and Authorizations v2 for capture and void.
  • AI: Gemini (gemini-3.5-flash-lite) with Zod-validated structured output for a two-stage injection detector, a risk explainer, and a policy drafter.
  • Frontend: React 19, Vite, and Tailwind 4.
  • Security: Argon2id owner sessions, HttpOnly SameSite=Strict cookies, CSRF tokens, constant-time webhook verification, a strict CSP on approval pages, and a hard lock to the sandbox environment.
  • Workers: a 30-second hold-expiry worker and a 60-second reconciler that recovers ambiguous orders and voids.

A single executeDecision() choke point is the only code path in the system that can touch PayPal.

Challenges we ran into

  • Ambiguous payment states. Network failures can leave a PayPal order or void in an unknown state. We built a dual-attestation reconciler so the ledger and PayPal never silently disagree, and it records RECONCILIATION_UNRESOLVED events in the audit log until the state can be proven.
  • Keeping the AI from becoming the authority. It was tempting to let the model decide. We enforced the opposite as a hard invariant: AI output can only escalate a decision, never relax one.
  • Money correctness. We used integer minor units everywhere, idempotency keys, and snapshot-hashed holds so an approved payment is exactly the one the owner reviewed.
  • Fail-closed everywhere. Expired holds, missing sessions, and misconfiguration all default to denial rather than permission.

Accomplishments that we're proud of

  • A real PayPal Sandbox flow covering authorize, capture, and void, tied to an internal ledger.
  • 1,434 automated tests across 64 files passing, plus typecheck and lint.
  • An adversarial test suite with 12 attack vectors, all ending in $0.00 of unauthorized spend.
  • A clear separation of powers: agents ask, the policy engine decides, humans approve, and AI only advises.

What we learned

Safety for agentic payments can't live in prompts. It has to live in architecture: least-privilege tools, deterministic rules, a single execution choke point, and an honest audit trail. We also learned how much hidden complexity sits in "just void the payment" once networks and retries are involved.

What's next for PayGuard

  • Live Telegram approvals (built, but not yet verified end-to-end)
  • stdio MCP transport support
  • Remote WORM anchoring of the audit chain, to defend against offline disk tampering
  • Per-category and per-vendor policy rules, and multi-owner approval flows
  • Production hardening and a verified Docker deployment

PayGuard targets PayPal Sandbox exclusively. No real money moves.

Share this project:

Updates

Submission history