Daniel Cohen·
Threat-modeled a new file-upload feature before writing any code — STRIDE table, abuse cases, and the S3 policy we almost got wrong
Threat-models a feature from its spec before implementation: STRIDE analysis per component, realistic abuse cases, and concrete mitigations mapped to the design.
Pre-Implementation Threat Model (STRIDE + Abuse Cases)
You are a security engineer threat-modeling a feature BEFORE implementation — the cheapest moment to fix design flaws. Work from the spec, not from imagined code.
Feature spec:
{{feature_spec}}
Architecture context (services involved, trust boundaries, auth model):
{{architecture}}
Data sensitivity (what data flows through this, worst-case if leaked): {{data_sensitivity}}
Produce:
1. **Data flow sketch in text** — numbered hops from user action to storage and back, marking every trust boundary crossing with [TB]. If the spec is ambiguous about a hop, state your assumption explicitly — wrong assumptions are findings too.
2. **STRIDE per boundary crossing** — for each [TB], walk Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege. Skip categories that genuinely don't apply, but say "n/a because..." rather than silently omitting. Generic threats ("an attacker could intercept traffic") are banned unless the spec shows a reason TLS wouldn't apply.
3. **Top 5 abuse cases** — written as short attacker stories with a concrete goal ("upload a polyglot file that executes when an admin previews it"), ranked by likelihood × impact for THIS feature, not a generic top-10 list.
4. **Mitigations table** — each abuse case → specific design-level mitigation → where it lives (which service/config) → residual risk after mitigation. Prefer mitigations that remove the vulnerability class (presigned URLs with content-type enforcement) over detective controls (scanning after the fact) — but include the detective layer where removal is impossible.
5. **The decision list** — design choices the team must make BEFORE coding starts, each phrased as a question with your recommended answer and its cost.
End with what this model does NOT cover, so nobody mistakes it for a pentest.
Ergebnisse
## Data flow — profile document upload
1. User selects file in browser → 2. Client requests upload authorization from API [TB1: browser→API] → 3. API validates user + quota, returns presigned S3 URL → 4. Client PUTs file directly to S3 [TB2: browser→S3] → 5. S3 event triggers processing lambda [TB3: storage→compute] → 6. Lambda scans, generates thumbnail, writes metadata to DB → 7. Other users fetch document via API-mediated download [TB4: API→S3→user].
Assumption stated: spec doesn't say whether downloads are proxied or redirect to S3. I assume presigned GET redirect. **This is decision #1 below — it changes TB4's whole threat picture.**
## STRIDE highlights per boundary
**TB1 (browser→API):** Spoofing — covered by session auth. Tampering — client-declared content type must be treated as hostile; enforce in presign conditions, not just request validation. DoS — authorization endpoint needs per-user rate limit; presign requests are cheap for us to issue but each enables a 100MB upload. EoP — n/a because presign scope is single-key.
**TB2 (browser→S3):** Tampering — presigned PUT must pin content-length range and content-type, else the "one 5MB PDF" authorization uploads a 5GB video. Information disclosure — bucket must block public ACLs at account level; presign must not be reusable (short expiry, single-use semantics via key uniqueness).
**TB3 (S3→lambda):** EoP — the processing lambda parses hostile files with image/PDF libraries; it must run with minimal IAM (read the one key, write thumbnail prefix, nothing else) because parser RCE is the realistic entry point. DoS — decompression bombs; cap pixel dimensions and processing time.
**TB4 (download):** Information disclosure — THE finding: spec says documents are "visible to team members", but a presigned GET, once issued, works for anyone holding the URL. Authorization happens at issuance, not at access.
## Top abuse cases
1. **Stored malware distribution** — attacker uploads malware; platform serves it to teammates from a trusted domain. (High/High)
2. **Presigned URL leakage** — team member shares a presigned GET in Slack; it outlives their team membership. (High/Med)
3. **Parser exploitation** — crafted PDF exploits the thumbnail lambda for AWS credential theft. (Med/High)
4. **Quota bypass via presign hoarding** — request many presigns, upload later, exceed storage quota. (Med/Low)
5. **Polyglot content-type confusion** — file that is both valid image and valid HTML, served inline → stored XSS. (Med/High)
## Mitigations
| Abuse | Mitigation | Lives in | Residual |
|---|---|---|---|
| 1 | Scan in TB3 before metadata write; unscanned files undownloadable | lambda + DB state flag | zero-day signatures |
| 2 | 60s GET expiry + always re-authorize at API before issuing | API | 60s window |
| 3 | Minimal IAM role + sandboxed parser + no env credentials | lambda config | parser 0-days, contained |
| 4 | Count quota at presign issuance, reconcile on S3 event | API + lambda | brief over-count |
| 5 | Force `Content-Disposition: attachment` + serve from separate domain | S3 metadata via presign conditions | none meaningful |
## Decisions before coding
1. **Proxy downloads or presigned redirect?** Recommend: presigned redirect with 60s expiry (cost: URL-sharing window) — proxying costs API bandwidth forever.
2. **Separate download domain?** Recommend: yes, `files.{domain}` with no cookies (cost: one cert + DNS) — kills cookie-scoped XSS class outright.
3. **Sync or async scanning?** Recommend: async with pending state (cost: download delay ≈ seconds) — sync couples upload latency to scanner health.
## Not covered
Runtime dependencies' CVEs, S3 account-level config drift, insider access, and anything about the existing auth system this feature inherits. This is a design review, not a pentest.
Modell: Claude Opus 4.6
43 Likes25 SavesScore: 30
2 Kommentare
Ahmed Hassan·
Authorization at issuance vs at access — that presigned URL distinction is the most common S3 design mistake I see in reviews.
Jonas Weber·
The decision list with costs attached is what makes this usable in an actual planning meeting instead of a security lecture.
