ADR-0037 — Public sharing security model
- Status: Accepted
- Date: 2026-06-11 · Revised: 2026-06-12 (Architecture Freeze V1)
- Related: security/06 public sharing, ADR-0008, ADR-0011
V1 Freeze (2026-06-12): Accepted, scoped. Blocker-5 follow-up: the bearer token is stored only as a hash (
SHARE.link_token_hash), matching how API tokens are handled — a DB/backup leak no longer hands out live links. The scoped-capability core (unguessable token, one node + permission, password, expiry, max-downloads, revocation) is V1. The heavier abuse program (sandboxed-origin serving, SSRF defenses, malware/CSAM scanning, link reputation) is Deferred to P3+ — noted below.
Context
Public file sharing and public APIs are BitVault’s most-exposed surface and a magnet for abuse (enumeration, exfiltration, malware/phishing/CSAM hosting, SSRF via previews). A share link or presigned URL is a bearer capability — whoever holds it can act within its scope, with no account — so the capability must be tightly bounded and the served content handled as hostile.
Decision
- Share links are scoped capabilities: a ≥128-bit unguessable token, presented
by the holder but stored only as a hash (
link_token_hash; looked up by hash, never stored in plaintext — consistent withapi_tokens, data model 08); scoped to one node + permission; optional password (hashed, rate-limited), expiry, max-downloads, instant revocation; optional watermark/view-only. The anonymous principal is authorized by the PDP for exactly that resource — never the tenant (ADR-0010). - Presigned URLs (data plane, ADR-0011):
short TTL, exact key, single method,
content-length-range; never logged/in query strings; revocation impossible → keep short. - Serve user content safely (Deferred to P3+):
Content-Disposition: attachment,nosniff, and a separate sandboxed origin + strict CSP for inline/preview so a malicious HTML/SVG can’t run in the app origin (stored-XSS defense). (V1 serves downloads as attachments withnosniff; inline preview and the sandboxed origin land with previews in P5.) - SSRF defense (Deferred to P3+, with previews/plugins): egress allow-lists, block link-local/cloud-metadata, DNS-rebinding protection; plugins get only scoped HTTP.
- Abuse program (Deferred to P3+): malware/CSAM scanning + reporting workflow, link reputation, per-tenant quotas/rate limits (security/09).
Consequences
Positive
- Public sharing’s blast radius is bounded per-link; enumeration and exfiltration are hard; stored-XSS and SSRF classes are closed by construction.
Negative / costs
- Sandboxed-origin serving adds infra (a second domain, CSP tuning).
- Presigned URLs can’t be revoked once issued → short TTL is the only lever (accepted).
- Content-abuse detection is imperfect and an ongoing operational/legal program, not a one-time control.
Alternatives considered
- Sequential/guessable share IDs: enables enumeration. Rejected (CSPRNG tokens).
- Serve user files from the app origin: stored-XSS / cookie theft. Rejected (sandbox origin).
- Long-lived presigned URLs for convenience: large leaked-URL blast radius. Rejected (short TTL).
Scaling
Token checks are O(1); abuse scanning runs as event-driven Functions (product/06); CDN + per-tenant limits absorb public read load.