CVE-2025-32333 AI-generated analysis
platform/packages/apps/Settings, SPA navigation, src/com/android/settings/spa/SpaActivity.kt
Settings' SpaActivity.startSpaActivityForApp now rejects an intent data scheme-specific part that does not match a Java-style package name regex before putting it into the SPA navigation destination string. For malformed values it returns false and launches no activity.
Root cause
In SpaActivity.kt, Context.startSpaActivityForApp(destinationPrefix, intent) used intent.data?.schemeSpecificPart as the package name. It then built the destination "$destinationPrefix/$packageName/${UserHandle.myUserId()}" without checking that value. A scheme-specific part containing characters such as '/' or '#' would change the shape of the destination string passed to startSpaActivity, instead of standing in as a plain package name. The added test uses "package:package.name/10#". How the destination is then parsed is not shown.
How the fix works
- src/com/android/settings/spa/SpaActivity.kt: Context.startSpaActivityForApp: the package name is now read via intent.data?.schemeSpecificPart?.takeIf { Regex("^([a-zA-Z]\\w*\\.)*[a-zA-Z]\\w*$").matches(it) }. If the value is absent or does not fully match (dot-separated segments, each starting with a letter followed by [A-Za-z0-9_]), the function returns false before calling startSpaActivity. No destination string is built and no activity is started.
- tests/spa_unit/src/com/android/settings/spa/SpaActivityTest.kt: adds startSpaActivityForApp_hasMalformedPackageName. It passes data "package:package.name/10#" and verifies that context.startActivity is never called.
Completeness
- The check is applied only in startSpaActivityForApp. In the shown excerpt, that is the only function that builds a destination from intent data. Other callers of startSpaActivity in Settings are not shown.
- Context.startSpaActivity(destination) itself is still unvalidated and forwards whatever destination string it receives. Any caller that builds a destination from other external input (none is shown in the material) is not covered by this fix.
- The user segment comes from UserHandle.myUserId(), not from the intent. destinationPrefix is a caller-supplied parameter whose origin is not shown.
- The validation only checks format (regex). It does not check that the package exists or is visible to the caller.
Behavior changes
- startSpaActivityForApp returns false and launches nothing when the scheme-specific part: contains any character outside [A-Za-z0-9_.]; has a segment starting with a digit or underscore; has empty segments (leading, trailing or double dots); or is empty. Before the fix, such values were forwarded to startSpaActivity.
- Callers now get false for such intents. Their fallback behavior is not shown in the material.
Per major
- Android 14: same fix: commit 591ea09a63e5 in android-security-14.0.0_r22 (subject says 'for udc'; cherry-picked from two upstream changes). At android-security-14.0.0_r29, 7/8 lines of the patched region are present.
- Android 15: not affected per the bulletin. At android-security-15.0.0_r17, 5/8 lines of the patched region are present. The material does not show the code in this branch.
- Android 16: not affected per the bulletin (the bulletin lists 16-next, not 16). At android-security-16.0.0_r8, 5/8 lines are present. The material does not show the code in this branch.
- Android 17: not affected per the bulletin. At android-security-17.0.0_r1, 5/8 lines are present. The material does not show the code in this branch.
Unknowns
- Which Settings entry points call startSpaActivityForApp, and with what destinationPrefix.
- How startSpaActivity/BrowseActivity parses the destination route, and so what a malformed segment could change.
- What the two upstream changes in the cherry-pick chain contain, and what code the Android 15/16/17 branches have in this region.