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:
- Short TTL (minutes), exact key, single method, content-length-range — minimize what a leaked URL grants and for how long.
- Never log presigned URLs or put them in query-string-logged paths (CWE-532); deliver via redirect/response body.
- Tenant-scoped issuance only after a PDP check (04).
3. Serving user content safely (stored XSS / sniffing)
User-uploaded files served on your domain are a stored-XSS and content-sniffing vector:
- Serve downloads with
Content-Disposition: attachmentandX-Content-Type-Options: nosniff. - Serve previewable/inline content from a separate, sandboxed origin (cookieless domain) with a strict CSP — so a malicious HTML/SVG file can’t run script in the app origin or read app cookies.
- Strip active content from previews; render via the transform pipeline (product/04), not the browser on the main origin.
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:
- Egress allow-list; block link-local/metadata (
169.254.169.254,::1, RFC1918 unless explicitly allowed); DNS-rebinding protection (re-resolve + pin). - Plugins get only a scoped, allow-listed HTTP host function (product/09), never raw network.
- Webhooks validate target URLs and never follow redirects to internal ranges.
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
- OWASP API7 SSRF: https://owasp.org/API-Security/editions/2023/en/0xa7-server-side-request-forgery/
- OWASP File Upload Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html
- Serving untrusted content / CSP: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html