addJavaScriptInterface is one of the most powerful and most dangerous calls in an Android WebView, because it hands JavaScript running in the page a door into your native code. That is exactly what you want when the page is your own trusted content, and a serious vulnerability when the WebView can load anything else. The combination of a JavaScript interface and untrusted web content is how a WebView turns into remote access to your app. Here is what the call does, why it is risky, and how to use a bridge without opening that door.
Short answer
addJavaScriptInterface exposes the methods of a native object to JavaScript running in an Android WebView, creating a bridge from web content into your app's native code. Per Android's WebView documentation, this is safe only when the WebView loads content you fully control, because if it loads untrusted or remote content, malicious JavaScript can call your exposed native methods. Since Android 4.2 only methods annotated @JavascriptInterface are exposed, which closed an older remote-code-execution hole, but the bridge is still dangerous with untrusted content. So expose a JavaScript interface only to trusted content, keep the surface minimal, and never combine a bridge with loading arbitrary web pages.
What you should know
- It bridges JS to native code: web JavaScript can call your exposed methods.
- Safe only for trusted content: the page must be content you control.
- Untrusted content is the danger: malicious JS can reach native functions.
- @JavascriptInterface is required: since Android 4.2, only annotated methods are exposed.
- Keep the surface minimal: expose as little as possible, or nothing.
What does addJavaScriptInterface do?
It makes a native object callable from JavaScript inside the WebView. When you register an object with addJavaScriptInterface, the methods you annotate with @JavascriptInterface become available to scripts running in the loaded page, so the web side can invoke native functionality, such as reading a value, triggering an action, or passing data back to the app. This is genuinely useful for a hybrid app whose WebView shows your own pages and needs to talk to native code. The risk is that the bridge does not care who wrote the JavaScript: any script executing in that WebView, including one injected into or served by untrusted content, can call the exposed methods just as your own page can. So the bridge is only as safe as the content you allow into the WebView.
Why is it risky?
Because it gives web content a path into native capabilities. The table shows where the risk sits.
| Setup | Risk |
|---|---|
| Bridge plus your own bundled content only | Low; you control the JavaScript |
| Bridge plus remote content you control over HTTPS | Moderate; depends on content integrity |
| Bridge plus untrusted or arbitrary web pages | High; malicious JS can call native methods |
| Bridge exposing sensitive native methods | High; the exposed surface is the attack surface |
The dangerous combination is a JavaScript interface plus a WebView that can load content you do not fully control, since any script there reaches your exposed methods. Before Android 4.2 the danger was worse, because all public methods were exposed and reflection allowed arbitrary code execution; the @JavascriptInterface requirement closed that specific hole, but exposing native methods to untrusted JavaScript is still a real vulnerability. Whatever you expose becomes the attack surface.
How do you use a WebView bridge safely?
Only bridge to content you control, and keep what you expose small. The safest design is to use addJavaScriptInterface only when the WebView loads your own trusted content, ideally bundled in the app or served from your backend over HTTPS, and never when it can navigate to arbitrary or user-supplied pages. Restrict navigation so the WebView cannot wander to untrusted origins, since content integrity is the whole basis of the bridge's safety. Expose the minimum set of methods through @JavascriptInterface, avoid exposing anything sensitive or powerful, and validate any data that crosses from JavaScript into native code. If a feature does not truly need a native bridge, consider not using one at all, since the safest interface is the one you did not expose. Enabling JavaScript and a bridge together is a deliberate choice that should match trusted content only.
What to watch out for
The first trap is enabling a JavaScript interface on a WebView that loads remote or user-controlled content, which lets foreign JavaScript call your native methods. The second is exposing a broad or sensitive set of methods, since the exposed surface is exactly what an attacker targets. The third is assuming the @JavascriptInterface annotation makes the bridge safe, when it only narrows what is exposed and does not vouch for the content. A pre-submission scan such as PTKD.com (https://ptkd.com) reads the compiled APK or AAB against OWASP MASVS and surfaces WebView configuration and JavaScript-interface usage, so you can confirm a bridge is not exposed to untrusted content before you ship. Restricting the content and the exposed surface is the fix.
What to take away
addJavaScriptInterfaceexposes native methods to JavaScript in a WebView, bridging web content into your app's native code.- It is safe only with content you fully control; combined with untrusted or remote content, malicious JavaScript can call your native methods.
- Since Android 4.2 only
@JavascriptInterface-annotated methods are exposed, but the bridge is still risky with untrusted content and a broad exposed surface. - Bridge only to trusted content, expose the minimum, validate inputs, and use a pre-submission scan such as PTKD.com to confirm your WebView is not exposed to untrusted pages.



