Follow-up from #1297 (not a merge blocker).
Evidence
src/screens/chat.screen.tsx:44 (isAcceptedAttachment): if file.type is present but not in ACCEPTED_MIME_TYPES, the function still returns true when the name ends with .pdf / .jpeg / .jpg / .png.
A file named payload.png with type: image/svg+xml or text/html is therefore accepted. isImageFile (line 51) then treats any image/* MIME as a preview candidate.
The composer preview sink itself is still only a blob: object URL (asBlobPreviewUrl at line 60), so this is a type-policy gap, not an HTML injection path.
Suggested fix
Fall back to the extension only when file.type is empty. If a MIME type is present, it must be in the allow-list. Restrict isImageFile to image/jpeg, image/jpg, and image/png.
Follow-up from #1297 (not a merge blocker).
Evidence
src/screens/chat.screen.tsx:44(isAcceptedAttachment): iffile.typeis present but not inACCEPTED_MIME_TYPES, the function still returns true when the name ends with.pdf/.jpeg/.jpg/.png.A file named
payload.pngwithtype: image/svg+xmlortext/htmlis therefore accepted.isImageFile(line 51) then treats anyimage/*MIME as a preview candidate.The composer preview sink itself is still only a
blob:object URL (asBlobPreviewUrlat line 60), so this is a type-policy gap, not an HTML injection path.Suggested fix
Fall back to the extension only when
file.typeis empty. If a MIME type is present, it must be in the allow-list. RestrictisImageFiletoimage/jpeg,image/jpg, andimage/png.