CVE-2024-40662 AI-generated analysis
platform/frameworks/base, core/java/android/net/Uri.java (Uri.Builder)
Uri.Builder.scheme(String) in android.net.Uri now removes every "://" sequence from a non-null scheme before storing it, so a caller-supplied scheme can no longer carry that scheme delimiter into the built Uri.
Root cause
Uri.Builder.scheme(String scheme) assigned the argument directly to this.scheme with no validation. A scheme value containing "://" (for example "http://https://evil.com:/te:st/", the value used in the new test) was accepted and ended up in the built Uri's scheme and in its serialized "<scheme>://<authority>..." form. That form then holds extra delimiters ahead of the real authority set with authority(). The material does not show how a consumer misuses this.
How the fix works
- core/java/android/net/Uri.java: Uri.Builder.scheme(String) now branches on null. A non-null scheme is stored as scheme.replace("://", ""), which removes the occurrences of the three-character delimiter. A null scheme is still stored as null (relative Uri). The commit message says this narrow replacement was chosen over removing characters that are unsupported under IANA guidelines, because that could break apps that use custom schemes with asterisks.
- core/tests/coretests/src/android/net/UriTest.java: adds testSchemeSanitization (annotated @AsbSecurityTest(cveBugId = 261721900)). It builds a Uri with scheme "http://https://evil.com:/te:st/", authority "google.com" and path "one/way", then asserts that getScheme() is "httphttpsevil.com:/te:st/" and toString() is "httphttpsevil.com:/te:st/://google.com/one/way". The commit also adds the import android.platform.test.annotations.AsbSecurityTest.
- On Android 15, commit 003800764d61 (android-15.0.0_r1) changed an earlier scheme.replaceAll("://", "") to scheme.replace("://", ""). Its commit message says this optimized performance. The Android 14 backport e7af00cafb52 already uses the replace() form.
Completeness
- Only the exact sequence "://" is removed from the scheme. The new test shows that ':' and '/' stay in the stored scheme ("httphttpsevil.com:/te:st/"), so the scheme is still not limited to standard scheme characters.
- The patched code makes a single replace() call and does not repeat it until no "://" is left. Removing one occurrence can join a leftover ':' with a following "//" and form a new "://" in the stored value. The material does not show whether this matters for any consumer.
- In the diff, only Uri.Builder.scheme(String) changes. The other Builder setters (for example opaquePart, authority and path) are not modified.
Behavior changes
- Uri.Builder.scheme() silently changes its input. Any "://" substring is dropped, so getScheme() and toString() of the built Uri differ from the string supplied. Apps that pass a scheme containing "://" will see different output.
- No new exception or error code is introduced. Null schemes behave as before.
- On Android 15 the follow-up changed replaceAll to replace, which its commit message describes as a performance change. Because "://" contains no regex metacharacters, the result is the same (general platform knowledge).
Per major
- Android 14: same fix: DO NOT MERGE cherry-pick e7af00cafb52 landed in android-security-14.0.0_r12 (replace() form plus UriTest.testSchemeSanitization). At android-security-14.0.0_r29, 8/8 lines of the patched region are present.
- Android 15: resolved in the android-15.0.0_r1 base. Commit 003800764d61 switched an earlier replaceAll("://", "") to replace("://", ""). At android-security-15.0.0_r17, 3/4 lines of the patched region are present. The material does not show why one line differs.
- Android 16: not affected (not listed by the bulletin). At android-security-16.0.0_r8, 8/8 lines of the patched region are present.
- Android 17: not affected (not listed by the bulletin). At android-security-17.0.0_r1, 8/8 lines of the patched region are present.
Unknowns
- Which system component or privileged consumer uses Builder-produced URIs in a way that turns the delimiter injection into EoP. The material only shows the library-level fix and the unit test.
- Why the Android 15 security tag reports only 3/4 lines of the patched region present.
- Whether Google considered that a single replace() call can leave a re-formed "://" for crafted inputs.