Stored XSS via a scanned document

Dev environment on vuln.patholux.magyar.studio. The payload is real; the seeded patient and user data are fake.

1. The pathologist opens the incoming scan

The file was imported with Content-Type: video/mp4, text/html. The preview cannot handle that type, so it falls back to an “open in new tab” link.

Document review page with an open file fallback

2. The link renders as HTML and reads the session

The file URL is served from the app origin. Chrome takes the last type in the comma list, renders the body as HTML, and the script reads /api/auth/get-session.

XSS page showing the stolen session email

3. The stored value

$ curl -sS -b attacker.cookies \
    -H 'content-type: application/json' \
    -d '{"0":{"filetype":"external-document","fileUrl":"https://vuln.patholux.magyar.studio/xss-payload"}}' \
    'https://vuln.patholux.magyar.studio/api/v1/trpc/files.importFromUrl?batch=1'

[{"result":{"data":{"fileId":"file_01M6DX71ZWRASANVRJQY6XB1V7"}}}]

4. The fixed response

HTTP/2 200
content-disposition: attachment; filename="Ueberweisung_Scan"; filename*=UTF-8''Ueberweisung_Scan
content-type: application/octet-stream
x-content-type-options: nosniff

The external-document row is normally created by the scanner/OCR integration. It was inserted here to show the review-screen click. The file import and the file response are the real API and server behavior.