CVE-2025-26443 AI-generated analysis
platform/packages/apps/ManagedProvisioning, terms HTML rendering (common/HtmlToSpannedParser, links handled via WebActivity per class javadoc)
HtmlToSpannedParser in ManagedProvisioning now rejects any URLSpan whose URL is not http:// or https:// (returning null for the whole parsed text) before handing the URL to UrlIntentFactory, so links embedded in the TermsActivity HTML can no longer produce intents for other schemes.
Root cause
In src/com/android/managedprovisioning/common/HtmlToSpannedParser.java, the parse method iterated all URLSpan objects in the Html.fromHtml result and passed urlSpan.getURL() straight to mUrlIntentFactory.create(), using any non-null intent for the span. It did not check the URL scheme, so links with non-web schemes produced intents. The commit message states this allowed an app to be installed via a link embedded in the TermsActivity.
How the fix works
- HtmlToSpannedParser.java (URLSpan loop in the parse method): the URL is read into a local `url`, and `isValidURL(url)` runs before `mUrlIntentFactory.create(url)`. If the check fails, the code logs `ProvisionLogger.logw("Invalid URL provided. Only HTTP and HTTPS URLs are allowed.")` and the method returns null at once, so no Spanned is produced for that HTML.
- HtmlToSpannedParser.java: adds a new private helper `isValidURL(String url)` that returns `URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)`, plus a new import of `android.webkit.URLUtil`.
- The fix listed for Android 16 is a different commit (5d67902f6a74, DisclaimersParserImpl.java). It adds `validateUriSchemeAndPermission(Uri)`: the disclaimer content Uri must use the scheme `content` or `android.resource`, and `mContext.checkUriPermission(uri, Binder.getCallingPid(), Binder.getCallingUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)` must be granted. Otherwise a SecurityException is caught and that disclaimer is skipped. This hardening is separate from the HtmlToSpannedParser scheme check.
Completeness
- Covers every URLSpan in the Html.fromHtml result inside HtmlToSpannedParser, which is the only place in the diff where URLs become intents. A single non-http(s) link drops the entire result (return null); the span is not just left unclickable.
- The validation is a scheme allow-list via URLUtil.isHttpUrl/isHttpsUrl. It does not check host or path.
- The fix does not touch the UrlIntentFactory or ClickableSpanFactory implementations, or WebActivity. Whether other code paths turn terms links into intents is not shown.
- The DisclaimersParserImpl Uri scheme/permission check seen on Android 16 is not part of the Android 14/15 commits shown.
Behavior changes
- HTML containing any link whose URL is not http:// or https:// now makes HtmlToSpannedParser return null instead of a Spanned with clickable links.
- A warning is logged via ProvisionLogger.logw when an invalid URL is found.
- On Android 16 (separate commit): a disclaimer is skipped with an error log if its content Uri is not content: or android.resource:, or if the calling pid/uid cannot read it.
Per major
- Android 14: Same fix: commit 69a363847696 in android-security-14.0.0_r21, a cherry-pick of 0eb898e8737f (Change-Id I58a5f31812ec5e1ae5675f959201d4237c888ee3) that changes only HtmlToSpannedParser.java. At android-security-14.0.0_r29, 7 of the 8 lines of the patched region are present; the material does not show which line differs.
- Android 15: Same fix: commit a3172895010e in android-security-15.0.0_r9, with a diff identical to the Android 14 commit. At android-security-15.0.0_r17, 7 of the 8 lines are present.
- Android 16: Resolved in base (android-16.0.0_r2). The HtmlToSpannedParser patched region is fully present (8 of 8 lines) at android-security-16.0.0_r8. The fix listed for Android 16 is a different change, 5d67902f6a74 in DisclaimersParserImpl.java (Uri scheme and caller URI-permission validation).
- Android 17: Not affected: the bulletin does not list Android 17. At android-security-17.0.0_r1, 7 of the 8 lines of the HtmlToSpannedParser patched region are present.
Unknowns
- Which line of the 8-line patched region differs at the latest 14, 15 and 17 security tags.
- Whether the DisclaimersParserImpl change (Android 16) was also applied to 14/15, and whether it is formally part of this CVE.
- The name of the HtmlToSpannedParser method that contains the URLSpan loop, and how callers (TermsActivity) handle the new null return.
- Where the terms HTML comes from (for example, whether it comes from EXTRA_PROVISIONING_DISCLAIMERS) and how a link click launches the intent.
- The concrete UrlIntentFactory implementation used in production.