refactor(android): move cleartext opt-out into a networkSecurityConfig — #2439
android / Build + lint + test (push) Successful in 3m46s

`android:usesCleartextTraffic="true"` sat on <application> as a bare opt-out of
the platform's network-security default, with nothing recorded about why. It's
now a res/xml/network_security_config.xml carrying the same permission and the
reasoning behind it.

Behaviour is unchanged. networkSecurityConfig supersedes the attribute on API
24+ and our minSdk is 26, so the attribute is removed rather than kept
alongside.

Cleartext stays permitted because two independent things need it, and neither
can be narrowed to a domain list:

- The Minstrel server's host is user-entered at runtime, and plenty of
  self-hosters run plain HTTP on a LAN.
- UPnP/DLNA/Sonos — device-description and SOAP control URLs arrive in SSDP
  responses at runtime and are plain HTTP essentially always. This one wasn't in
  the original ticket, which only considered the server; it independently rules
  out the "tighten it later to RFC1918" idea, since <domain-config> matches
  literal hostnames, not CIDR ranges, and renderer IPs are unknowable ahead of
  time.

Trust anchors deliberately left at the platform default. Adding
<certificates src="user" /> would let self-hosters use HTTPS with a private CA —
which Mihon does, and which suits this product — but it also trusts every CA on
the device including a corporate MITM proxy. Raised separately rather than
assumed as a default.

tools:ignore="InsecureBaseConfiguration" mirrors Mihon's config and keeps
lintVitalRelease quiet about a choice that is deliberate and now documented.
This commit is contained in:
2026-08-05 08:41:05 -04:00
parent 1bf0e388cb
commit 2e1a8a62d8
2 changed files with 39 additions and 1 deletions
+1 -1
View File
@@ -28,9 +28,9 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/Theme.Minstrel"
android:usesCleartextTraffic="true"
tools:targetApi="34">
<!-- Portrait-locked until a tablet/landscape layout exists.
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Replaces a bare android:usesCleartextTraffic="true" on <application> (#2439).
Cleartext is still permitted app-wide, and it has to be. Two independent
reasons, neither of which can be narrowed to a domain list:
1. The Minstrel server's host is entered by the user at runtime. Plenty of
self-hosters run it over plain HTTP on a LAN; refusing that would break
real installs rather than secure anyone.
2. UPnP / DLNA / Sonos. Device-description and SOAP control URLs arrive in
SSDP responses at runtime and are plain HTTP essentially without
exception — see player/output/upnp/{UpnpDiscoveryController,SoapClient}.
A <domain-config> would be the way to scope this, but it matches literal
hostnames rather than CIDR ranges, and both sets of hosts above are unknowable
until runtime. So a permissive base-config is an honest description of our
situation — the gain over the manifest attribute is that the reasoning now
lives somewhere, and there is one place to tighten if a future settings screen
can distinguish a LAN server from a WAN one.
Worth stating because it looks worse than it is: this is NOT a tamper risk for
the in-app updater. An APK altered in transit and re-signed is rejected by the
platform as a signature mismatch on update, so the boundary there is enforced
regardless of transport.
Trust anchors are deliberately left at the platform default (system CAs only).
Adding <certificates src="user" /> would let self-hosters use HTTPS with their
own private CA — attractive for this product, and what Mihon does — but it
also makes the app trust every CA on the device, including a corporate MITM
proxy. That's an operator decision, not a default worth assuming.
-->
<network-security-config xmlns:tools="http://schemas.android.com/tools">
<base-config
cleartextTrafficPermitted="true"
tools:ignore="InsecureBaseConfiguration" />
</network-security-config>