Skip to content

Conversation

@sullystuff
Copy link

@sullystuff sullystuff commented Nov 28, 2025

First time contributor checklist

Contributor checklist

  • Samsung S24 Ultra - Android 16
  • My contribution is fully baked and ready to be merged as is
  • I ensure that all the open issues my contribution fixes are mentioned in the commit message of my first commit using the Fixes #1234 syntax

Description

Add privacy features to prevent timing attacks as detailed here

  • Add random delay 300-5000ms to delivered/read receipts
  • Disable delivered receipts for:
    • Edited messages
    • Reactions (delivered receipts do not show on any UI, this has no reason to exist)
    • Deleted messages (delivered receipts do not show on any UI, this has no reason to exist)
    • blocked users (this is default on iOS but doesn't exist on Android, this can be used to profile users)

Tested with iOS 26.1 on iPhone 16 Pro as well as Windows 11 for the sending client, and aforementioned Android mobile device for the receiving client (with this modified apk)

@flattop-coleslaw-reaffirm
Copy link

flattop-coleslaw-reaffirm commented Nov 28, 2025

this is good fun!

If the server can see the sender, it will send a receipt.

Ironically, it doesn't send a receipt until the client is online. Exposing you are online. This is also a problem that should be fixed!!!

Disable delivered receipts for:

Edited messages

These show up in the ui. It's inconsistent to disable them.

blocked users (this is default on iOS but doesn't exist on Android, this can be used to profile users)

Again, if the server can see the sender, it sends a receipt. This will commonly be the case with blocked senders. When the server cannot see the sender no receipt is sent to blocked senders on Android.

You don't need all those options; when might someone prefer instant receipts?

Consider removing the minimum delay so instant can be chosen at random.

@sullystuff
Copy link
Author

If the server can see the sender, it will send a receipt.

Are you referring to the Signal servers?
If so, I toggled "disable edit delivered receipts" on the test device, edited a message on Device 1 and it was not marked as delivered. I then interacted with test device, sending and receiving messages to and from another user, and the edited message still has not been marked as delivered. Same goes for all other delivered receipt toggles I added

These show up in the ui. It's inconsistent to disable them.

Yes, it should be an optional toggle, and it should be clear how it will affect UX for the other users.

I'll consider ways to drop the time add minimum to 0, or perhaps make the delay an optional range.

@sullystuff
Copy link
Author

Disabled delivered receipts are enabled by default for reactions+deletes as these don't affect UX at all

@flattop-coleslaw-reaffirm

the edited message still has not been marked as delivered

If you ensure Allow from anyone in Settings>Privacy>Advanced is off for the test device, ensure both devices don't share group membership, block Device 1 and then edit the message you'll have a different result.

Show status icon is on by default I believe in the same section of settings.

On Device 1, If you look at "Message details" for the message to be edited you'll see the icon. Then once you edit the message it'll vanish.

If Device 1 can prove it has the test device's current profile keys, the server cannot see that Device 1 sent a message to the test device.

https://signal.org/blog/sealed-sender#:~:text=Delivery%20tokens

Blocking rotates test device's profile key meaning Device 1 will only receive server receipts, nothing directly from the test device.

if Allow from anyone is on, Device 1 doesn't need test device's profile keys.
On Android, shared group membership means blocking doesn't rotate profile key.

@sullystuff
Copy link
Author

Interesting, you're right, so this only works when the attacker is using sealed sender, and an attacker is most likely to not use sealed sender lol... so is there no way to patch that on the client end? Is this a protocol issue?

@Lama-Thematique
Copy link

Lama-Thematique commented Nov 29, 2025

Add random delay 300-5000ms to delivered/read receipts

This is good but not perfect, is make the phone delay distribution much less obvious by adding a lot of variance and shifting the mean by 2.65 seconds but with enough data points you could still statistically estimate the mean over a period and compensate for both the added variance and the shift of the distribution.

The new distribution is now a sum of the 'true' distribution (delay from the phone) that we want to hide, and the 'fake' distribution the random 0.3 to 5 second delay.

By modelling the coupled distribution you can get estimations of the real distribution of timings from the device and be able to defeat the random delay mitigation. There is 2 possibilities to fix it:

  • Have the range of delay so high that you need way to much datapoint to do analysis making it practically useless but this is unpractical as it would either needs a low rate limit or a long delay for seen indicators to correctly mask the distribution.
  • Compensate the fake distribution to hide the true distribution.

How to compensate:

  1. Compute the delay (call it 'd') from the moment the signal server received the message (and i hope the is a way to get a timestamp for that) and the moment you are processing the response (just before adding it to queue).
  2. get a random value bewteen 0.3 and 5 seconds (call it 'r').
  3. delay the message by : r - d

This way it's no longer possible to mesure d and hence do the exploit.

Note: the graphs on the paper observe maximum delays of about 3 seconds, this should become the lower bound of the delay instead of 0.3 sec, so 'r' should be sampled form a uniform distribution ranging from 3 to 5 second.

Note 2: The exploit might still be possible after this if queued responses are also being delayed differently depending the device state (I don't know how if it's the case), in which case estimation of the full delay is needs to be compensated which is harder to do preciselly. My hypothesis (that need to be verified empirically before implementation) for a simple estimation of that full delay could be the double of 'd' initally estimated changing the last step "to delay the message by : r - 2*d".

@Lama-Thematique
Copy link

Finally I would recommend contacting the original authors of the papers once you have some good mitigations in place so that they can verify it by testing it in practice on the same devices used for their research, as they likelly already have code for that kinds of mesurements.

@flattop-coleslaw-reaffirm

If the intent is protection from traffic analysts @sullystuff this seems effective. Signal might implement it in a more joined-up, rigorous and thorough way.

They should also fix that server-side issue I mentioned too.

@Lama-Thematique
Copy link

What I'd like to suggest is to merge the random delay as is, for 2 reasons:

  • test if there is community backlash for the additional delay that it creates
  • have a quick answer to less sophisticated analysis

At the same time, a second cross platform issue/tracker that also include protocol discussion should be created to discuss how to best make the entire attack completely impossible.
This discussion is complex and likelly it will take a significant amount of time keeping the vulnerability exploitable for long which is why it's better with a temporary "quick fix" merged.

@Lama-Thematique
Copy link

Lama-Thematique commented Nov 29, 2025

Finally after thinking it over, it might much easier to mitigate server side. This does place more trust in the server as the server would be able to collect all the data for the exploit. But the server can easily compute the full exact RTT of your device and correct for it when sending the read indicator back to the attacker.
A server side mitigation also does not care about the wide range of possible devices that could have different behaviours nor the platform used by the user.

@sullystuff
Copy link
Author

@Lama-Thematique Sure, it's easier to mitigate server-side, but as you stated that places more trust in the server when we're trying to avoid that (imo)

This is good but not perfect, is make the phone delay distribution much less obvious by adding a lot of variance and shifting the mean by 2.65 seconds but with enough data points you could still statistically estimate the mean over a period and compensate for both the added variance and the shift of the distribution.

Yes, over a long enough period of time an attacker could, in theory, be able to calculate away the noise. I think the best trustless solution here is to adjust the min/max delays on a per-device/OS-version basis, as reported by those researchers. I'll do my best to get in touch with them.

@sullystuff
Copy link
Author

I've sent an email to one of the researchers, I'll update here if I get a response, and if I don't I'll reach out to a few more.

@Lama-Thematique
Copy link

Lama-Thematique commented Nov 29, 2025

Sure, it's easier to mitigate server-side, but as you stated that places more trust in the server when we're trying to avoid that (imo)

It's tradeoffs as:

  • server side mitigation is certainly better than current status as today everyone (server and 3rd party alike) can use this attack.
  • the server side mitigations is very easy to implement code wise
  • it makes 100% sure the distribution is hidden to 3rd party (as we can have exact RTT)
  • but the negative is that it trust the server

Tho i agree that i would prefer a solid trustless implementation.


Trustless solution are great because it's trustless but could not entirely hide the distributions correctly as it's based on estimations of RTT. Implementation needs to be carefull to have good unbiased estimates of the true RTT distribution in all situations (4g/wifi, different OS and version, different hardwares, different background/foreground tasks, etc...) otherwise better data anlysis could bring back the problem.

per-device/OS-version basis

This is a bad idea IMO at it requires constant maintenance for the table of devices and OS versions and could still be affected by other factors. For trustless solutions I think heuristic based methods are preferable meaning device estimates it's own RTT by itself.


In all, my preferences (and this is a opinion so it's debatable) are:
Best = Precise trustless solution
Ok = trusted server side solution
Worse = Naïve trustless solution
Bad = No solutions

@sullystuff
Copy link
Author

We can probably automate tests on the client to measure the average time to perform return pings (standby, app foreground, app background, active phone call etc) and adjust the delay by the measured average time per state. That will take a while to write though.

@sullystuff
Copy link
Author

@greyson-signal @alex-signal thoughts?

@kernoelpanic
Copy link

Hey there,

I’m one of the authors of the paper you referred to. We’re happy to see progress being made to mitigate the issue. We fully agree that having no solution is the worst option, but finding a “real fix” is also quite tricky.

As you already noted, there are things which can be done with relatively little effort, though:

  • Prevent sending receipts of any kind for actions that do not trigger observable notifications for the user. This prevents an attacker from gathering a large set of samples in a short amount of time.
  • Force a specific distribution of receipts on the client side (as discussed here). This will not be perfect, but it would have an immediate effect by making it much harder in practice to extract useful information from receipts.

Keep in mind, this will not be a solution against the various "is online" side-channels, but make it harder for an attacker to extract more information from receipts.

In the long run, other solutions can be considered. These might also include a discussion about whether explicit delivery receipts are needed at all, or whether they could be disabled by privacy-sensitive users. From our current understanding, delivery receipts mainly serve the purpose of allowing the sender to clear their send queue and handle certain edge cases. But we would love to have a more detailed discussion about whether it might be possible to get rid of them completely. Maybe it is enough to implicitly acknowledge received messages only when an explicit reply is sent, for example?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants