[PM-34032] feat: secure inline image attachment previews with privacy mask#6711
[PM-34032] feat: secure inline image attachment previews with privacy mask#6711yuuouu wants to merge 2 commits intobitwarden:mainfrom
Conversation
- Introduce inline image thumbnails in VaultItemScreen with a privacy MaskedOverlay. - Implement strict burn-after-reading: decrypted temporary files are deleted immediately after being rendered into Glide's memory. - Enforce `DiskCacheStrategy.NONE` across all Glide requests to prevent plaintext image leaks in third-party caches. - Scope VaultMediaViewerViewModel to NavGraph for state sharing, but tie temporary file purging strictly to `Lifecycle.Event.ON_DESTROY` of VaultItemScreen to prevent cross-session state leakage. - Refactor MediaViewerScreen (fullscreen) to perform an independent secondary decryption, decoupling completely from thumbnail file paths. - Add `isAutoLoadAttachmentsEnabled` and `isAutoUnmaskAllEnabled` flags to pave the way for future user-configurable settings.
|
Thank you for your contribution! We've added this to our internal tracking system for review. Details on our contribution process can be found here: https://contributing.bitwarden.com/contributing/pull-requests/community-pr-process. |
|
Hi @david-livefront , Just checking in on this PR. I understand that since this involves core privacy mechanisms (memory-only caching & lifecycle-bound purging constraints), it might need deeper security and QA reviews. Please let me know if there’s anything I can clarify or any testing scenarios I can assist with whenever it makes it to your sprint backlog! |
|
@yuuouu As far as I see, this was added to the BW Android app with the latest release 2026.4.0: https://bitwarden.com/help/attachments/#view-an-attachment PS: I'm just another user, not a Bitwarden employee. |
📝 Summary
DiskCacheStrategy.NONEacross all Glide requests to prevent plaintext image leaks in third-party caches.Lifecycle.Event.ON_DESTROYof VaultItemScreen to prevent cross-session state leakage.isAutoLoadAttachmentsEnabledandisAutoUnmaskAllEnabledflags to pave the way for future user-configurable settings.🎟️ Tracking
PM-29871: bug: Add more accessibility callouts for external links
📔 Objective
This PR significantly enhances the UX of viewing image attachments by introducing inline thumbnails with a privacy mask, while strictly adhering to Bitwarden's zero-knowledge and zero-trace security standards.
Previously, viewing an attachment required navigating to a completely separate screen. This update allows users to preview images directly within the
VaultItemScreen, utilizing a highly secure "burn-after-reading" strategy paired with memory-only caching.Changes Included
MaskedOverlayinline. Tapping the mask decrypts and loads the thumbnail seamlessly.DiskCacheStrategy.NONEon all Glide requests to guarantee plaintext binaries never linger in the Android file system.media_previewscache and sharedVaultMediaViewerViewModelstates are completely wiped uponLifecycle.Event.ON_DESTROYof theVaultItemScreenor upon Vault Lock.MediaViewerScreenno longer relies on the thumbnail'sfilePath. Instead, it triggers a secondary, isolated decryption to ensure large files are handled securely and independently.Future Settings Configuration (Flags)
To accommodate different user privacy preferences and network constraints, I have introduced two configuration flags in
VaultMediaViewerViewModel:isAutoUnmaskAllEnabled(Currentlytrue): When a user taps one masked image, all other images within the same vault item are automatically decrypted and unmasked for a smoother viewing experience.isAutoLoadAttachmentsEnabled(Currentlyfalse): Determines whether attachments should bypass the privacy mask and load automatically upon entering the vault item screen.Note: Currently, these are hardcoded properties within the ViewModel. They are explicitly designed and reserved to be moved to
SettingsRepositoryin a future PR, allowing users to toggle these behaviors via the App's "Settings -> Privacy" menu (similar toisAutoCopyTotpDisabled).📸 Video Demonstration
The video below demonstrates the seamless UX and the strict lifecycle security mechanisms:
isAutoUnmaskAllEnabledtriggers the rest).10_18_80_125_6666_20260324_132035_600.mp4
Security Checklist
DiskCacheStrategy.NONE).