4ce2df0a2b
CI / backend (push) Successful in 52s
CI / frontend (push) Successful in 14s
Deploy Staging / deploy (push) Successful in 18s
CI / backend (pull_request) Successful in 52s
CI / frontend (pull_request) Successful in 15s
Security / secrets (push) Successful in 4s
Security / dependencies (push) Successful in 55s
Security / secrets (pull_request) Successful in 4s
Security / dependencies (pull_request) Successful in 54s
4.5 KiB
4.5 KiB
06 — Security Model (Part 5)
Builds on the existing hardening (read-only scope, encrypted tokens, IDOR global query filters, SSRF egress guard, non-root containers, confirmed destructive actions) and adds what multi-user + admin + multi-provider require.
RBAC
- Roles: Admin · Member (small-team, one org). First user bootstraps as Admin.
- Enforced by policy-based authorization at the API (ASP.NET Core policies), not in the UI.
| Capability | Member | Admin |
|---|---|---|
| Read/manage own mail & accounts | ✅ | ✅ |
| Own user settings | ✅ | ✅ |
| Link/unlink own provider accounts | ✅ | ✅ |
| View/manage other users | ❌ | ✅ |
| Toggle feature flags (incl. AI global) | ❌ | ✅ |
| Enable/disable providers | ❌ | ✅ |
| Maintenance mode, system settings | ❌ | ✅ |
| View audit log & monitoring | ❌ | ✅ |
- No cross-user data access, ever — Admin manages accounts/flags/system, not other users' email contents (privacy). Admin power is over the platform, not people's inboxes.
OAuth token storage
- Refresh/access tokens encrypted at rest with the Data Protection API (AES); keys persist
to the mounted
/keysvolume (existing). Decrypted only in-memory for the moment of an API call. Never logged, never sent to the browser. - 1:1
provider_tokensper account; rotation timestamped; a compromised/rotated token is replaced atomically. Token columns arebyteaciphertext, not readable in DB dumps.
Session handling
- Opaque server-side sessions (DB-backed) + HttpOnly/Secure/SameSite cookie; id rotated on login (anti-fixation); idle + absolute expiry; server-side revocation (logout, sign-out-everywhere, admin revoke, role change). CSRF via SameSite + token.
Admin access protection
- Admin routes require the Admin policy; sensitive mutations (toggle AI global, disable a provider, suspend a user, enter maintenance) require a confirmation / step-up and are rate-limited.
- Every admin action is audit-logged (
audit_logs: actor, action, target, metadata, ip, time) — append-only. - First-admin bootstrap is one-time; afterwards admin is grant-only by an existing Admin (logged). Guard against privilege escalation: role changes are Admin-only + audited + force session refresh.
API security boundaries
- Per-user isolation via EF global query filters (extended to
account_id/user_id) so a query can never return another user's rows — the IDOR safeguard, now multi-account. - Input validation (FluentValidation) on all DTOs; mass-assignment safe (explicit DTOs, no entity binding).
- Rate limiting on auth, admin, search, and AI endpoints.
- SSRF egress guard (existing) constrains all outbound calls — provider APIs, IMAP hosts, Ollama, and any opt-in cloud AI — to an allowlist; user-supplied IMAP hosts are validated.
- Security headers (CSP, HSTS, X-Frame-Options, etc.) via the reverse proxy/API; strict CORS.
Multi-provider & AI specifics
- Least-privilege scopes per provider; extra scopes added per-feature with consent.
- Provider isolation: disabling a provider flag revokes its use cleanly; per-account tokens are independent (one reauth doesn't affect others).
- Prompt injection: email content is untrusted → LLM output is advisory only, never triggers actions; a human/rule confirms. AI runs local by default; cloud AI is explicit opt-in with per-feature consent + egress logging.
- Attachments/vision: sandboxed parsing, size/type limits, never executed.
Threat model (summary)
| Threat | Mitigation |
|---|---|
| Account hijack via linking | Must authenticate as target user; unique (provider, sub); linking an owned identity blocked |
| Token theft / DB exposure | Encryption at rest; tokens never in logs/browser; rotation |
| Privilege escalation | Admin-only role changes, audited, session refresh; policy checks server-side |
| IDOR / cross-user leakage | Global query filters on user_id/account_id |
| CSRF / session fixation | SameSite + token; session id rotation; server-side revoke |
| SSRF (providers/IMAP/AI) | Egress allowlist guard; validate user-supplied hosts |
| Prompt injection | AI advisory-only; never acts; local-first |
| Mass admin abuse | Rate limit + step-up + full audit trail |
Non-negotiables
Admins manage the platform, not users' inboxes · tokens encrypted & browser-invisible · every privileged action audited · AI never required and never acts autonomously.