Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
Mountain View desk6 min

Android WebView Security in Kotlin: A Safe Wrapper Design

A security-first Kotlin WebView design keeps JavaScript and native access limited, serves packaged assets through AndroidX WebKit, and controls every navigation destination.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A secure Kotlin WebView wrapper starts by deciding exactly which content it may display. Keep navigation on HTTPS destinations you control, leave JavaScript off unless a page needs it, serve packaged files through AndroidX WebKit’s WebViewAssetLoader, and omit a JavaScript-to-native bridge unless there is a specific need. These choices define what page code can do inside your app.

Set the content boundary before building the WebView

A WebView is a browser-like environment running inside your app. Its pages can execute JavaScript, and a native bridge can expose app capabilities to page code. Treat both the page origin and the destinations the user can reach as part of your app’s security boundary. Android recommends keeping WebView navigation within destinations the app controls and using an allowlist. Android’s WebView guide and security checklist describe these risks.

As an Amazon Associate I earn from qualifying purchases.

  • App-owned content: Prefer packaged assets or pages on a domain you control. This is the clearest fit for a wrapper.
  • A small set of third-party destinations: Allow only the exact HTTPS hosts the app needs. Decide explicitly whether any subdomains are trusted; do not treat a matching suffix as an exact host match.
  • Arbitrary or user-selected content: Do not show it in a WebView that has a privileged JavaScript bridge. Send destinations outside the trusted set to the user’s browser, or reject them.

Keep these cases separate in the design. A page that is safe to display without native capabilities may not be safe in a WebView that can call into the app.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Start with restrictive WebView settings

JavaScript is disabled by default. Keep it disabled for static pages; Android notes that JavaScript execution is off by default and advises against enabling it when unnecessary. If the content requires JavaScript, enable it only for that WebView and preserve the navigation boundary described below. Android’s security checklist explains the default.

val settings = webView.settings
settings.javaScriptEnabled = false
settings.allowFileAccess = false
settings.allowFileAccessFromFileURLs = false
settings.allowUniversalAccessFromFileURLs = false
settings.mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW

Set javaScriptEnabled to true only when required by the pages you have decided to trust. Do not turn on allowFileAccessFromFileURLs or allowUniversalAccessFromFileURLs; Android identifies these file-origin permissions as unsafe. Its in-app content guidance recommends setting file URL access flags to false for the strongest security. Avoid MIXED_CONTENT_ALWAYS_ALLOW; keeping pages and their subresources on HTTPS avoids weakening transport protections.

Serve packaged assets with WebViewAssetLoader

For HTML, CSS, JavaScript, and other files bundled with the app, use AndroidX WebKit’s WebViewAssetLoader rather than a file:// URL. It serves local app content under an HTTP(S)-style origin, which works with same-origin behavior. Android’s guide calls it a flexible, performant way to load in-app content. Read the local-content guide and check the API documentation for the AndroidX WebKit version selected by your project.

val assetLoader = WebViewAssetLoader.Builder()
    .addPathHandler(
        "/assets/",
        WebViewAssetLoader.AssetsPathHandler(this)
    )
    .build()

webView.webViewClient = object : WebViewClient() {
    override fun shouldInterceptRequest(
        view: WebView,
        request: WebResourceRequest
    ): WebResourceResponse? {
        return assetLoader.shouldInterceptRequest(request.url)
    }
}

webView.loadUrl(
    "https://appassets.androidplatform.net/assets/index.html"
)

The example maps the app’s packaged assets to /assets/ and loads the entry page from the documented appassets.androidplatform.net origin. Add other handlers only for content the app intentionally serves. Android documents that shouldInterceptRequest runs on a thread other than the main thread, so do not access or mutate view-system state there; keep handler work safe for that callback context. See Android’s local-content API guidance.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For generated HTML that does not need a full asset tree, use loadDataWithBaseURL() with an intentional base URL rather than defaulting to data: URLs. The base URL affects the page’s origin behavior, so choose it deliberately and do not use this as a way to grant untrusted content privileges.

Allow only intended navigation destinations

Check both the URI scheme and host. For a remote-content wrapper, an allowlist should contain exact approved HTTPS hostnames; decide whether subdomains are needed and enumerate or validate them intentionally. Reject unexpected schemes, hosts, and malformed URIs. Do not rely on a trusted initial URL alone: a page can navigate later, and a server can redirect.

A small navigation policy can follow this pattern. This example keeps the packaged asset origin in the WebView and hands other URLs to the browser only when they meet a separate HTTPS host allowlist. Replace the sample host with a host your app actually controls.

private val trustedRemoteHosts = setOf("content.example.com")

private fun isTrustedRemote(uri: Uri): Boolean =
    uri.scheme.equals("https", ignoreCase = true) &&
        uri.host?.lowercase() in trustedRemoteHosts &&
        uri.userInfo == null

private fun isAppAsset(uri: Uri): Boolean =
    uri.scheme.equals("https", ignoreCase = true) &&
        uri.host.equals("appassets.androidplatform.net", ignoreCase = true)

webView.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView,
        request: WebResourceRequest
    ): Boolean {
        val uri = request.url
        if (isAppAsset(uri) || isTrustedRemote(uri)) {
            return false
        }

        // Open only approved external HTTPS destinations in the browser.
        if (isTrustedRemote(uri)) {
            view.context.startActivity(Intent(Intent.ACTION_VIEW, uri))
        }
        return true
    }
}

The snippet is a policy outline, not a complete production client: as written, approved remote hosts remain in the WebView, while a disallowed URL is blocked. If your policy instead sends a particular approved destination to the browser, implement that decision explicitly and handle the possibility that no browser activity can open the URL. Do not put arbitrary rejected URLs into an external intent. For app assets, consider restricting paths as well as the asset host if only a subset should be reachable.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Redirect and subsequent-navigation behavior must be checked in the actual WebView configuration. Android’s security guidance discusses allowlisting and warns against letting users navigate outside the app’s control. Consult the WebView guide. Also block cleartext traffic through the app manifest or a network security configuration so an HTTP destination cannot become an unprotected exception to the policy.

Do not add a JavaScript bridge by default

If page content does not need native capabilities, do not install a bridge. Android warns that addJavascriptInterface() exposes the supplied object to every frame, including iframes, and provides no mechanism to verify the calling frame’s origin. Its WebView guide puts the rule plainly: “Therefore, don’t use addJavascriptInterface() unless you wrote all of the HTML and JavaScript that appears in your WebView.” Read the official guidance.

If a bridge is essential, keep it narrow and expose only low-risk operations. Do not use it to pass secrets or as a shortcut around sensitive permissioned operations. Keep untrusted pages out of that WebView, and remove the interface before loading content that is not fully controlled by the app. Android recommends keeping sensitive functionality in app code and providing user disclosure where relevant. See the security checklist.

Message channels are not automatically safe substitutes: specify an expected target origin instead of *, and validate incoming messages before acting. A message received from an unexpected sender must not trigger privileged app behavior. Android’s WebView documentation covers bridge and messaging risks.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep file selection and local data exposure narrow

A WebView file picker does not make the selected source trustworthy. If the app supports file selection, validate how selected URIs are handled and avoid making app-private files available to page scripts. Broad file access and loading untrusted local content can expose data or create code-execution risks; Android’s unsafe file inclusion guidance describes the issue. Only add file access behavior for a concrete user need, and keep it separate from any privileged bridge.

Test the boundary, not just the happy path

Android API levels, target-SDK effects, AndroidX WebKit APIs, and WebView provider behavior can change. Test the app’s actual minimum Android version, target SDK, and WebView provider versions represented among users. Include cases that exercise the trust decisions rather than checking only that the first page loads:

  • Load the packaged entry page and verify its assets resolve through the asset loader.
  • Try an allowed HTTPS host, a lookalike or unlisted host, a non-HTTPS scheme, and a URL with unexpected credentials.
  • Test server redirects and links or scripts that initiate later navigation, not only the initial URL.
  • Include iframe behavior and any JavaScript bridge or message-channel interactions if those features exist.
  • Verify cleartext requests fail and that a blocked destination cannot gain access through file URLs or mixed content.
  • If file selection is supported, confirm the app handles returned URIs without exposing private files to page code.

These checks are particularly important when changing WebView providers or app target settings, because behavior may vary across deployed configurations.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.