01 — Threat Model
Deliverable: threat model + attack vectors + security risks. Method: STRIDE across trust boundaries, mapped to the OWASP API Security Top 10 (2023), with attack trees for the crown-jewel assets and a ranked risk register.
1. Assets & adversaries
Assets (what we protect): ① tenant data (file bytes + metadata), ② credentials & encryption keys, ③ the audit log’s integrity, ④ availability, ⑤ the namespace’s correctness. Ranked: cross-tenant confidentiality and key compromise are catastrophic; availability and integrity are severe.
Adversaries: external attacker (unauthenticated), malicious tenant/user (authenticated, attacking other tenants), compromised credential/API key, malicious insider / rogue DBA, malicious plugin author, supply-chain attacker, anonymous public-link abuser.
2. STRIDE by trust boundary
| STRIDE | Threat (example) | Boundary | Primary control |
|---|---|---|---|
| Spoofing | stolen token / API key; forged tenant claim | edge | OAuth 2.1 + MFA (03); signed tokens; key hashing (02) |
| Tampering | mutate another’s object; alter manifest; edit audit | control/data | object-level authz (BOLA) (04); content hashing (storage/04); tamper-evident log (07) |
| Repudiation | “I didn’t share that file” | all | immutable, attributable audit (07) |
| Info disclosure | cross-tenant read; cache/log leakage; presigned-URL leak | data/edge | RLS + defense-in-depth isolation (05); encryption (10); scoped short-TTL URLs (06) |
| Denial of service | request flood; expensive ops; storage exhaustion | edge/data | layered rate limits + quotas (09) |
| Elevation of privilege | self-elevate role; BFLA on admin API; plugin sandbox escape | control | deny-by-default RBAC (04); WASM capability sandbox (product/09) |
3. Attack vectors — OWASP API Top 10 (2023) mapped to BitVault
| # | Risk | BitVault exposure | Mitigation |
|---|---|---|---|
| API1 | Broken Object Level Authorization (BOLA) — #1, ~40% of API attacks | guess a node_id/share_id from another user/tenant |
every object access checked at the PDP and RLS; never trust client IDs (04, 05) |
| API2 | Broken Authentication | credential stuffing, JWT exp not checked, token theft | OAuth 2.1, MFA, refresh rotation + reuse detection, exp/aud/iss validation (03) |
| API3 | Broken Object Property Level Authorization (excessive exposure / mass assignment) | API returns/accepts fields a role shouldn’t see/set | field-level authz; explicit allow-listed DTOs; never bind raw input to models (04) |
| API4 | Unrestricted Resource Consumption | upload floods, search/transform abuse, huge files | per-tenant/key rate limits + quotas + size caps (09) |
| API5 | Broken Function Level Authorization (BFLA) | a member calls an admin endpoint | role checks per function, deny-by-default, AppProject/scope guards (04) |
| API6 | Unrestricted Access to Sensitive Business Flows | scripted mass public-link creation, bulk download, signups | flow-level limits, CAPTCHA/step-up, anomaly detection (09) |
| API7 | SSRF | preview/transform/webhook fetches a URL → hits cloud metadata | egress allow-lists, block link-local/metadata IPs, scoped HTTP in plugins (product/09) |
| API8 | Security Misconfiguration | open bucket, permissive CORS, verbose errors | hardened defaults, IaC + GitOps review (platform/), PodSecurity, no stack traces to clients |
| API9 | Improper Inventory Management | forgotten API versions/endpoints/debug routes | versioned API + OpenAPI inventory (ADR-0015); kill old versions |
| API10 | Unsafe Consumption of APIs | trusting an external IdP/KMS/webhook response blindly | validate external responses; signed webhooks (08 events) |
4. Cross-tenant attack vectors (the highest-severity class)
These deserve special call-out because authN/authZ do not prevent them:
- Forged
tenant_idin a token/request → tenant context must derive from the verified token and be re-checked on every authz decision, not just login. - Cache-key collision (
prefs:{user_id}identical across tenants) → tenant-prefix all cache keys. - Connection-pool contamination — a global/poorly-scoped
tenant_idwritten during anawait→ identity-swap under concurrency → request-scoped context + PgBouncer session pooling with mandatoryserver_reset_query. - SQLi overriding
tenant_id→ parameterized queries + RLS as backstop. - Sensitive values in URLs/GET → leak into logs/referer (CWE-532) → only in body/headers, never the query string.
- Side-channels (dedup existence, timing) → per-tenant dedup (ADR-0018).
5. Attack tree — “Read another tenant’s file” (the nightmare)
flowchart TB
classDef g fill:#fecaca,stroke:#b91c1c,color:#111827;
classDef a fill:#fde68a,stroke:#b45309,color:#111827;
classDef m fill:#bbf7d0,stroke:#15803d,color:#111827;
G["GOAL: read tenant B's file as tenant A"]:::g
G --> A1["forge/alter tenant_id claim"]:::a --> M1["signed tokens + verify on every decision ([05])"]:::m
G --> A2["BOLA: access B's node_id directly"]:::a --> M2["PDP object-authz + RLS ([04],[05])"]:::m
G --> A3["cache-key collision read"]:::a --> M3["tenant-prefixed cache keys ([05])"]:::m
G --> A4["conn-pool identity swap"]:::a --> M4["request-scoped ctx + server_reset_query ([05])"]:::m
G --> A5["search index cross-tenant hit"]:::a --> M5["tenant-scoped index + filter ([ADR-0009])"]:::m
G --> A6["leaked/over-broad presigned URL"]:::a --> M6["scoped, short-TTL, exact-key URLs ([06])"]:::m
G --> A7["read B's backup / object directly"]:::a --> M7["per-tenant keys (crypto-isolation) ([10])"]:::m
Every branch is independently mitigated — defense in depth, because any single control will eventually have a bug.
6. Attack tree — “Account / tenant takeover”
flowchart TB
classDef g fill:#fecaca,stroke:#b91c1c,color:#111827;
classDef a fill:#fde68a,stroke:#b45309,color:#111827;
classDef m fill:#bbf7d0,stroke:#15803d,color:#111827;
G["GOAL: take over an account / org admin"]:::g
G --> A1["credential stuffing / brute force"]:::a --> M1["MFA + lockout + breach-pw check ([03],[09])"]:::m
G --> A2["steal access/refresh token"]:::a --> M2["short TTL + rotation + reuse-detect + DPoP ([03])"]:::m
G --> A3["leaked API key (git/logs)"]:::a --> M3["hashed, scoped, rotatable + secret scanning ([02],[08])"]:::m
G --> A4["session fixation / XSS"]:::a --> M4["secure cookies + CSP + httpOnly + SameSite ([03])"]:::m
G --> A5["self-elevate role"]:::a --> M5["deny-by-default authz on role change ([04])"]:::m
G --> A6["phishing OAuth consent"]:::a --> M6["exact redirect-URI match + PKCE ([03])"]:::m
7. Risk register (ranked)
| Risk | Likelihood | Impact | Severity | Key mitigation | Residual |
|---|---|---|---|---|---|
| Cross-tenant data leak (BOLA/isolation) | Med | Critical | 🔴 Critical | PDP + RLS + cache/key/conn isolation (05) | low (defense-in-depth + tests) |
| Encryption-key compromise | Low | Critical | 🔴 Critical | KMS, per-tenant keys, no export, rotation (10) | low |
| Account/API-key takeover | Med | High | 🟠 High | MFA, token rotation, key hashing (03) | medium (human factor) |
| Public-link abuse / data exfiltration | Med | High | 🟠 High | scoped capability tokens, expiry, AV/abuse (06) | medium |
| DoS / resource exhaustion | High | Med | 🟠 High | layered rate limits + quotas (09) | low-med |
| Audit tampering / repudiation | Low | High | 🟡 Med | tamper-evident, separate-domain log (07) | low |
| SSRF via previews/plugins | Med | Med | 🟡 Med | egress allow-list, metadata block (06) | low |
| Plugin sandbox escape | Low | High | 🟡 Med | WASM capability sandbox + limits (product/09) | low |
| Supply-chain compromise | Low | Critical | 🟡 Med | signing, SBOM, SLSA, admission verify (ADR-0032) | low |
| Insider / rogue DBA | Low | Critical | 🟡 Med | per-tenant encryption, least privilege, audit (10) | medium |
8. How we keep the model honest
- Continuous tests for the top risks: the cross-tenant access test (forged
tenant_idblocked by RLS, 05), BOLA fuzzing, token-reuse detection, rate-limit tests. - Pen testing + bug bounty (12 roadmap).
- Threat model is living: revisited on every new trust boundary (new principal, new external integration, new plugin capability).
References
- OWASP API Top 10 (2023): https://owasp.org/API-Security/editions/2023/en/0x11-t10/
- STRIDE: https://learn.microsoft.com/azure/security/develop/threat-modeling-tool-threats
- OWASP Multi-Tenant Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Multi_Tenant_Security_Cheat_Sheet.html