CVE-2026-0078 AI-generated analysis
platform/frameworks/base, DevicePolicyManagerService (device policy / global proxy)
DevicePolicyManagerService.setGlobalProxy now rejects proxySpec and exclusionList strings whose modified-UTF-8 encoding exceeds 65535 bytes (via PolicySizeVerifier.enforceMaxStringLength) before storing them in the admin's policy state.
Root cause
In DevicePolicyManagerService.setGlobalProxy, in the else branch (the branch that does not clear the fields), the service set admin.specifiesGlobalProxy = true and stored the caller-supplied proxySpec and exclusionList into admin.globalProxySpec and admin.globalProxyExclusionList without any size check. The new PolicySizeVerifier.countBytes documents the limit: a string whose modified-UTF-8 form is longer than 65535 bytes cannot have its length represented by a short (UTFDataFormatException "String more than 65535 UTF bytes long"). The material does not show the downstream serialization failure path itself.
How the fix works
- core/java/android/app/admin/PolicySizeVerifier.java (new file in the 14 and 17 commits): adds enforceMaxStringLength(String str, String argName), which calls a private countBytes(s, shortLength=true) that sums modified-UTF-8 byte lengths (1 byte for U+0001..U+007F, 2 bytes for U+0000 and up to U+07FF, 3 bytes otherwise) and throws UTFDataFormatException once the total exceeds 65535; enforceMaxStringLength converts that into IllegalArgumentException(argName + " too long").
- services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java: imports android.app.admin.PolicySizeVerifier; in setGlobalProxy's else branch, before admin.specifiesGlobalProxy/globalProxySpec/globalProxyExclusionList are assigned, calls PolicySizeVerifier.enforceMaxStringLength(proxySpec, "proxySpec") and, if exclusionList != null, PolicySizeVerifier.enforceMaxStringLength(exclusionList, "exclusionList"). Because the checks precede these assignments, an oversized value does not reach those fields.
- services/tests/servicestests/res/xml/device_admin_sample.xml: adds <set-global-proxy /> to the test admin's uses-policies (likely so the test admin holds the global proxy policy).
- services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java: adds testSetGlobalProxy_tooLongStrings, asserting IllegalArgumentException for a 65536-char proxy host and for a 65536-char exclusion list entry.
Completeness
- Covers exactly the two strings stored by setGlobalProxy (proxySpec and exclusionList) in the branch that stores them; the other branch only clears the fields to null.
- The limit enforced is 65535 modified-UTF-8 bytes, matching the short-length constraint described in countBytes; values at or below that are accepted unchanged.
- exclusionList is null-guarded before the check; proxySpec is passed without a guard. The if condition selecting the else branch is not shown in the diff, so whether proxySpec is always non-null there is not visible.
- The new PolicySizeVerifier on 14/17 contains only enforceMaxStringLength and countBytes; the imports of ModifiedUtf8, ComponentName, Bundle, Parcelable, PersistableBundle, ArrayDeque and Queue are unused by the shown code.
- Whether other string-valued device policies in DevicePolicyManagerService receive the same validation is not shown in the material.
Behavior changes
- DevicePolicyManager.setGlobalProxy now throws IllegalArgumentException ("proxySpec too long" or "exclusionList too long") when either string exceeds 65535 modified-UTF-8 bytes; before the fix no such check existed on this path.
- On rejection the admin's specifiesGlobalProxy, globalProxySpec and globalProxyExclusionList fields are not assigned by this branch.
Per major
- Android 14: same fix: commit fa2c8531ae6f in android-security-14.0.0_r28 adds core/java/android/app/admin/PolicySizeVerifier.java as a new file plus the import and DevicePolicyManagerService check (hunk at line ~8403) and tests; 8/8 patched lines present at android-security-14.0.0_r29.
- Android 15: adapted fix: commit 71bc705a2542 in android-security-15.0.0_r16 changes only DevicePolicyManagerService (hunk at line ~8576) and the two test files; it adds neither PolicySizeVerifier.java nor the import, implying both already exist on that branch (not shown); 8/8 lines present at android-security-15.0.0_r17.
- Android 16: adapted fix: commit 50cbf4422ac8 in android-security-16.0.0_r7 changes only DevicePolicyManagerService (hunk at line ~8643) and the two test files, adding neither PolicySizeVerifier.java nor the import (presumably pre-existing, not shown); 8/8 lines present at android-security-16.0.0_r8.
- Android 17: same fix: commit cf8446b51ae1 in android-17.0.0_r1 includes the new PolicySizeVerifier.java (same blob 3a1c34309bbc as the 14 version), the import, the DevicePolicyManagerService check (hunk at line ~8406) and tests; 8/8 lines present at android-security-17.0.0_r1.
Unknowns
- The exact downstream failure caused by an oversized stored proxySpec/exclusionList (which serializer consumes these ActiveAdmin fields and how it fails) is not shown; only the 65535-byte modified-UTF-8 limit is evidenced by countBytes and the test comment.
- The if condition guarding the else branch in setGlobalProxy is not shown, so whether proxySpec can be null when passed to enforceMaxStringLength is not visible.
- Why the 14 and 17 commits add PolicySizeVerifier.java as a new file while the 15 and 16 commits do not is not explained by the material.
- Whether other DevicePolicyManagerService string policies are validated with PolicySizeVerifier is not visible in the provided context.