← Back to io-no.com

Don't Trust the Open Link Button in Android Notifications

June 11, 2025

cover image
Cover image: @Frank01001

TL;DR

Android notifications do not properly handle some Unicode characters, leading to inconsistencies between what is displayed and what is used by the automatic Open Link suggestions. This may trick users into opening a different link from the one shown in the notification. The misbehaviour can be exploited for phishing or to trigger app links and deep links.

Background

If you regularly use an Android device, you may have noticed that notifications often include suggestions based on their content. This is particularly common—and useful—when the notifications come from messaging apps, where the system automatically suggests actions such as quick replies or opening a link contained into the message text.

notification suggestion examples

In this post, I focus on the Open Link suggestion, a button that lets users open links (automatically) extracted from a notification. It is important to clarify from the beginning that developers do not explicitly implement this feature; it is provided automatically by Android’s notification system. In this post, I will show examples using WhatsApp, Telegram, Instagram, Discord, and Slack.

The Idea

What if someone could make the Open Link suggestion open a different link from the one displayed in the notification?

Let’s take, for example, the following notification:

Amazon.com link

As shown in the screenshot, the notification displays a link to amazon.com and, as expected, includes an Open Link suggestion. But… are we sure the link that opens is actually amazon.com? Unfortunately, no. In fact, tapping Open Link on that specific notification opens zon.com (empty at the time of writing).

zon.com browser

How is this possible?

The issue lies in the way Android handles (some) Unicode characters in notifications. Certain characters—including some invisible ones—are not filtered or processed consistently, causing a mismatch between what is rendered and what the suggestion engine parses.

In the example above, the actual message text was:

ama[]zon.com

where [] represents an invisible Unicode character (U+200B, zero width space). The notification renders ama[]zon.com, including the hidden character. However, the suggestion engine treats that character as a separator, seeing ama and zon.com as two separate words. It then extracts zon.com as the link to open, so pressing Open Link opens zon.com.

A clearer case is:

amaWzon link

where (U+0D58) is a visible Unicode character. The notification displays ama൘zon.com, but the suggestion opens zon.com. Obviously, the misbehaviour is more interesting when the character is invisible, as in the original example.

It is interesting to note that, in some cases, Unicode characters actually trigger more correct behavior. For example, consider the case shown in the following screenshot.

amazon correct link

In this notification, each "a" in amazon.com is in fact a Cyrillic small letter a (U+0430) rather than the standard Latin "a". This is a common technique used in phishing attacks, where visually similar characters (known as homoglyphs) are substituted to deceive users into clicking links that appear legitimate but are not. In this particular case, the notification simply does not show the Open Link button.

Consequences

This misbehaviour can be trivially exploited to deceive users into opening a different link from the one shown in the notification. The main limitation is that the opened link must be a substring of the displayed link, but that hardly prevents an attacker from crafting persuasive payloads.

Consider another toy example.

polimi link

Here, the Open Link suggestion opens polimi.it. Indeed, the message contains actually the text www.polimi.it[]alia.[]google.[]com, where [] represents the usual invisible character (U+200B, zero width space). These characters are used to split the link into meaningful segments so that polimi.it is matched as a link, while other parts of the text containing potential link patterns are not.

One more.

wired Io_no link

The notification displays the full link, yet the Open Link suggestion silently opens tinyurl.com/2bc33y5s, which redirects to my website. The actual message text is:

wired.[]com/found-vulnerability-[]tinyurl.com/2bc33y5s[]/whatever

Here, the invisible character (U+200B, zero width space) is used to prevent wired.com from being matched as a link, ensuring that only the desired URL (tinyurl.com/2bc33y5s) is detected and suggested.

With more imagination, an attacker could craft even sneakier notifications.

The same misbehavior can deceive users into triggering app or deep links while they believe they are simply opening a regular website. For example:

wired whatsapp link

The actual text is

wired.[]com/something-here-[]wa.me/1234567890?text=provola

and the Open Link suggestion silently targets wa.me/1234567890?text=provola, which launches WhatsApp with a pre-filled message.

This happens because wa.me is registered by WhatsApp. When tapped, it invokes a deep link inside the app that opens a specific view — in this case, a chat window with the number 1234567890 and the message provola. These links are often used for legitimate app integrations but can also be abused to trigger unintended app behavior (see below).

Combining with URL-shortener

As shown in the previous example, if a link can be handled by an installed app, the Open Link suggestion in the notification displays the app's icon instead of the default browser icon. This makes the attack more noticeable to users. Furthermore, the Android notification system typically does not match custom URI schemes (i.e., schemes other than http or https), which are commonly used by app links.

To make the attack less detectable and support any type of URI scheme, attackers can use a URL shortener.

wired tiny whatsapp link

The actual notification text is the following:

wired.[]com/found-vulnerability-[]tinyurl.com/cardarella

while Open Link opens tinyurl.com/cardarella, which redirects to:

whatsapp://call-phone-number?phone=1234567890

prompting a whatsapp call to that number. In this case as well, in the tested WhatsApp version, the call requires user confirmation—this is an intentionally harmless example used for demonstration purposes.

Ok, but what can I do?

In well-designed apps, deep links that trigger actions—like sending a message, starting a call, or opening a specific screen—should always ask for user confirmation. But in the real world? That’s not always the case.

Sometimes, due to poor implementation, apps skip this crucial step, assuming that any incoming link comes from a trusted user interaction. The result? Deep links can silently perform actions without the user even realizing it. I recently encountered one such misconfigured deep link in an official Google app—no confirmation, no warning, just straight to execution (don't worry, I reported it through the proper disclosure channels). In this context, the misbehavior described here can serve as a potential entry point for deep-link exploitation.

Tests

The misbehaviour was tested on the following applications:

Some invisible characters fail in certain apps. For example, U+200B (zero width space) works on WhatsApp but not on Telegram, while U+2065 (invisible plus) succeeds on Telegram. This is likely due to internal filtering mechanisms implemented either within the app itself or on their backend servers, which prevent the storage or transmission of certain characters.

To bypass app-specific filters and validate my findings, I built a custom app capable of sending notifications with arbitrary Unicode content. This confirmed the initial observations and revealed many characters that can trigger the misbehaviour.

Devices tested

Video

Disclosure

I reported this issue to Google on 11 March 2025 through the Google Bug Hunter program (Android & Devices VRP). Below, I will share their response without any further comments.

On 26 March 2025 Google replied:

google first response

After waiting more than a couple of months for a fix on my Pixel 9 Pro XL, I asked for an update on 6 June 2025. Google replied on 7 June 2025:

gogole second response

I have informed the team of my intention to publish this post, and they had the opportunity to read it in advance.

Other Mobile Systems

Just as a reference, I’ll briefly discuss the behavior on iOS/iPadOS—practically the only other major mobile operating system.

iOS notification link

As shown in the screenshot, iOS/iPadOS exhibits the same general behavior: it splits the URL at the invisible Unicode character. However, there is one huge difference. In this case, the matching part of the link is styled with a different color and underline (typical of URLs), making it trivial for the user to spot the misbehavior.