Security insights

Push Notifications as an Attack Surface

A founder once asked me, halfway through a pentest debrief: "Push notifications? Really?" Yes, really. A Q&A walking through every question we get about why notifications are dangerous, and the answers that usually surprise the room.

BU
BugSwagger Team

We were sitting in a glass conference room at the end of a two-week mobile engagement. The CTO had assembled their team for the debrief. We were on slide eleven of the report. The slide said: "Critical: notification extension fetches arbitrary URLs from push payloads."

The CEO, who had wandered in to listen, raised his hand. "Sorry — push notifications? Like, the little banners? Why are those a critical finding?"

That conversation lasted twenty minutes. It was the most engaged the room had been all week. I've had a version of the same conversation in roughly thirty other engagements since. The questions don't change much. The answers usually do surprise the room.

So, in the spirit of being useful: here are the questions we get most often about push notifications as an attack surface, and the answers we give. If you're a founder or CTO and you've been quietly wondering whether the "notification stuff" matters — this Q&A is for you.

Q: Push notifications go from our backend to Apple, then to the user's phone. Where does the attacker fit in?

A: This is the right first question, and the answer that throws people is: the attacker is whoever can send a push to your users. The pipeline you described — your backend → APNS or FCM → phone — has at least four places where an attacker can become "whoever can send a push."

First, your backend itself. If any service that has access to your APNS/FCM credentials is compromised, the attacker now sends pushes. We've seen analytics SDKs, marketing platforms, and vendor integrations that all have push-sending capability for legitimate reasons. Each of those is a back door.

Second, your APNS or FCM credentials directly. Tokens leak. Credentials leak. The Apple or Google account that owns the push certificate may have weaker authentication than the production database. We have seen APNS keys committed to GitHub repositories, sitting in environment dumps, included in mobile app binaries by accident. Whoever finds one of those can send arbitrary pushes to your users.

Third, your third-party push service. Many companies don't talk to APNS directly — they use OneSignal, Braze, Iterable, Customer.io, Airship, or similar. Those services have access to your push tokens. A compromise of one of them is a compromise of your push channel. The supply chain matters here as much as anywhere.

Fourth, the user's account in your own product. If sending a push is a feature your app exposes (notifying followers of a new message, alerting team members of an event), then any user can trigger pushes. A malicious user can become an attacker against another user, through your own UI.

So the "attacker who can send a push" is not a hypothetical state actor. It's the union of all of those vectors, and at least one of them is almost certainly easier to compromise than your application itself.

Q: Okay, but worst case — they send a notification with a weird message. That's annoying, not a breach.

A: If the only thing your notification handler did was display the text, you'd be right. The text-only push is mostly a nuisance, modulo phishing-by-display tricks.

The reason notifications are an attack surface is that your app does more than display the text. Specifically, two things happen before the user sees anything:

One: on iOS, your UNNotificationServiceExtension runs. On Android, your NotificationListenerService. This is code you wrote, running in the background, before the user is aware a push arrived. It can parse the payload, modify it, fetch additional content, do whatever the developer programmed. It runs without user interaction. Every bug in this code is a 0-click bug — meaning the user has to do nothing for it to fire.

Two: notifications support attachments. Rich media — images, videos, audio — fetched from URLs in the payload. The fetching and parsing happens in the background. If the parser has a memory corruption bug, and the attachment URL points at an attacker-crafted image, you have a 0-click image parser exploit, exactly the same shape as the iOS zero-clicks we covered in a separate article.

The text is the only part the user sees. Most of what runs is invisible to them.

Q: But our notification extension is small. We just parse a couple of fields. There can't be much there.

A: That sentence is the one that usually leads to the actual finding. Let me walk you through what "we just parse a couple of fields" tends to look like in production.

We tested an app whose notification extension was twenty lines of code. It read a "title" field, a "body" field, and an "image_url" field. Title and body went straight into the notification. The image_url was fetched and attached as a rich media preview.

That image_url field is the entire finding. The extension was fetching whatever URL the push payload contained. No allowlist. No validation. The team's mental model was "the URL comes from our backend, our backend is trusted." The attacker's mental model was "the URL comes from the push payload, and I can send pushes."

What can you do with an arbitrary fetch from a notification extension? Quite a lot. You can point it at http://169.254.169.254/... if the phone is on a corporate Wi-Fi that has access to internal AWS metadata. You can point it at internal IP addresses if the user is on a VPN — half of enterprise users are on a VPN half the time. You can point it at a URL that returns a malicious image and rely on the image parser to misbehave. You can point it at a URL that returns a 10GB response and burn the user's data plan and battery.

Twenty lines of code. One critical finding.

Q: We use deep links from notifications — tap the notification, it opens the relevant screen. Is that a problem?

A: Yes, and this is one of the most common ways notifications escalate to account takeover. The pattern goes:

The notification handler defines what URL to deep-link to when tapped. The URL comes from the push payload. The deep link handler in your app navigates to the URL's destination — and, often, performs the action implied by the URL.

We've seen apps where a notification tap could navigate to app://settings/disable-2fa?confirm=true. The user taps "you have a new message." Their 2FA gets disabled. They never saw the URL. They tapped a notification.

The principle to enforce: a notification tap navigates the user; it does not act on the user's behalf. Every action requires explicit user interaction within the app after navigation. The notification is the doorbell. It is not the key.

If your team can't immediately enumerate which deep links from notifications can result in state changes without further confirmation, that audit is the work for next sprint.

Q: We sign our push payloads. Doesn't that solve the problem?

A: It helps. It doesn't solve.

Signing helps against the case where the attacker has access to APNS/FCM but not your signing key. That is a meaningful category of attackers — a leaked APNS certificate is much more common than a leaked HMAC key, statistically. So payload signing closes that vector.

It does not close the cases where the attacker has compromised your backend (which has the signing key), where a vendor with push access (with their own signing infrastructure) is compromised, or where the threat model is "user A pushes to user B" through legitimate features of your app.

Signing is one layer. The other layers are: validating the payload contents even when signed (signed garbage is still garbage), keeping URLs out of payloads and using opaque tokens instead, and requiring user interaction for any action.

Q: How would we even know if this had been exploited?

A: Probably you wouldn't, which is the honest answer to most "how would we know" questions in mobile security.

The notification handler runs in the background. It doesn't generate logs unless you wrote logging into it. Most teams haven't. If the handler fetches an attacker-controlled URL, your detection would have to be at the device level (very few teams have this), at the network level on the user's WiFi (you don't have this), or at the destination service (which would be the attacker's service, so no).

The first signal of this class of compromise will, in most cases, be a user noticing something off. Their account behaves strangely. A 2FA setting they didn't change. A connected device they don't recognize. The user files a support ticket. The support ticket sits in a queue for a day. By then, the attacker has been operating for however long they've been operating.

This is, by the way, why the upstream fixes — validating payloads, no URLs in payloads, no actions on tap — are more important than detection. The detection layer for this kind of attack is so weak that prevention has to do almost all the work.

Q: My team is going to say "but no one is doing this in the wild." What's the answer?

A: That sentence — "no one is doing this in the wild" — is one of the more reliable predictors of being in someone else's wild. It usually means "we have not specifically looked for this in our logs, and nobody has notified us yet." Both of those things can be true while you are, in fact, being exploited.

The harder answer: commercial spyware operations have been confirmed using push notifications as part of delivery chains. WhatsApp's lawsuit against NSO Group documented push-related payloads. Other research has documented similar patterns. The "in the wild" volume on this specific surface is meaningful for high-value targets and modest for the rest, but the surface is real, and growing.

The framing that lands better than "people are doing this": "What's the cost if someone does, what's the cost if they don't, and what's the cost of closing the surface either way?" The cost of closing is small. The cost of being on the wrong side of either of the other two answers is large. The math points one direction.

Q: What's the actual change set you'd recommend? Concrete things.

A: Five.

One. Treat the push payload as untrusted input, identical in trust level to a public API request. Validate every field. Reject unknown fields. Apply the same allowlists you would on your API.

Two. Stop putting URLs in payloads. Use opaque tokens — a notification ID that your app resolves against a known set of pre-registered actions and destinations. The token has no power outside the app; the URL has all the power in the world.

Three. Notification taps navigate, never act. If you have an action that fires from a notification — disabling 2FA, confirming a payment, accepting a transfer — wrap it in an in-app confirmation that requires the user to explicitly approve after the navigation.

Four. Sign payloads with a key that lives only in your application backend, not in vendor systems. Verify in the extension before acting. This closes the "leaked APNS certificate" attacker class.

Five. Audit what your notification extension actually does. The most useful exercise is: read the extension's source code end to end, and write down every external call (network, file, IPC) it makes. Then ask whether each is necessary. Usually at least one isn't.

Q: How long would it take to implement these?

A: One sprint for most apps, if the team is focused. The work is genuinely small. The tax is mostly in the audit — finding every place the current notification logic does something it shouldn't — rather than in the new code. Most teams find this surprising; they expect the work to be larger and end up shipping the fix faster than the meeting in which they decided to do it.

One last question, the one that ended the original meeting

The CEO who had wandered in: "Has anyone you've worked with actually shipped this fix?"

Me: "Most of them did, within two months of finding it. Two haven't yet. One of them had a breach last quarter that involved this surface. They're shipping the fix now."

The CEO sat back in his chair. "Add it to next sprint."

That, more than anything else, is what I want you to take from this Q&A. The conversation about push notifications doesn't have to be long. It just has to happen. Most teams haven't had it. The ones who do, in our experience, fix the obvious problems within a quarter. The ones who don't, find out about the problems some other way.

Found this helpful?

Want a hand-tested assessment for your own stack?

Tell us what you're protecting — we'll respond within one business day with a scoped proposal written by a pentester.