Skip to content

Threat Model

This is a bank. It is modelled like one, STRIDE across every trust boundary, plus the abuse cases specific to consumer crypto that are how people actually lose money.

Trust boundaries

flowchart LR
    U["User + device"] ---|B1| C["Client app"]
    C ---|B2| S["AURA services"]
    S ---|B3| K["Kernel contracts"]
    C ---|B4| K
    S ---|B5| E["External providers<br/>Privy · Guard · KYC · RPC"]
    K ---|B6| CH["Base + token contracts"]
Boundary Assumed hostile?
B1 User ↔ device Device may be lost, stolen, or malware-infected
B2 Client ↔ services Client may be modified; requests may be forged
B3 Services ↔ kernel Services are untrusted. Design assumption.
B4 Client ↔ kernel Client may submit arbitrary operations
B5 Services ↔ providers Providers may be down, wrong, or compromised
B6 Kernel ↔ chain Chain may reorg; tokens may pause or blacklist

STRIDE, condensed

The properties below hold because policy lives in the kernel, not a backend.

Category Representative threat Why it fails / residual
Spoofing Relayer or 2FA service forges a payment Cannot, no user signature, no execution. This is the point of B3.
Sign-in as the user Privy + device-bound passkey; step-up on new device. Privy compromise mitigated by passkey as a separate factor.
Tampering Modified client raises its own limits Policy is on-chain; setPolicy is Tier 4 (invariant 4).
MITM alters the payee The signature covers the full UserOp hash, including calldata.
Queued intent altered before execution intentHash binds token, payee, and amount (invariant 6).
Repudiation "AURA moved my money" AURA structurally cannot, demonstrable from the contracts.
Info disclosure Payee names on a public ledger Names never go on-chain.
Balance/history linkable Inherent to a public chain, disclosed honestly; ZK is Phase 4.
Denial of service Paymaster drained Verifying paymaster + per-user budgets + circuit breaker.
Guard API flooded Rate-limited; fails closed.
Elevation Session key used beyond scope Per-tx cap, daily cap, trusted-payees-only, short expiry, all on-chain.
Uninstalling the security hook Tier 4.

One honest limitation, stated plainly

On a public chain, anyone with a user's account address can see their balance and every payment. The banking metaphor must not imply bank-grade privacy. The Phase 4 ZK work addresses this; until then it is disclosed, not hidden.

The abuse cases that actually take people's money

STRIDE misses these, and they are the ones that matter in consumer payments.

  1. Authorised push-payment fraud, the user is tricked into sending willingly; every technical control passes. The single largest category of loss in UK consumer payments. Mitigations: first-payment cooling-off to a new payee (Tier 3), payee-name confirmation, an explicit irreversibility notice, anomaly detection. Residual risk is real and cannot be eliminated, but a 30-minute delay on a first large payment to a new payee is the highest-leverage control that exists, which is why it lives in the kernel, not the UI.
  2. Wrong-chain / wrong-asset loss, the category's defining failure. Addressed by AURA Guard and the refusal state. Residual: the receive screen, where an outside sender is beyond our control, hence a blunt, undismissible warning there.
  3. Device theft with an unlocked session, session keys are capped and trusted-payees-only; anything meaningful needs biometrics; new-device + new-payee + large is always Tier 4.
  4. Coerced transfer, the cooling-off window lets the user cancel after coercion ends. A duress mechanism is deferred; a fake-PIN-that-silently-fails is its own hazard.
  5. Malicious token contracts, mitigated by the allowlist: four vetted stablecoins and nothing else.
  6. Compliance-side loss, USDC/USDT issuers can freeze and blacklist addresses. AURA cannot prevent this and must not imply it can; it is disclosed, detected, and communicated if it happens.

Assumptions, made explicit

  1. Base's sequencer is honest and available. If not, payments stall; funds are safe.
  2. Circle and Tether do not arbitrarily freeze our users. Outside our control.
  3. Privy does not maliciously reconstruct keys. Mitigated by passkey as an independent factor and by the pluggable signer.
  4. The audited contract code does what the audit says. Mitigated by audit + invariant tests + a bug bounty.
  5. Users read the wrong-chain warning. Partly false, hence controls, not just copy.

Public-origin hardening (the demo)

The live testnet demo is a public origin, so it carries defence-in-depth independent of the contracts: security headers (X-Frame-Options: DENY, HSTS, a strict Referrer-Policy and Permissions-Policy), per-IP rate limits that are tighter on the routes that spend testnet gas, scanner user-agent blocking, and a shared rate-limiter behind the app that counts per account rather than per IP. The provisioning path is rate-limited and monitored for balance so it cannot be drained silently.

Required before real money

  • [ ] External audit of the full contract suite
  • [ ] Invariant and fuzz tests covering all seven contract invariants
  • [ ] Fork tests against real token contracts on Base
  • [ ] The escape hatch tested end to end with every AURA service offline
  • [ ] Paymaster abuse testing
  • [ ] Recovery threat-modelled on its own terms
  • [ ] Incident-response runbook, including who may pull the pause and who may not
  • [ ] Bug bounty live before mainnet

Until every box is ticked, this system stays on testnet.