SA-010 Avatar validation
This commit is contained in:
+9
-5
@@ -151,13 +151,17 @@ These findings are prioritized below. Severity describes the potential security
|
||||
|
||||
### SA-010: Avatar validation trusts the client MIME type
|
||||
|
||||
**Severity:** Medium
|
||||
**Evidence:** `upload_avatar()` in `backend/app/api/user_config.py` selects the extension from `UploadFile.content_type` and writes the bytes without decoding or inspecting the image.
|
||||
**Severity:** Medium, remediated in current worktree
|
||||
**Evidence before remediation:** `upload_avatar()` in `backend/app/api/user_config.py` selected the extension from `UploadFile.content_type` and wrote the bytes without decoding or inspecting the image.
|
||||
**Impact:** A user can upload arbitrary content while labeling it as an image. Public serving may cause unexpected content handling, bandwidth consumption, or browser-side exposure. The current random user-ID filename reduces path traversal risk, but it does not establish that the content is a safe image.
|
||||
|
||||
**Recommendation:** Decode images with a hardened image library, enforce pixel and dimension limits, re-encode to a safe format, strip metadata, and serve with a fixed safe `Content-Type` and `X-Content-Type-Options: nosniff`. Consider a separate media origin and a stricter content security policy.
|
||||
**Current state:** Avatar bytes are limited to 2 MB, decoded and verified with Pillow, checked against a 25-megapixel limit, fully loaded, converted to RGBA, and re-encoded as server-generated PNG. The client MIME type is used only as an initial allow-list check; invalid image content is rejected. Static serving uses the generated `.png` extension and therefore returns `image/png`.
|
||||
|
||||
**Priority:** Medium.
|
||||
**Residual impact:** Add `X-Content-Type-Options: nosniff` at the application or reverse-proxy layer and consider a separate media origin for stronger isolation.
|
||||
|
||||
**Recommendation:** Keep Pillow current, monitor decompression-bomb and upload failures, and preserve fixed image content types and dimensions. Add a stricter media-origin policy if avatars become a higher-risk feature.
|
||||
|
||||
**Priority:** Completed in code; response-header and media-isolation hardening remain.
|
||||
|
||||
### SA-011: Error details can disclose infrastructure information
|
||||
|
||||
@@ -250,7 +254,7 @@ Before production exposure:
|
||||
- [x] Disable direct host publication of the application port in production.
|
||||
- [ ] Configure HTTPS, HSTS, CSP, Referrer-Policy, frame protections, `nosniff`, and trusted hosts.
|
||||
- [ ] Define a restrictive CORS policy or leave CORS disabled.
|
||||
- [ ] Add global request-size limits and hardened image decoding/re-encoding.
|
||||
- [x] Add global request-size limits and hardened image decoding/re-encoding.
|
||||
- [x] Add OTP recovery codes and a protected recovery workflow.
|
||||
- [ ] Remove or implement refresh-token behavior.
|
||||
- [ ] Add security audit events and centralized redacted logging.
|
||||
|
||||
Reference in New Issue
Block a user