Daniel Cohen·
Threat-modeled a file-upload feature from its spec before a line was written. The prompt found an SSRF path through the thumbnail service that our review checklist missed.
Runs a STRIDE threat model against a feature spec before implementation, with concrete abuse scenarios and mitigations.
Spec-Stage Threat Model (STRIDE)
You are an application security engineer running a design-review threat model. I will give you a feature specification BEFORE implementation. Your job is to find the ways this design gets abused, so we fix them in the spec instead of in an incident.
Feature spec:
{{feature_spec}}
System context (stack, auth model, trust boundaries, third-party services):
{{system_context}}
Process:
1. **Asset & entry-point inventory.** List what an attacker would want here (data, compute, trust) and every entry point the feature adds: endpoints, file parsers, webhooks, background jobs, third-party callbacks.
2. **Data-flow narrative.** Describe the happy-path data flow in numbered steps, marking each trust-boundary crossing with ⇄. Threats live at the crossings.
3. **STRIDE pass.** For each entry point, walk Spoofing, Tampering, Repudiation, Information disclosure, Denial of service, Elevation of privilege. Only report findings that are plausible in THIS design — no generic boilerplate. For each finding: a concrete abuse scenario written as an attacker story ("I upload a file that..."), severity (Critical/High/Medium/Low) with a one-line justification, and a specific mitigation at the design level.
4. **The nasty three.** Pick your three highest-confidence findings and expand each: preconditions, step-by-step exploitation, blast radius, and the exact spec change that kills it.
5. **Requirements block.** Output a copy-pasteable "Security Requirements" section for the spec: numbered, testable statements ("the thumbnail service MUST NOT follow redirects", "uploaded files MUST be served from a separate origin").
If the spec is missing information you need (auth between internal services, storage location, size limits), list those questions FIRST and state the assumptions you proceeded with.
Ergebnisse
## Threat Model: User Avatar & Document Upload
### Open Questions (assumptions in brackets)
1. Does the thumbnail service fetch by URL or receive bytes? [Assumed: fetches by URL — the spec says "thumbnailer pulls the source"]
2. Auth between API and thumbnailer? [Assumed: none, internal network trust]
3. Max file size? [Assumed: unspecified = unlimited]
### Asset & Entry-Point Inventory
Assets: user PII in documents, S3 credentials, internal network reachability, compute (image processing).
New entry points: `POST /uploads`, the image parsing pipeline, the thumbnailer's HTTP fetch, the signed-URL download endpoint.
### Data Flow
1. Client → ⇄ API: multipart upload
2. API → S3: store original
3. API → ⇄ thumbnailer: passes source URL
4. Thumbnailer → ⇄ fetches URL, parses image, writes thumbnail
5. Client ⇄ downloads via signed URL
### The Nasty Three
**1. SSRF via thumbnailer fetch — Critical.**
Attacker story: I upload an "avatar" whose stored source URL I can influence (spec allows re-pointing via the `sourceUrl` PATCH). The thumbnailer, sitting inside the VPC with no egress policy, happily fetches `http://169.254.169.254/latest/meta-data/` or internal admin services.
Preconditions: URL-based fetch (assumed, confirm!). Blast radius: cloud credentials, internal service enumeration.
**Spec change:** thumbnailer receives bytes or an S3 object key — never a URL. If URL fetch must exist: allowlist the S3 origin only, no redirects, no private IP ranges, 5s timeout.
**2. Decompression/parse bomb — High.**
Attacker story: I upload a 200KB image that decompresses to 8GB (pixel flood). No size/dimension limits assumed → thumbnailer OOMs; repeated uploads = cheap DoS of the whole pipeline.
**Spec change:** enforce max file size (10MB), max dimensions (e.g. 8k×8k) checked from headers before full decode, process in a memory-capped worker.
**3. Stored-file content-type confusion — High.**
Attacker story: I upload an HTML file named `report.pdf`. The download endpoint serves it from the app origin with a sniffable content type → stored XSS with app-origin cookies.
**Spec change:** serve all user files from a separate origin/subdomain, force `Content-Disposition: attachment`, set `X-Content-Type-Options: nosniff`, and re-write content type from server-side detection, never from the client.
### Security Requirements (paste into spec)
1. The thumbnail service MUST receive object keys, not URLs.
2. Uploads MUST be rejected over 10MB before body buffering completes.
3. User files MUST be served from `files.<domain>` with attachment disposition and nosniff.
4. Image decoding MUST run with memory and CPU limits; a decode failure MUST NOT retry more than once.
5. Signed download URLs MUST expire within 15 minutes and be single-audience.
Modell: Claude Opus 4.6
45 Likes27 SavesScore: 35
2 Kommentare
Emily Chen·
The assume-then-confirm pattern for missing spec details is exactly right. Refusing to proceed helps nobody, silently assuming helps attackers.
Luca Brunner·
Requirement 1 alone would have prevented an incident I once spent a weekend on. Bytes, not URLs.
