openclaw - 💡(How to fix) Fix Android: Gateway TLS handshake fails on SDK 36 with domain-specific network security config [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#59090Fetched 2026-04-08 02:28:46
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

On Android 16 (SDK 36), the gateway TLS handshake fails immediately during onboarding when connecting via a Tailscale .ts.net domain. The app never reaches the pairing stage — the connection is rejected at the TLS layer before any data is exchanged.

Error Message

Gateway error: Domain specific configurations require that hostname aware
checkServerTrusted(X509Certificate[], String, String) is used

Root Cause

The app defines domain-specific rules in network_security_config.xml:

<domain-config cleartextTrafficPermitted="true">
  <domain includeSubdomains="true">ts.net</domain>
</domain-config>

When a domain-config block is present, Android's network security policy requires the TrustManager to implement the hostname-aware 3-parameter overload:

checkServerTrusted(X509Certificate[] chain, String authType, String hostname)

However, GatewayTls.kt creates anonymous X509TrustManager objects (line 44 for the main trust manager, and line ~96 for the probeGatewayTlsFingerprint trust-all manager). X509TrustManager only defines the 2-parameter checkServerTrusted(chain, authType), which Android rejects at handshake time for domain-scoped connections.

This is not specific to Tailscale — any gateway address matching a domain-config entry in network_security_config.xml will trigger the same failure.

Code Example

Gateway error: Domain specific configurations require that hostname aware
checkServerTrusted(X509Certificate[], String, String) is used

---

<domain-config cleartextTrafficPermitted="true">
  <domain includeSubdomains="true">ts.net</domain>
</domain-config>

---

checkServerTrusted(X509Certificate[] chain, String authType, String hostname)
RAW_BUFFERClick to expand / collapse

Summary

On Android 16 (SDK 36), the gateway TLS handshake fails immediately during onboarding when connecting via a Tailscale .ts.net domain. The app never reaches the pairing stage — the connection is rejected at the TLS layer before any data is exchanged.

Error

Gateway error: Domain specific configurations require that hostname aware
checkServerTrusted(X509Certificate[], String, String) is used

Environment

  • Device: Samsung SM-S921N (Galaxy S25)
  • Android: 16 (SDK 36)
  • App version: 2026.4.1-dev
  • Gateway address: https://<hostname>.ts.net
  • Route: Tailscale

Root Cause

The app defines domain-specific rules in network_security_config.xml:

<domain-config cleartextTrafficPermitted="true">
  <domain includeSubdomains="true">ts.net</domain>
</domain-config>

When a domain-config block is present, Android's network security policy requires the TrustManager to implement the hostname-aware 3-parameter overload:

checkServerTrusted(X509Certificate[] chain, String authType, String hostname)

However, GatewayTls.kt creates anonymous X509TrustManager objects (line 44 for the main trust manager, and line ~96 for the probeGatewayTlsFingerprint trust-all manager). X509TrustManager only defines the 2-parameter checkServerTrusted(chain, authType), which Android rejects at handshake time for domain-scoped connections.

This is not specific to Tailscale — any gateway address matching a domain-config entry in network_security_config.xml will trigger the same failure.

Impact

  • Pairing is impossible over any route that matches a domain-config rule (currently ts.net and openclaw.local).
  • openclaw devices list shows no pending pairing request because the TLS handshake fails before the HTTP/WebSocket layer is reached.
  • The error message is not actionable for end users.

Proposed Fix

Replace X509TrustManager with X509ExtendedTrustManager in two locations in GatewayTls.kt:

  1. buildGatewayTlsConfig trust manager (main connection) — implement the Socket and SSLEngine overloads for both checkServerTrusted and checkClientTrusted, delegating to the same fingerprint verification logic.
  2. probeGatewayTlsFingerprint trust-all manager (fingerprint probe) — implement the same overloads as no-ops.

X509ExtendedTrustManager extends X509TrustManager, so the change is backwards-compatible with OkHttpClient.sslSocketFactory() which accepts X509TrustManager.

No changes are needed to network_security_config.xml itself.

Reproduction Steps

  1. Set up a gateway accessible via a .ts.net Tailscale hostname
  2. Install the Android app on a device running Android 16 (SDK 36)
  3. Start onboarding and enter the .ts.net gateway address
  4. Observe the TLS error on the final connection check screen

Additional Context

This likely affects all Android 14+ devices (SDK 34+) where domain-specific network security configurations trigger stricter TLS validation, but was confirmed on SDK 36. Older SDK versions may silently fall back to the 2-parameter method.

extent analysis

TL;DR

Replace X509TrustManager with X509ExtendedTrustManager in GatewayTls.kt to support hostname-aware TLS validation.

Guidance

  • Identify the locations in GatewayTls.kt where X509TrustManager is used (lines 44 and ~96) and replace it with X509ExtendedTrustManager.
  • Implement the Socket and SSLEngine overloads for checkServerTrusted and checkClientTrusted in the main connection trust manager, delegating to the existing fingerprint verification logic.
  • Implement the same overloads as no-ops in the probeGatewayTlsFingerprint trust-all manager.
  • Verify that the TLS handshake succeeds after making these changes by retrying the onboarding process.

Example

// Example implementation of X509ExtendedTrustManager
public class CustomTrustManager extends X509ExtendedTrustManager {
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) {
        // Delegate to existing fingerprint verification logic
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {
        // Delegate to existing fingerprint verification logic
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) {
        // No-op for client trust
    }

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine engine) {
        // No-op for client trust
    }
}

Notes

This fix is specific to Android 14+ devices (SDK 34+) where domain-specific network security configurations trigger stricter TLS validation. Older SDK versions may not require this change.

Recommendation

Apply the proposed fix by replacing X509TrustManager with X509ExtendedTrustManager in GatewayTls.kt, as this will enable hostname-aware TLS validation and resolve the TLS handshake failure.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING