Files
cesnimda 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
docs: discovery blueprint + multi-provider design (#8)
2026-07-01 19:59:53 +02:00

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 /keys volume (existing). Decrypted only in-memory for the moment of an API call. Never logged, never sent to the browser.
  • 1:1 provider_tokens per account; rotation timestamped; a compromised/rotated token is replaced atomically. Token columns are bytea ciphertext, 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.