Security Model
Threat model, attack vectors, and security properties of IntentGuard.
Threat Model Summary
IntentGuard addresses 12 attack vectors documented in THREAT-MODEL.md:
| ID | Attack Vector | Status | Mitigation |
|---|---|---|---|
| A1 | Frontend compromise | Mitigated | Core design: device separation |
| A2 | Mobile device compromise | Residual | Biometric auth + SecureStore |
| A3 | Replay attack | Mitigated | PDA closed after verify/revoke |
| A4 | Stale intent (expired) | Mitigated | TTL enforcement (30s–3600s) |
| A5 | Cross-app attack | Mitigated | app_id in PDA seeds |
| A6 | Hash preimage | Mitigated | SHA-256 (2^256 preimage resistance) |
| A7 | Admin key compromise | Mitigated | Squads multisig + time lock |
| A8 | PDA squatting | Mitigated | Signer constraint on commit |
| A9 | Rent drain | Mitigated | close refunds rent to user |
| A10 | RPC manipulation | Residual | Fail-closed on RPC error |
| A11 | Protocol pause DoS | Mitigated | Revoke always available; multisig admin |
| A12 | TX ordering attack | Mitigated | has_one constraint (only owner) |
Security Properties
- Device separation — Intent is confirmed on a physically separate device
- Atomic verification — Verify instruction is part of the TX; mismatch = full revert
- Per-user per-app isolation — PDA seeds:
[b"intent", user, app_id] - One active intent — Only 1 pending intent per user per app (Anchor init constraint)
- Signer-only access — Only the wallet owner can commit, verify, or revoke
- Checked arithmetic — All counters use
checked_add - Fail-closed — Extension blocks transactions on RPC error (not fail-open)
On-Chain Security
Access Control
// Every user instruction requires signer
#[account(mut)]
pub user: Signer<'info>,
// has_one ensures stored user matches signer
#[account(
has_one = user,
seeds = [b"intent", user.key().as_ref(), intent_commit.app_id.as_ref()],
bump = intent_commit.bump,
)]
Admin Protections
- Admin instructions check
config.admin == signer - Cannot transfer admin to zero address or system program
- MAX_MIN_BALANCE = 1 SOL (prevents lockout via spam protection)
- MAX_VERIFY_FEE = 0.1 SOL (prevents fee abuse)
- Mainnet: admin transferred to Squads multisig vault
Extension Security
- XSS prevention — All user input sanitized with
textContent(notinnerHTML) - Bypass list — Max 50 entries, validated hostnames only
- Pairing keys — Non-extractable CryptoKey, no JWK export
- Request IDs —
crypto.getRandomValues(not sequential) - Content script — No global state leaks, scoped poll timers
Test Coverage
| Category | Tests | Description |
|---|---|---|
| On-chain integration | 29 | Full flow, access control, TTL, admin |
| On-chain security | 43 | 12 attack vectors, edge cases |
| Trident fuzzing | ~1M instructions | 8 flows, 5K iterations, 0 violations |
| Unit tests (vitest) | 612 | SDK, extension, pairing, security |
Bug Bounty
| Severity | Reward | Example |
|---|---|---|
| Critical | $50,000 | Fund theft, unauthorized verify |
| High | $10,000 | Admin bypass, intent manipulation |
| Medium | $2,000 | Counter corruption, fee drain |
| Low | $500 | Informational findings |
Report: [email protected] — 48hr acknowledgment SLA. See SECURITY.md for full details.