7
6
Fork
You've already forked documentation
16

Blog post: Push notifs, security and privacy #22

Merged
s1m merged 4 commits from blog/security-privacy into main 2025年05月14日 09:29:52 +02:00
Owner
Copy link
No description provided.
Add blog post: Push notifications, security and privacy
All checks were successful
ci/woodpecker/push/main Pipeline was successful
ci/woodpecker/pr/main Pipeline was successful
32a37f9d1f
@ -0,0 +21,4 @@
## Push notifications
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information. This method is very useful for obtaining "real-time" events efficiently, particularly used for instant messaging applications.
First-time contributor
Copy link

This sentence is hard to understand I think.
Maybe something like this would work better:

Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information.

Push notifications are relatively short messages sent by an application's server to the (usually) mobile application through a push service. A push service is always reachable and forwards received messages to the mobile application, even if the application is not running.

This sentence is hard to understand I think. Maybe something like this would work better: > Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information. Push notifications are relatively short messages sent by an application's server to the (usually) mobile application through a push service. A push service is always reachable and forwards received messages to the mobile application, even if the application is not running.
s1m marked this conversation as resolved
@ -0,0 +23,4 @@
Push notifications are relatively short messages sent by an application's server to the (usually) mobile application that can be disconnected, in order to wake it up to process the information. This method is very useful for obtaining "real-time" events efficiently, particularly used for instant messaging applications.
Without push notifications, applications would either have less instant notifications, by fetching updates periodically, or would increase their battery consumption by maintaining a constant connection with their servers. The first solution is appropriate when events don't need to be instant - for example, it's acceptable to check for your phone updates every x hours. The second solution is appropriate when battery and data consumption are negligible compared to actual usage: maintaining the connection should be at a minimum efficient, and applications should be used on a daily basis. It's perfectly acceptable for the messaging app you use all day to drain a few percent of your battery a day for that connection, but it's different if you only receive one message a week on that app. What's more, we all have many applications that we rarely use.
First-time contributor
Copy link

it's acceptable to check for your phone updates every x hours

it's acceptable for your phone to check for system updates every x hours.

> it's acceptable to check for your phone updates every x hours it's acceptable for your phone to check for system updates every x hours.
s1m marked this conversation as resolved
@ -0,0 +47,4 @@
- send fake push notifications to other applications
- obtain the secrets needed to send push notifications over the Internet to other applications
- unregister other applications
- rate limit other applications, if a rate limit exists, for example to refuse registration of other applications.
First-time contributor
Copy link

rate limit other applications, if a rate limit exists, for example to refuse registration of other applications.

rate limit other applications, if a rate limit exists, for example to refuse registrations of other applications.

> rate limit other applications, if a rate limit exists, for example to refuse registration of other applications. rate limit other applications, if a rate limit exists, for example to refuse registration**s** of other applications.
s1m marked this conversation as resolved
@ -0,0 +66,4 @@
- Broadcast intents are used for IPC, and they reach the targeted application only. Other applications aren't able to read the content of IPC calls.
- Requests to the Play Services are sent with a [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). During registrations and unregistrations, the identity of the creator of the PendingIntent is used to get the sender of the request. But as stated per the documentation _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. This solution is not ideal, as PendingIntents sent for another reason can be used to unsubscribe their creator from push notifications, or to reach the rate limit.
- Requests to the subscribed applications rely on [permissions](https://developer.android.com/guide/topics/permissions/overview) (`com.google.android.c2dm.permission.SEND`) to be sure the push notifications come from the Play Services. It isn't possible to have 2 applications on the system providing the same permission. This is a good solution for Google notifications because it is designed to be provided by a single implementation of the service.
- The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
First-time contributor
Copy link

The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped.

The Play Services also relies on intents received from the system when applications are uninstalled, or when their data is wiped.

These privileged intent can't be sent from regular applications.

These privileged intents can't be sent from regular applications.

> The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped. The Play Services also relies on intent**s** received from the system when applications are uninstalled, or when their data is wiped. > These privileged intent can't be sent from regular applications. These privileged intent**s** can't be sent from regular applications.
s1m marked this conversation as resolved
@ -0,0 +69,4 @@
- The Play Services also relies on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
On the (push) server side:
- Push messages to the FCM server usually follow the FCM API, and need to contain a secret token provided by Firebase. It prevent unauthorized actors to send push notifications to applications. It is also possible to send WebPush requests, then the request rely on [VAPID](https://www.rfc-editor.org/rfc/rfc8292), and the application server needs to have a private key. Using WebPush for Google notifications has been detailed in the blog post about [push notifications for decentralized services](../20250131_push_for_decentralized/).
First-time contributor
Copy link

It prevent unauthorized actors to send push notifications to applications

It prevents unauthorized actors to send push notifications to applications

It is also possible to send WebPush requests, then the request rely on

It is also possible to send WebPush requests, then the requests rely on

> It prevent unauthorized actors to send push notifications to applications It prevent**s** unauthorized actors to send push notifications to applications > It is also possible to send WebPush requests, then the request rely on It is also possible to send WebPush requests, then the request**s** rely on
s1m marked this conversation as resolved
@ -0,0 +77,4 @@
**UnifiedPush**
UnifiedPush is a push notification protocol that allows users to choose the service they want to use. Therefore, users may install different applications providing push notifications (often called _distributors_). UnifiedPush is actually 2 different protocol, one for Android, another one for Linux.
First-time contributor
Copy link

UnifiedPush is actually 2 different protocol, one for Android, another one for Linux.
Write

UnifiedPush is actually 2 different protocols, one for Android, another one for Linux.
Write

> UnifiedPush is actually 2 different protocol, one for Android, another one for Linux. Write UnifiedPush is actually 2 different protocol**s**, one for Android, another one for Linux. Write
s1m marked this conversation as resolved
@ -0,0 +81,4 @@
For Android, the IPC calls are protected by different means:
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
First-time contributor
Copy link

if the device is recent enough.

Maybe it's better to just say: Android >= 14 ?

For older devices, the server identify the sender of the

For older devices, the server identifies the sender of the

> if the device is recent enough. Maybe it's better to just say: Android >= 14 ? > For older devices, the server identify the sender of the For older devices, the server identif**ies** the sender of the
s1m marked this conversation as resolved
@ -0,0 +82,4 @@
For Android, the IPC calls are protected by different means:
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
- A secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
First-time contributor
Copy link

This token is used to check requests' authorization from the push service, and to unsubscribe applications.

This token is used to check the requests' authorization from the push service, and to unsubscribe applications.

> This token is used to check requests' authorization from the push service, and to unsubscribe applications. This token is used to check **the** requests' authorization from the push service, and to unsubscribe applications.
s1m marked this conversation as resolved
@ -0,0 +83,4 @@
- As of Google notifications, broadcast intents are used for IPC and reach the targeted application only. Other applications aren't able to read the content of other IPC calls.
- For the registration, the application sends the intent with a flag that shares the sender real identity to the push service, if the device is recent enough. For older devices, the server identify the sender of the request using an attached [PendingIntent](https://developer.android.com/reference/android/app/PendingIntent.html). As said earlier, _the PendingIntent you receive from an application could actually be one it received from another application, meaning the result you get here will identify the original application_. PendingIntents could be passed to reach the registration rate limit of a distributor.
- A secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
- The Push services may also rely on intent received from the system when applications are uninstalled, or when their data is wiped. These privileged intent can't be sent from regular applications.
First-time contributor
Copy link

The Push services may also rely on intent received from the system when applications are uninstalled

The Push services may also rely on intents received from the system when applications are uninstalled

These privileged intent can't be sent from regular applications.

These privileged intents can't be sent from regular applications.

> The Push services may also rely on intent received from the system when applications are uninstalled The Push services may also rely on intent**s** received from the system when applications are uninstalled > These privileged intent can't be sent from regular applications. These privileged intent**s** can't be sent from regular applications.
s1m marked this conversation as resolved
@ -0,0 +88,4 @@
For linux, IPC is based on [D-Bus](https://www.freedesktop.org/wiki/Software/dbus/):
- D-Bus calls reach the targeted application only too, and other applications aren't able to read the content of other calls.
- The push service can use sandbox properties to control the origin of registration requests. For instance it can get the caller PID and control the flatpak info. If this isn't implemented and the distributor implements rate limits for the registrations, another application may be able to reach the limit for another application.
- As of Android, a secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
First-time contributor
Copy link

This token is used to check requests' authorization from the push service

This token is used to check the requests' authorization from the push service

> This token is used to check requests' authorization from the push service This token is used to check **the** requests' authorization from the push service
s1m marked this conversation as resolved
@ -0,0 +91,4 @@
- As of Android, a secret token is generated and shared during the first registration call. This token is used to check requests' authorization from the push service, and to unsubscribe applications.
On the push server side:
- Push endpoints, the URL where applications sends push messages, are [Capability URL](https://www.w3.org/TR/capability-urls/). This kind of URL works as a shared secret between the application and the push system. It usually contain a token and can be re-generated if necessary.
First-time contributor
Copy link

the URL where applications sends push messages

the URL where applications send push messages

It usually contain a token and can be re-generated if necessary.

It usually contains a token and can be re-generated if necessary.

> the URL where applications sends push messages the URL where applications **send** push messages > It usually contain a token and can be re-generated if necessary. It usually contain**s** a token and can be re-generated if necessary.
s1m marked this conversation as resolved
@ -0,0 +92,4 @@
On the push server side:
- Push endpoints, the URL where applications sends push messages, are [Capability URL](https://www.w3.org/TR/capability-urls/). This kind of URL works as a shared secret between the application and the push system. It usually contain a token and can be re-generated if necessary.
- Push servers are supposed to support VAPID. VAPID is a standard ([RFC8292](https://www.rfc-editor.org/rfc/rfc8292)) providing access control based on asymmetric keys. All provider doesn't check VAPID authorizations, but UnifiedPush specifications even allow distributors to _require_ it. The application registers with the push service for a given public key, then the push server will only accept requests with a signature made with this private key, for the given push server. This is an additional protection, if the push endpoint is leaked, it cannot be used.
First-time contributor
Copy link

All provider doesn't check VAPID authorizations

Not all providers check VAPID authorizations

> All provider doesn't check VAPID authorizations Not all providers check VAPID authorizations
s1m marked this conversation as resolved
@ -0,0 +102,4 @@
Other aspects can be analyzed, such as the possibility of using push notifications as a DDOS amplification vector or for Server-Side Request Forgery (SSRF, a bug exploited to send requests from the server to resources inaccessible to the attacker, such as resources in the server LAN). For both these reasons, it is recommended that the application server:
- rejects push endpoints pointing to private IPs, with an option to allow some IP/hosts for self-hosters
- doesn't follow redirections for push requests
- sends a single push request with a token to validate a push subscription. Actual push notifications will be send once the subscription is validated. It's like what usually see to valide email addresses.
First-time contributor
Copy link

Actual push notifications will be send once the subscription is validated.

Actual push notifications will be sent once the subscription is validated.

> Actual push notifications will be send once the subscription is validated. Actual push notifications will be sen**t** once the subscription is validated.
s1m marked this conversation as resolved
@ -0,0 +103,4 @@
- rejects push endpoints pointing to private IPs, with an option to allow some IP/hosts for self-hosters
- doesn't follow redirections for push requests
- sends a single push request with a token to validate a push subscription. Actual push notifications will be send once the subscription is validated. It's like what usually see to valide email addresses.
- removes push subscriptions that returns a 404 HTTP code
First-time contributor
Copy link

removes push subscriptions that returns a 404 HTTP code

removes push subscriptions that return a 404 HTTP code

> removes push subscriptions that returns a 404 HTTP code removes push subscriptions that **return** a 404 HTTP code
s1m marked this conversation as resolved
Minor patch to blog post about push & security
All checks were successful
ci/woodpecker/push/main Pipeline was successful
ci/woodpecker/pr/main Pipeline was successful
ci/woodpecker/pull_request_closed/main Pipeline was successful
5623c07fb7
Author
Owner
Copy link

Thanks for your review @maximiliangalanis !

Thanks for your review @maximiliangalanis !
Sign in to join this conversation.
No reviewers
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
UnifiedPush/documentation!22
Reference in a new issue
UnifiedPush/documentation
No description provided.
Delete branch "blog/security-privacy"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?