Talos Vulnerability Report


Signal Messenger Android self deleting messages Information Disclosure Vulnerability

December 6, 2018
CVE Number



Signal Messenger for Android 4.24.8 may expose private information when using “disappearing messages.” If a user uses the photo feature available in the “attach file” menu, then Signal will leave the picture in its own cache directory, which is available to any application on the system.

Tested Versions

Signal Messenger Android 4.24.8

Product URLs


CVSSv3 Score

3.3 - CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N


CWE-359: Exposure of Private Information (‘Privacy Violation’)


By default Signal uses its own photo-taking code rather than using the Android provided MediaStore class to provide photo taking functionality. This allows Signal to have a better control over the photos and to allows it to avoid information leaks.

However, if a user uses the photo taking feature available in the “Attach File” menu, then this photo will be taken by the Android MediaStore class rather than using Signal’s code. A file with the photo will be stored in the signal cache directory, which will not be deleted from the file system, even if the user has the “disappearing messages” option enabled, leaving the photo exposed to any application on the system.

Looking at the Signal for Android source code, the file AttachmentTypeSelector.java contains the source code for the class that generates the “Attach File” menu options. The camera button and the listener are defined as marked bellow, a possible solution would be to either redirect the button to use Signal’s own camera code or just eliminate the option altogether.

public AttachmentTypeSelector(@NonNull Context context, @NonNull LoaderManager loaderManager, @Nullable AttachmentClickedListener listener) { super(context);

LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout   layout   = (LinearLayout) inflater.inflate(R.layout.attachment_type_selector, null, true);

this.listener       = listener;
this.loaderManager  = loaderManager;
this.recentRail     = ViewUtil.findById(layout, R.id.recent_photos);
this.imageButton    = ViewUtil.findById(layout, R.id.gallery_button);
this.audioButton    = ViewUtil.findById(layout, R.id.audio_button);
this.documentButton = ViewUtil.findById(layout, R.id.document_button);
this.contactButton  = ViewUtil.findById(layout, R.id.contact_button);
this.cameraButton   = ViewUtil.findById(layout, R.id.camera_button);                    <---- Camera Option
this.locationButton = ViewUtil.findById(layout, R.id.location_button);
this.gifButton      = ViewUtil.findById(layout, R.id.giphy_button);
this.closeButton    = ViewUtil.findById(layout, R.id.close_button);

this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_GALLERY));
this.audioButton.setOnClickListener(new PropagatingClickListener(ADD_SOUND));
this.documentButton.setOnClickListener(new PropagatingClickListener(ADD_DOCUMENT));
this.contactButton.setOnClickListener(new PropagatingClickListener(ADD_CONTACT_INFO));
this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO));          <----- TAKE_PHOTO
this.locationButton.setOnClickListener(new PropagatingClickListener(ADD_LOCATION));
this.gifButton.setOnClickListener(new PropagatingClickListener(ADD_GIF));
this.closeButton.setOnClickListener(new CloseClickListener());
this.recentRail.setListener(new RecentPhotoSelectedListener());

  ViewUtil.findById(layout, R.id.location_linear_layout).setVisibility(View.INVISIBLE);

Given that this behavior does not occur when using the regular Signal provided icon to take photos, there is a legitimate expectation from the users that the behavior will be the same in both cases.


2018-09-10 - Initial contact
2018-09-12 - Vendor Disclosure
2018-09-25 - Vendor fix released on version 4.26.2
2018-12-07 - Public Release


Discovered by Vitor Ventura of Cisco Talos.