Auditing mobile WebView bridge exposure: when a web page calls into the native app
A mobile app that embeds a WebView often gives the web content a way to call back into native code: a bridge
that exposes native methods to JavaScript so the page can use the camera, read files, fetch tokens, or drive
app features. That bridge is safe only when the content on the other side is trusted and confined, content the
app authored, loaded from an origin it controls, over a channel that cannot be tampered with. It becomes an
exposure when untrusted content reaches the bridge: a remote page the app loads, a third-party frame inside
it, a link the WebView follows to an attacker origin, or content injected over an insecure channel. Then web
script the app did not author invokes native methods and acts with the app's privileges. The bug is a native
capability reachable from web content the app does not fully trust, whether because the bridge is exposed to
untrusted origins, the WebView loads content it should not, or the bridge methods trust any caller. You audit
these by tracing which content can reach the bridge and what each exposed method does.
When to use
- A native app embeds a WebView that exposes a native interface or message handler to JavaScript.
- The WebView loads remote content, third-party frames, or follows links to origins the app does not control.
- Bridge methods perform privileged actions or return app data without checking the calling origin.
Scope check
Audit WebView bridges only on apps you own or are authorized to assess, on test devices and accounts, driving
the bridge with benign content you control rather than acting against real data. A confirmed exposure lets web
content wield native privilege, so keep every probe within scope. If you can't name the authorization, stop.
The loop
Establish which content can actually reach the bridge and whether the methods check the caller first.
For each exposed native interface, determine whether only trusted, app-authored content loaded from a
controlled origin over a secure channel can reach it, or whether remote content, a third-party frame, a
followed link, or injected content can, and whether each bridge method verifies the calling origin. This is
the false-positive killer: a bridge reachable only by trusted confined content, or one whose methods
authorize the caller, is not driven by an attacker even though it exposes native capability. Name the
untrusted content path before crafting a call.
Enumerate the exposed native methods. List the methods the bridge exposes to JavaScript and what each
does: privileged actions, data reads, capability access, or navigation. Note which are sensitive enough
that web script invoking them would matter.
Map what content can reach the bridge. Determine what the WebView loads and whether it is confined to a
controlled origin: does it load remote pages, allow third-party frames, follow links to arbitrary origins,
or load content over a channel an attacker can tamper with. Any untrusted content that runs script in the
WebView can reach an exposed bridge.
Check the origin and caller restriction. Determine whether the bridge is exposed only to trusted
origins and whether each method verifies the caller before acting, or whether the interface is available to
whatever content runs in the WebView and the methods trust any caller. A method that acts for any origin is
the exposure.
Check the content-loading confinement. Determine whether the WebView restricts navigation to the app's
own origins, blocks mixed and insecure content, and isolates any third-party frame from the bridge, or
whether untrusted content can be loaded into the same context that holds the interface.
Confirm and record. Confirm by loading benign untrusted content you control into the WebView, through a
followed link, a frame, or a tampered channel, and invoking a sensitive native method from that content on
a test device. Kill the lead if only trusted confined content reaches the bridge, if each method authorizes
the calling origin, and if navigation and framing are restricted to controlled origins. Record the method,
the untrusted content path, the missing check, and the invocation observed, or set a kill_reason.
Where the WebView bridge leaks
- The untrusted-content path is the finding. A bridge is expected to expose capability to trusted content;
the bug is untrusted content reaching it. Name how attacker content gets into the WebView.
- Remote and mixed content bring the attacker in. A WebView that loads remote pages or allows insecure
content lets a tampered or attacker page run script beside the interface.
- Third-party frames inherit the bridge. A frame from another origin loaded in the same WebView can reach
an interface exposed to the whole context unless the bridge is confined to the top frame's trusted origin.
- Followed links escape the trusted origin. A WebView that follows links to arbitrary origins can navigate
to an attacker page that then calls the bridge.
- Methods that trust any caller are the sink. A bridge method that performs a privileged action or returns
data without checking the calling origin acts for whatever content invoked it.
Worked example (a confirm and a kill)
Confirm. A WebView exposes a native method that returns an authentication token and follows links to
arbitrary origins. Navigating the WebView to a benign attacker-controlled page over a followed link lets that
page's script invoke the method and receive the token, on a test device with a test account. Confirmed
native capability reachable from untrusted web content, high, remediation = expose the bridge only to
app-authored content on a controlled origin, verify the calling origin in each native method, restrict WebView
navigation and framing to controlled origins, and block insecure and mixed content.
Kill. The same WebView loads only app-authored content from a controlled origin over a secure channel,
restricts navigation so links to other origins open outside the bridge context, isolates third-party frames
from the interface, and each native method verifies the calling origin before acting. No untrusted content
reaches the bridge. Killed, kill_reason = "the bridge is reachable only by trusted confined content on a
controlled origin and every method authorizes the caller; untrusted web content cannot invoke a native
method."
Rationalizations to reject
- "We only load our own pages." -> Confirm the WebView cannot navigate or frame elsewhere; a followed link,
a redirect, or an embedded frame can bring untrusted content into the same context as the bridge.
- "The bridge only exposes harmless methods." -> Enumerate every exposed method; one that returns a token,
reads a file, or performs an action is enough, and harmless methods can be chained.
- "The connection is HTTPS." -> A secure channel to a remote origin still runs remote script beside the
bridge; transport security does not make the loaded origin trusted.
- "A frame cannot reach our interface." -> If the interface is exposed to the whole WebView context, a
third-party frame's script can reach it unless the bridge confines itself to the trusted top origin.
- "The method just returns data." -> Returning app data to untrusted web script is disclosure; treat a data
read as a sensitive method and authorize the caller.
Executing this in practice
You need every native method the bridge exposes, what each does, and whether it verifies the calling origin,
plus what the WebView loads and whether navigation, framing, and content security confine it to controlled
origins. For each exposed method, decide whether untrusted content can reach it through a remote page, a
frame, a followed link, or a tampered channel. Reading the bridge exposure and the WebView's loading policy
settles most leads; loading benign untrusted content you control and invoking a sensitive method on a test
device settles the rest.
Related
auditing-mobile-deeplink-trust - a deep link that drives the WebView to load attacker content is one way
untrusted content reaches the bridge, joining link trust to bridge exposure.
testing-postmessage-and-web-message-trust - a bridge reached through cross-frame messaging shares the
origin-verification failure that skill treats in the pure-web setting.
hunting-mobile-tls-pinning-and-trust-gaps - content loaded over a channel an attacker can tamper with
reaches the bridge, the transport-trust gap that skill covers.
auditing-electron-ipc-trust - the desktop analogue, where a renderer bridges to native capability and the
same caller-authorization question applies.
- FINDING-SCHEMA.md - source = the untrusted web content reaching the bridge, sink =
the native method it invokes, evidence = benign attacker-controlled content invoking a sensitive native
method on a test device.
1---2name: auditing-mobile-webview-bridge-exposure3description: Audit the trust a mobile app places in web content loaded in an embedded WebView, where a native bridge exposes app capabilities to JavaScript, letting web content that the app did not author, remote pages, loaded third-party frames, or attacker-influenced URLs, call native methods, read app data, or act with the app's privileges, because the bridge is exposed to untrusted origins, the loaded content is not origin-restricted, or the bridge methods do not check the caller. Use when a native app embeds a WebView that both loads remote or mixed content and exposes a native interface to script. Covers script-to-native bridges reachable by untrusted content, unrestricted content loading, and bridge methods that trust any caller. The untrusted web content reaching the bridge is the source, the native method it invokes is the sink, and web script driving native capability is the bug.4license: MIT5---67# Auditing mobile WebView bridge exposure: when a web page calls into the native app89A mobile app that embeds a WebView often gives the web content a way to call back into native code: a bridge10that exposes native methods to JavaScript so the page can use the camera, read files, fetch tokens, or drive11app features. That bridge is safe only when the content on the other side is trusted and confined, content the12app authored, loaded from an origin it controls, over a channel that cannot be tampered with. It becomes an13exposure when untrusted content reaches the bridge: a remote page the app loads, a third-party frame inside14it, a link the WebView follows to an attacker origin, or content injected over an insecure channel. Then web15script the app did not author invokes native methods and acts with the app's privileges. The bug is a native16capability reachable from web content the app does not fully trust, whether because the bridge is exposed to17untrusted origins, the WebView loads content it should not, or the bridge methods trust any caller. You audit18these by tracing which content can reach the bridge and what each exposed method does.1920## When to use2122- A native app embeds a WebView that exposes a native interface or message handler to JavaScript.23- The WebView loads remote content, third-party frames, or follows links to origins the app does not control.24- Bridge methods perform privileged actions or return app data without checking the calling origin.2526## Scope check2728Audit WebView bridges only on apps you own or are authorized to assess, on test devices and accounts, driving29the bridge with benign content you control rather than acting against real data. A confirmed exposure lets web30content wield native privilege, so keep every probe within scope. If you can't name the authorization, stop.3132## The loop33341. **Establish which content can actually reach the bridge and whether the methods check the caller first.**35 For each exposed native interface, determine whether only trusted, app-authored content loaded from a36 controlled origin over a secure channel can reach it, or whether remote content, a third-party frame, a37 followed link, or injected content can, and whether each bridge method verifies the calling origin. This is38 the false-positive killer: a bridge reachable only by trusted confined content, or one whose methods39 authorize the caller, is not driven by an attacker even though it exposes native capability. Name the40 untrusted content path before crafting a call.41422. **Enumerate the exposed native methods.** List the methods the bridge exposes to JavaScript and what each43 does: privileged actions, data reads, capability access, or navigation. Note which are sensitive enough44 that web script invoking them would matter.45463. **Map what content can reach the bridge.** Determine what the WebView loads and whether it is confined to a47 controlled origin: does it load remote pages, allow third-party frames, follow links to arbitrary origins,48 or load content over a channel an attacker can tamper with. Any untrusted content that runs script in the49 WebView can reach an exposed bridge.50514. **Check the origin and caller restriction.** Determine whether the bridge is exposed only to trusted52 origins and whether each method verifies the caller before acting, or whether the interface is available to53 whatever content runs in the WebView and the methods trust any caller. A method that acts for any origin is54 the exposure.55565. **Check the content-loading confinement.** Determine whether the WebView restricts navigation to the app's57 own origins, blocks mixed and insecure content, and isolates any third-party frame from the bridge, or58 whether untrusted content can be loaded into the same context that holds the interface.59606. **Confirm and record.** Confirm by loading benign untrusted content you control into the WebView, through a61 followed link, a frame, or a tampered channel, and invoking a sensitive native method from that content on62 a test device. Kill the lead if only trusted confined content reaches the bridge, if each method authorizes63 the calling origin, and if navigation and framing are restricted to controlled origins. Record the method,64 the untrusted content path, the missing check, and the invocation observed, or set a `kill_reason`.6566## Where the WebView bridge leaks6768- **The untrusted-content path is the finding.** A bridge is expected to expose capability to trusted content;69 the bug is untrusted content reaching it. Name how attacker content gets into the WebView.70- **Remote and mixed content bring the attacker in.** A WebView that loads remote pages or allows insecure71 content lets a tampered or attacker page run script beside the interface.72- **Third-party frames inherit the bridge.** A frame from another origin loaded in the same WebView can reach73 an interface exposed to the whole context unless the bridge is confined to the top frame's trusted origin.74- **Followed links escape the trusted origin.** A WebView that follows links to arbitrary origins can navigate75 to an attacker page that then calls the bridge.76- **Methods that trust any caller are the sink.** A bridge method that performs a privileged action or returns77 data without checking the calling origin acts for whatever content invoked it.7879## Worked example (a confirm and a kill)8081> **Confirm.** A WebView exposes a native method that returns an authentication token and follows links to82> arbitrary origins. Navigating the WebView to a benign attacker-controlled page over a followed link lets that83> page's script invoke the method and receive the token, on a test device with a test account. **Confirmed**84> native capability reachable from untrusted web content, `high`, remediation = expose the bridge only to85> app-authored content on a controlled origin, verify the calling origin in each native method, restrict WebView86> navigation and framing to controlled origins, and block insecure and mixed content.87>88> **Kill.** The same WebView loads only app-authored content from a controlled origin over a secure channel,89> restricts navigation so links to other origins open outside the bridge context, isolates third-party frames90> from the interface, and each native method verifies the calling origin before acting. No untrusted content91> reaches the bridge. **Killed**, `kill_reason` = "the bridge is reachable only by trusted confined content on a92> controlled origin and every method authorizes the caller; untrusted web content cannot invoke a native93> method."9495## Rationalizations to reject9697- *"We only load our own pages."* -> Confirm the WebView cannot navigate or frame elsewhere; a followed link,98 a redirect, or an embedded frame can bring untrusted content into the same context as the bridge.99- *"The bridge only exposes harmless methods."* -> Enumerate every exposed method; one that returns a token,100 reads a file, or performs an action is enough, and harmless methods can be chained.101- *"The connection is HTTPS."* -> A secure channel to a remote origin still runs remote script beside the102 bridge; transport security does not make the loaded origin trusted.103- *"A frame cannot reach our interface."* -> If the interface is exposed to the whole WebView context, a104 third-party frame's script can reach it unless the bridge confines itself to the trusted top origin.105- *"The method just returns data."* -> Returning app data to untrusted web script is disclosure; treat a data106 read as a sensitive method and authorize the caller.107108## Executing this in practice109110You need every native method the bridge exposes, what each does, and whether it verifies the calling origin,111plus what the WebView loads and whether navigation, framing, and content security confine it to controlled112origins. For each exposed method, decide whether untrusted content can reach it through a remote page, a113frame, a followed link, or a tampered channel. Reading the bridge exposure and the WebView's loading policy114settles most leads; loading benign untrusted content you control and invoking a sensitive method on a test115device settles the rest.116117## Related118119- `auditing-mobile-deeplink-trust` - a deep link that drives the WebView to load attacker content is one way120 untrusted content reaches the bridge, joining link trust to bridge exposure.121- `testing-postmessage-and-web-message-trust` - a bridge reached through cross-frame messaging shares the122 origin-verification failure that skill treats in the pure-web setting.123- `hunting-mobile-tls-pinning-and-trust-gaps` - content loaded over a channel an attacker can tamper with124 reaches the bridge, the transport-trust gap that skill covers.125- `auditing-electron-ipc-trust` - the desktop analogue, where a renderer bridges to native capability and the126 same caller-authorization question applies.127- [FINDING-SCHEMA.md](../../FINDING-SCHEMA.md) - source = the untrusted web content reaching the bridge, sink =128 the native method it invokes, evidence = benign attacker-controlled content invoking a sensitive native129 method on a test device.