From 43e700498b135cc6c337ff2bfeadf9b0819236b9 Mon Sep 17 00:00:00 2001 From: archipelago Date: Thu, 25 Jun 2026 18:13:52 -0400 Subject: [PATCH] fix(android): trust self-signed certs for the user's own node in WebView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Node apps (e.g. NetBird on :8087) terminate TLS with a self-signed cert so the dashboard gets a secure context (OIDC / window.crypto.subtle, #15). The WebView's default onReceivedSslError CANCELs untrusted certs, so those apps rendered blank in the companion — exactly the netbird "won't load in the webview" report. Override onReceivedSslError in both WebViewClients (kiosk + in-app browser) to proceed() only when the failing cert's host matches the connected node; reject everything else (no blanket trust). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../app/ui/screens/WebViewScreen.kt | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/Android/app/src/main/java/com/archipelago/app/ui/screens/WebViewScreen.kt b/Android/app/src/main/java/com/archipelago/app/ui/screens/WebViewScreen.kt index 54bcb02a..23cbc5a3 100644 --- a/Android/app/src/main/java/com/archipelago/app/ui/screens/WebViewScreen.kt +++ b/Android/app/src/main/java/com/archipelago/app/ui/screens/WebViewScreen.kt @@ -323,6 +323,26 @@ fun WebViewScreen( } } + // Node apps (e.g. NetBird) terminate TLS with a + // self-signed cert — the dashboard needs a secure + // context for OIDC/window.crypto.subtle (#15). The + // WebView default is to CANCEL untrusted certs, so + // those apps render blank. The user explicitly trusts + // their own node, so proceed for same-host certs only; + // reject anything else (don't blanket-trust the web). + override fun onReceivedSslError( + view: WebView?, + handler: android.webkit.SslErrorHandler?, + error: android.net.http.SslError?, + ) { + val u = error?.url + if (u != null && isSameHost(u, serverUrl)) { + handler?.proceed() + } else { + handler?.cancel() + } + } + override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest?, @@ -553,6 +573,23 @@ private fun InAppBrowser( canGoForward = view?.canGoForward() == true } + // Self-signed TLS on the node's apps (e.g. NetBird on + // :8087) would otherwise be cancelled by the WebView + // and render blank. Proceed for the user's own node + // (same host); reject any other untrusted cert. + override fun onReceivedSslError( + view: WebView?, + handler: android.webkit.SslErrorHandler?, + error: android.net.http.SslError?, + ) { + val u = error?.url + if (u != null && isSameHost(u, serverUrl)) { + handler?.proceed() + } else { + handler?.cancel() + } + } + override fun shouldOverrideUrlLoading( view: WebView?, request: WebResourceRequest?,