Security

    Android WebView addJavascriptInterface Security Risks

    An Android WebView diagram showing a JavaScript interface bridging page script to native methods, with the annotated methods highlighted.

    Android's addJavascriptInterface lets JavaScript in a WebView call methods on a native object, which is powerful and risky. On Android below API 17 it exposed every public method, so attacker-controlled JavaScript could use reflection to reach Runtime.exec and run arbitrary code, the flaw tracked as CVE-2012-6636. From API 17, only methods annotated with @JavascriptInterface are exposed, which narrows the attack surface but does not remove it. Any method you expose is still callable, so loading untrusted or interceptable content into such a WebView remains dangerous.

    Short answer

    addJavascriptInterface bridges JavaScript to a native object, and its risk depends on your API level and what content the WebView loads. Per the Android WebView reference, apps targeting API 17 and above only expose methods marked @JavascriptInterface, which closed the original reflection-to-RCE exploit (CVE-2012-6636) that affected older versions. The remaining risk is that any exposed method is callable by whatever JavaScript runs, so a WebView that loads untrusted or interceptable content can still be abused. Test only your own app on an isolated device, minimize the exposed surface, load first-party HTTPS content, and prefer a modern message channel as a safer bridge, in line with OWASP MASVS guidance.

    What addJavascriptInterface does

    addJavascriptInterface takes a native object and a name and injects that object into the WebView's JavaScript context under the given global name, so page scripts can call its methods as if they were JavaScript functions. It is used to let web content trigger native behavior, such as reading a value from the app or invoking a native feature, which is why hybrid apps reach for it.

    The power is also the problem. Once an object is exposed, any JavaScript running in that WebView can call the exposed methods, and the WebView does not distinguish between your own trusted page and any other script that ends up executing. The safety of the bridge therefore depends entirely on what content the WebView loads and how narrow the exposed surface is.

    How the exploit works

    Understood defensively so you can spot it in your own app, the classic exploit abused the fact that older Android exposed every public method of the injected object to JavaScript. That included inherited methods such as getClass(), so attacker-controlled script could call the object's getClass method and then use Java reflection to reach Runtime.getRuntime().exec(), executing arbitrary commands with the app's permissions.

    The delivery was the other half. Because the attack only needs JavaScript to run in the WebView, loading remote content over cleartext HTTP let a network attacker inject the malicious script through a man-in-the-middle, and a hostile ad or iframe could do the same. This combination, an over-exposed interface plus untrusted content, is what turned a convenience API into remote code execution, tracked as CVE-2012-6636.

    The API 17 boundary and @JavascriptInterface

    Android 4.2, API level 17, changed the rule: for apps targeting API 17 or higher, only methods explicitly annotated with @JavascriptInterface are visible to JavaScript. Unannotated methods, including getClass(), are no longer reachable, which closes the reflection path used by the original exploit. This is why the annotation is now required to expose anything at all.

    The target API level is the key limit. The protection applies when your app targets API 17 or above and runs on Android 4.2 or later, which covers essentially all current devices. If you were to target an API below 17, or run on a very old device, the old all-methods behavior applies and the classic exploit returns. In practice you should target a modern API and rely on the annotation, but treat it as narrowing the surface, not as making the bridge safe by itself.

    Is it still a risk on modern Android?

    Yes, in a narrower form. The reflection-to-RCE path is closed on modern Android, but every method you annotate with @JavascriptInterface is still callable by any JavaScript in the WebView. If one of those methods does something sensitive and the WebView can load untrusted or interceptable content, an attacker who gets script to run can still call it. The table below summarizes how exposure and risk change by version and content.

    Version or contentWhat JavaScript can reachRisk level
    Target below API 17All public methods, including via reflectionCritical, reflection to Runtime.exec
    Target API 17 and aboveOnly @JavascriptInterface methodsReduced, exposed methods still callable
    WebView loads untrusted or remote contentYour exposed bridge methodsHigh if content can be intercepted
    Trusted first-party HTTPS onlyYour exposed bridge methodsLower, keep the surface minimal

    The takeaway is that two things drive the real risk: your target API level, which decides whether reflection is possible, and the trustworthiness of the content, which decides whether hostile script can run at all. Control both, not just one.

    How to test your own WebView responsibly

    Test only your own app, on a device or emulator you control, in an isolated environment. Start by finding every addJavascriptInterface call and listing exactly which methods are annotated and what they do, since that is your real exposed surface. Confirm the WebView only loads first-party content over HTTPS and that mixed content is disabled.

    For dynamic checks, load a local test page into your own WebView and try calling the exposed bridge from JavaScript to confirm only the intended methods are reachable and behave safely. Tools such as Frida can help you observe the bridge on your own build, and OWASP MASTG describes WebView and JavaScript-interface tests in detail. Keep all of this scoped to software you own, with the goal of shrinking the exposed surface rather than attacking anything external.

    Remediation checklist

    Remediation is about necessity, a minimal surface, and trusted content. The checklist below captures the fixes that matter most, from removing the interface to hardening what the WebView loads.

    CheckActionDone?
    NecessityRemove addJavascriptInterface where it is not truly needed[ ]
    Minimal surfaceAnnotate only required methods, keep them few and harmless[ ]
    Content trustLoad first-party HTTPS only; disable mixed content[ ]
    WebView hardeningTurn off file access and universal access from file URLs[ ]
    Modern bridgePrefer an allow-listed message listener over a raw interface[ ]

    The single most effective step is to load only trusted first-party content over HTTPS into any WebView that has a JavaScript interface, with mixed content disabled so remote script cannot be injected. After that, keep the exposed methods as few and as harmless as possible, and remove the interface entirely wherever it is not truly needed.

    Safer alternatives

    Modern Android offers safer ways to bridge web and native than a broad JavaScript interface. The AndroidX WebViewCompat.addWebMessageListener lets you receive messages from specific, allow-listed origins over a structured channel, which gives you the communication you need without exposing arbitrary native methods to any script on the page.

    Where you only need to pass data one way, evaluateJavascript and a postMessage-style channel are often enough and expose far less. Choosing one of these over addJavascriptInterface reduces the surface by design, so even if untrusted content somehow runs, there is little for it to call. Treat addJavascriptInterface as a last resort for cases these alternatives cannot cover.

    Where this fits in a security scan

    A JavaScript interface exposed to a WebView that loads remote content is a classic finding a security review should surface, alongside cleartext traffic, weak WebView settings, and stored secrets. It is easy to miss by hand, because the risky combination is spread across an addJavascriptInterface call, the WebView's settings, and the URLs it loads.

    A scanner like PTKD.com analyzes your app build and reports findings ordered by severity and mapped to OWASP MASVS, which helps you see an exposed interface and weak WebView configuration in context rather than one line at a time. To be clear about the boundary: a scanner points to where the risk is, and you still remove or narrow the interface, lock down what the WebView loads, and choose a safer bridge in code.

    What to take away

    • addJavascriptInterface bridges JavaScript to a native object, and any exposed method is callable by whatever script runs in the WebView.
    • Below API 17 it exposed all public methods, enabling reflection to Runtime.exec and remote code execution, tracked as CVE-2012-6636.
    • From API 17, only @JavascriptInterface methods are exposed, which narrows but does not remove the risk.
    • The real risk is driven by your target API level and whether the WebView can load untrusted or interceptable content.
    • Load only first-party HTTPS content, minimize the exposed surface, prefer a message listener, and scan with PTKD.com.
    • #webview
    • #addjavascriptinterface
    • #android security
    • #owasp masvs
    • #cve-2012-6636

    Frequently asked questions

    How does the addJavascriptInterface exploit work?
    On Android below API 17, the injected object exposed every public method to JavaScript, including inherited ones like getClass(). Attacker-controlled script could call getClass() and use Java reflection to reach Runtime.getRuntime().exec(), running arbitrary commands with the app's permissions. Delivery relied on the WebView loading untrusted content, often over cleartext HTTP via a man-in-the-middle or a hostile ad. It is tracked as CVE-2012-6636.
    Does the @JavascriptInterface annotation make it safe?
    It closes the original exploit by exposing only annotated methods, so reflection through getClass() is no longer reachable, but it does not make the bridge safe by itself. Every method you annotate is still callable by any JavaScript in the WebView, so an exposed sensitive method plus untrusted content is still dangerous. Keep the surface minimal.
    What target API level removes the reflection exploit?
    Targeting API 17 (Android 4.2) or higher, while running on Android 4.2 or later, which covers essentially all current devices. At that level only methods annotated with @JavascriptInterface are visible to JavaScript. Targeting an API below 17, or running on a very old device, restores the old all-methods behavior and the classic exploit.
    Is addJavascriptInterface still a risk on modern Android?
    Yes, in a narrower form. The reflection-to-RCE path is closed, but every @JavascriptInterface method is callable by any script in the WebView. If such a method is sensitive and the WebView can load untrusted or interceptable content, an attacker who gets script to run can call it. Risk depends on your target API and the content trust.
    How do I test my own WebView interface responsibly?
    Test only your own app on a device or emulator you control. Find every addJavascriptInterface call, list the annotated methods and what they do, and confirm the WebView loads first-party HTTPS content with mixed content disabled. Load a local test page and call the bridge to verify only intended methods are reachable, following OWASP MASTG WebView tests.
    What is a safer alternative to addJavascriptInterface?
    The AndroidX WebViewCompat.addWebMessageListener, which receives messages from specific allow-listed origins over a structured channel without exposing arbitrary native methods. For one-way data, evaluateJavascript and a postMessage-style channel expose far less. These reduce the surface by design, so treat addJavascriptInterface as a last resort.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free