06 — Public Sharing & API Security

The two most-exposed surfaces: public file sharing (anonymous capability access) and public APIs (the OWASP attack surface). Decision: ADR-0037. Closes OWASP API6 (sensitive flows), API7 (SSRF), API8 (misconfig), and the abuse surface.


1. Public sharing = handing out a capability

A public share link or presigned URL is a bearer capability: whoever holds it can act within its scope, with no account. So the capability itself must be tightly bounded.

flowchart TB
    classDef e fill:#fde68a,stroke:#b45309,color:#111827;
    classDef a fill:#bbf7d0,stroke:#15803d,color:#111827;
    classDef d fill:#c7d2fe,stroke:#3730a3,color:#111827;
    owner["owner creates share"]:::e --> tok["token: ≥128-bit random, unguessable"]:::a
    tok --> scope["scoped to ONE node + permission (view/download)"]:::a
    tok --> opts["optional: password (hashed, rate-limited) · expiry · max-downloads · revocation"]:::a
    visitor["anonymous visitor"]:::d -->|presents token| pdp["PDP: anonymous principal authorized for EXACTLY this resource ([04])"]:::a
    pdp --> serve["safe serving (§3) / scoped presigned GET (§4)"]:::a
Control Why
Unguessable token (≥128-bit CSPRNG) defeats enumeration ([API6])
Scoped to one node + permission the anonymous principal gets only the shared resource — never the tenant
Optional password (hashed, rate-limited) brute-force resistance
Expiry + max-downloads + revocation bound the capability’s lifetime/blast radius
Watermarking / view-only deter exfiltration of sensitive shares

2. Presigned-URL risks (the data-plane capability)

Presigned URLs (ADR-0011) are bearer tokens to the object store that cannot be revoked once issued, so:


3. Serving user content safely (stored XSS / sniffing)

User-uploaded files served on your domain are a stored-XSS and content-sniffing vector:


4. SSRF (API7) — previews, transforms, webhooks

Any feature that fetches a URL (link previews, import-from-URL, webhooks, plugins) can be coerced to hit internal/cloud-metadata endpoints:


5. Public API hardening (the OWASP surface)

Risk Control
API8 misconfig hardened defaults, strict CORS (no * with credentials), no verbose errors/stack traces, IaC-reviewed config (platform/)
API9 inventory versioned API + generated OpenAPI inventory (ADR-0015); retire old/debug routes
API4/6 abuse per-key/tenant rate limits + flow limits (09)
Input schema validation, output encoding, size/type limits

6. Abuse prevention (public storage is a magnet)

Abuse Defense
Malware hosting AV/malware scan on upload (Function/plugin, product/06); quarantine
Phishing pages link reputation, sandboxed serving (§3), takedown workflow
CSAM perceptual-hash matching + mandatory reporting workflow (legal obligation)
Bandwidth/storage abuse per-tenant quotas + rate limits (09); CDN with limits
Public-link spam / enumeration unguessable tokens, rate-limited creation, anomaly detection

7. Threats addressed & residual

Threat Control Residual
Public-link enumeration/guessing ≥128-bit tokens + rate limit very low
Leaked presigned URL short TTL + exact scope low (TTL window)
Stored XSS via served files sandboxed origin + CSP + nosniff + attachment low
SSRF to cloud metadata egress allow-list + metadata block low
Malware/CSAM hosting scanning + reporting medium (detection limits) — needs ongoing investment

Honest residual: content-abuse detection (malware/CSAM/phishing) is never perfect; it requires sustained investment, reporting workflows, and legal process — budget for it as an operational program, not a one-time control.

References