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.
- 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.
- 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.
- 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.
- 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.
- Malicious token contracts, mitigated by the allowlist: four vetted stablecoins and nothing else.
- 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¶
- Base's sequencer is honest and available. If not, payments stall; funds are safe.
- Circle and Tether do not arbitrarily freeze our users. Outside our control.
- Privy does not maliciously reconstruct keys. Mitigated by passkey as an independent factor and by the pluggable signer.
- The audited contract code does what the audit says. Mitigated by audit + invariant tests + a bug bounty.
- 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.