Skip to content

fix: drop okhttp internal hostname verifier import, pin hostname verification, harden insurance test - #6928

Merged
AndyScherzinger merged 3 commits into
masterfrom
fix/noid/okhttp-internal-and-insurance-test-race
Oct 18, 2026
Merged

AndyScherzinger merged 3 commits into
masterfrom
fix/noid/okhttp-internal-and-insurance-test-race

Conversation

@AndyScherzinger

@AndyScherzinger AndyScherzinger commented Oct 17, 2026 •

Copy link
Copy Markdown
Member

Two follow-ups from the okhttp 5 update (#6500) and the flaky test fix (#6927), plus a test pinning hostname verification.

1. Stop importing okhttp's internal OkHostnameVerifier

RestModule wrapped okhttp3.internal.tls.OkHostnameVerifier, an internal okhttp class without compatibility guarantees that a later release may move or remove. The same default verifier is now read through the public OkHttpClient.hostnameVerifier(). In okhttp 5.5.0 OkHostnameVerifier is a Kotlin object and the client's default (OkHttpClient.Builder.hostnameVerifier), so the very same instance is wrapped as before and hostname verification is unchanged, including the wrapping by our TrustManager for user-accepted certificates.

The new RestModuleHostnameVerificationTest builds the client through RestModule.provideHttpClient and runs real certificates (okhttp-tls HeldCertificate) through its hostname verifier:

  • a certificate for the requested host is accepted
  • a certificate for another host, for a subdomain, or with the host only as common name is rejected
  • a certificate for another host is only accepted once the user trusted it via the certificate dialog (the existing TrustManager fallback)

Unlike TrustManagerTest, which mocks the default verifier, this fails if hostname verification is ever weakened, whether by an okhttp default or by the client setup. Checked by temporarily installing an accept-all verifier in RestModule: all four rejection tests fail.

2. Make the insurance request never() checks observe the IO thread

In OfflineFirstChatRepositoryTest, the insurance request reaches the network mock from ChatMessageSyncer's pull flow on Dispatchers.IO, which runCurrent() does not wait for. A never() check right after runCurrent() therefore passed even when a request had been started too early, as long as the IO thread had not reached the mock yet: the mirror image of the race fixed in #6927. The three checks now use after(LONG_POLLING_OBSERVATION_MILLIS).never(), so they watch for 200 ms before concluding that nothing was sent.

Verified by injecting a bug (insurance requests no longer skipped while paused, plus a 100 ms delay on the IO thread): the old test still passed, the new one fails as it should. Without the injected bug, the class passes repeatedly (about 0.6 s slower in total); ktlint and detekt are clean; gplay and generic compile.

🖼️ Screenshots

🏚️ Before 🏡 After
B A

🚧 TODO

  • Smoke test on a device: log in and open a chat on a server with a valid certificate and, if available, on one with a self-signed certificate you accept

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed
  • 🔖 Capability is checked or not needed
  • 🔙 Backport requests are created or not needed: /backport to stable-xx.x
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?)

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

RestModule wrapped okhttp3.internal.tls.OkHostnameVerifier, an internal
class without compatibility guarantees that a later okhttp release may
move or remove. Read the same default verifier through the public
OkHttpClient.hostnameVerifier() instead; in okhttp 5 it is
OkHostnameVerifier, so hostname verification is unchanged.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
The insurance request reaches the network mock from the pull flow on
Dispatchers.IO, which runCurrent() does not wait for. A never() check
right after runCurrent() therefore passed even when a request had been
started too early, as long as the IO thread had not reached the mock
yet. Verify with after(), so the check watches for a while before
concluding that nothing was sent.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
@AndyScherzinger AndyScherzinger added this to the 25.1.0 milestone Oct 17, 2026
TrustManagerTest covers our verifier wrapper with a mocked default
verifier only. Build the client through RestModule.provideHttpClient
and run real certificates through its hostname verifier: a certificate
for another host, a subdomain or with the host only as common name is
rejected, and a mismatching one is only accepted once the user trusted
it. This fails if hostname verification is ever weakened, whether by
an okhttp default or by the client setup.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
@AndyScherzinger AndyScherzinger changed the title fix: drop okhttp internal hostname verifier import and harden insurance request test fix: drop okhttp internal hostname verifier import, pin hostname verification, harden insurance test Oct 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📱 QA build

Download app-qa-debug.apk
QR code Open the QR code for this download
Commit 1a0e9b1
Version 6928
Available until 7 days after this build

The QA build installs alongside a released Nextcloud app, so you can keep
using your existing install while testing.

Downloading the file requires a GitHub account, so open this link on the
device you want to test on, or transfer the APK to it.

@github-actions

Copy link
Copy Markdown
Contributor

Codacy

Lint

TypemasterPR
Warnings138138
Errors1515

SpotBugs

CategoryBaseNew
Bad practice77
Correctness88
Dodgy code4040
Internationalization33
Malicious code vulnerability33
Performance88
Security1111
Total8080

@AndyScherzinger
AndyScherzinger merged commit 4db681c into master Oct 18, 2026
20 of 22 checks passed
@AndyScherzinger
AndyScherzinger deleted the fix/noid/okhttp-internal-and-insurance-test-race branch October 18, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant