STRIDE per surface, with named adversaries and concrete mitigations. Cross-reference: plan.md §20; technical_spec.md §11.
Document version: 1.0 Last updated: 2026-05-07
Aura runs on the user’s personal device, reads system signals and OAuth-scoped cloud APIs, and stores a structured graph encrypted at rest. The trust narrative on slide 9 (plan.md §20.3) is the load-bearing claim: the user owns their data, can see and erase it, and no byte leaves the device without an explicit user-initiated action.
This threat model assumes:
Out of scope: nation-state adversaries, physical hardware attacks (chip decap), supply-chain attacks against Google or Apple themselves, unfixed kernel zero-days.
memory.sqlite and the agent service| Threat | STRIDE | Concrete | Mitigation |
|---|---|---|---|
| Spoofing | S | Malicious app issues a deep link aura://confirm?id=... to fake a confirm |
Deep links are signed with an app-internal HMAC; Aura ignores unsigned links. Tap-to-confirm requires foreground presentation of the originating card. |
| Tampering | T | Malicious app or rooted attacker modifies memory.sqlite |
DB encrypted with SQLCipher AES-256 (ADR-0007). Daily Merkle root in Settings lets the user detect retroactive edits. |
| Repudiation | R | User claims they did not authorise an action | Every action’s trace records outcome ∈ {confirmed, dismissed, timed_out, executed_auto, failed} with tap_lat_ms and the originating trigger.source. |
| Information disclosure | I | A curious app reads memory contents | App sandbox; SQLCipher; android:allowBackup="false"; iOS NSFileProtectionComplete and kCFURLIsExcludedFromBackupKey. |
| DoS | D | Notification storm overflows queues | Bounded queues with drop-oldest semantics (signal_q 1024, notif_q 256, usage_q 256, ime_q 64). Backpressure metric written to telemetry. Orchestrator runs in a single foreground service with WorkManager / BGProcessingTask scheduling that survives transient pressure. |
| Elevation of privilege | E | Non-Aura code calls a privileged tool | Tool dispatcher checks the caller via Binder.getCallingUid() (Android) / XPC peer audit token (iOS). The tool catalogue (ADR-0009) is locked at compile time. |
| Threat | Mitigation |
|---|---|
| Sniffing the WatchConnectivity / Wear OS Data Layer payload | Apple’s link is encrypted and device-paired. Wear OS pairing is over the Companion Device Manager. We ship no Bluetooth fallback that bypasses pairing. |
| Earbud TTS overheard by a bystander | Hard cap of 1 TTS per active session. The user can disable the EARBUD surface entirely from Settings → Surfaces. TTS payload contains only the action kind, never raw signal values. |
| Watch glance text leaks group name | Glance shows only chosen and a three-word rationale; channel names are redacted before send. |
| Threat | Mitigation |
|---|---|
| Pairing with attacker’s device | First pair displays a 6-digit code on both ends; user must match. State expires after 24 hours idle. |
| Replay of an old payload | Each payload is timestamped and a 60-second replay window is enforced; older payloads are discarded. |
| Bystander on the same Wi-Fi reads payloads | Multipeer (iOS) uses encrypted sessions by default (MCEncryptionPreference.required). Nearby Connections uses encrypted point-to-point strategy. |
| Threat | Mitigation |
|---|---|
| OAuth token theft from disk | Stored in Keychain / EncryptedSharedPreferences. Refresh tokens encrypted under the platform Keystore. |
| Scope creep | Tokens are scoped to gmail.metadata, gmail.readonly, calendar.readonly, calendar.events. Aura never requests gmail.modify or gmail.send. |
| User unaware of connected accounts | Settings → Connected Accounts lists every provider with the granted scopes and a one-tap revoke. Revocation calls oauth2.googleapis.com/revoke?token=... and clears the local copy. |
| Threat | Mitigation |
|---|---|
| Auto-upload of the export to cloud | Export is share-sheet only; user picks the destination. No background sync. |
| Plaintext export shared with a hostile party | Export profiles share-with-friend and share-with-clinician redact channel names, locations, balances, and HRV per technical_spec.md §5.4. The raw profile is the default for self-export only and warns the user before sharing. |
| Adversarial reads tracked but not stopped | Audit log captures every op=read with target id and agent. Daily Merkle root lets a user prove (or detect) reads at end-of-day. |
The plan names five classes (plan.md §20.1). Each is treated below with concrete mitigations and known residual risk.
Profile: another app installed by the user with the AccessibilityService permission. Such an app can read on-screen text, simulate taps, and observe view hierarchy in real time. This is the strongest hostile-app posture on Android.
Threat: read the Reasoning Trace drawer in real time, harvest signals[] and rationale, simulate a “Confirm” tap on Aura cards.
Mitigations:
FLAG_SECURE (Android) / screenCaptureProtected=true on relevant views (iOS 17+) to prevent screenshots and screen recording.getEnabledAccessibilityServiceList(); if a non-system service is enabled, show a one-time warning: “Aura works best with no third-party accessibility services.”AwaitingConfirm state.Residual risk: an a11y app can harvest summarised content if rendered. The user’s own decision to keep an a11y service running is in scope; we surface the risk and let the user decide.
Profile: another app with BIND_NOTIFICATION_LISTENER_SERVICE permission.
Threat: read Aura’s outbound proactive notifications and infer state.
Mitigations:
Residual risk: the fact that Aura emitted a notification is observable. Volume of notifications is observable. We accept this — the goal is silence, not steganography.
Profile: an attacker has obtained the user’s Apple ID or Google credentials.
Threat: log into Gmail / Calendar from another device, read messages and calendar.
Mitigations:
Residual risk: Gmail and Calendar themselves are exposed. The user’s defence is account-level (2FA, passkeys, recovery flows) and not Aura’s.
Profile: the device is stolen or misplaced. Attacker has physical possession.
Threat: extract memory.sqlite, read the graph, observe the audit log.
Mitigations:
NSFileProtectionComplete: file is unreadable when device is locked.Residual risk: an attacker with the unlock PIN or biometric (forced unlock) reads the graph. Mitigated for that case by adversary E mitigations below.
Profile: a parent, partner, or peer forces the user to unlock the device and reveal “what Aura knows”.
Threat: scroll the Memory tab; read traces; infer relationships, spending, stress.
Mitigations:
technical_spec.md §11.6). 5 rapid presses of the side / power button within 3 seconds, or a hold-and-shake gesture (configurable), triggers:
https://oauth2.googleapis.com/revoke?token=....Residual risk: a coercer who knows about Stealth and demands its toggle gets the full memory if the user discloses the Aura passcode. The product can’t defend against revealing every secret to a sufficiently determined coercer; the panic-wipe gesture remains the durable answer.
The threat model is consistent with the privacy invariants stated in plan.md §10.1, §14, and §20.3:
[TEAM TO VERIFY] itemsgetEnabledAccessibilityServiceList() returns services across user profiles on Android 14+.]plan.md §20.1.End of threat_model.md.