Sanitized finding from Client D. The original upload endpoint, payload and identities are omitted.
Context
The application allowed authenticated users to upload files used in a document and analysis workflow. The browser later displayed uploaded content in a trusted application origin.
Finding
The validation layer relied on filename and extension checks that could be bypassed. An SVG carrying active markup was accepted and stored. When another user opened the resulting resource, the browser interpreted the content in the application context.
Technical workflow
The upload path was tested with a benign SVG fixture and content-type variations. The original active payload is intentionally omitted; the point of the retest is to prove the server-side policy, not to publish a copy-paste payload:
# Authorized test account and inert fixture only
curl --fail-with-body --max-time 10 \
-H 'Authorization: Bearer TEST_TOKEN' \
-F 'file=@fixtures/benign.svg;type=image/svg+xml' \
'https://AUTHORIZED_HOST/api/upload'
A safe validation policy rejects active formats unless a dedicated sanitizer and origin are used:
INERT_MIME = {"image/png", "image/jpeg", "application/pdf"}
def accept_upload(*, detected_mime: str, extension: str) -> bool:
if detected_mime not in INERT_MIME:
return False
return extension.lower() in {".png", ".jpg", ".jpeg", ".pdf"}
The server must derive detected_mime from the file bytes, normalize the filename, store outside the application origin and return Content-Disposition: attachment where inline rendering is not required. CSP is a backstop, not a substitute for rejecting active content.
Impact
The stored execution could target users with access to the same workspace, including privileged roles. Depending on browser protections and session design, the impact included unauthorized actions, data access and workflow manipulation.
Remediation
- Reject active formats such as SVG and HTML unless they are fully sanitized and served from an isolated origin.
- Validate content server-side using magic bytes and an explicit allowlist of inert formats.
- Store uploads outside the application origin and serve them with a forced download disposition where possible.
- Add a strict CSP and regression tests for polyglot, renamed and content-type-confused files.
Validation
Re-test renamed active files, mismatched MIME types and SVG variants. Uploaded content must remain inert and isolated for every user role.
Expected result: rejected upload or inert download from an isolated origin, with no script execution in the application origin and no access to another user’s session context.