{
 "month": "2024-05",
 "generated": "2026-10-06T12:05+00:00",
 "majors": {
  "14": {
   "counts": {
    "announced": 8,
    "certain": 8,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2024-23706",
     "osv_id": "ASB-A-328068777",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "Critical",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Health Connect now rejects change-log token requests (and stored tokens) whose record-type set is empty, both in the framework ChangeLogTokenRequest constructor and in HealthConnectServiceImpl.getChangeLogToken / getChangeLogs. Previously the Builder documented that no record types meant all record types; getChangeLogToken now returns ERROR_INVALID_ARGUMENT in that case.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit. The essential parts are the two service-side isEmpty() checks and the IllegalArgumentException catch in HealthConnectServiceImpl, because the framework constructor check does not cover the unvalidated Parcel constructor.",
       "If getChangeLogs in the target branch has no IllegalArgumentException handler, consider adding one that maps to ERROR_INVALID_ARGUMENT. The diff does not show the existing catch blocks in getChangeLogs."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 11,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "change_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/HealthFitness",
       "sha": "6e6896c3fd8139779ff8d51a99ee06667e849d87",
       "tag": "android-security-14.0.0_r8",
       "provenance": "security_tag",
       "method": "change_id",
       "confidence": "certain",
       "evidence": "ref 6e6896c3fd81",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/HealthFitness"
     ]
    },
    {
     "cve": "CVE-2024-0024",
     "osv_id": "ASB-A-293602317",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "UserManagerService now truncates the user name and the seed account name and type to 500 characters at user creation, when seed account data is set, and when serializing the per-user XML, so an oversized string no longer causes the IOException that left user restrictions unwritten.",
      "confidence": "medium",
      "backport_notes": [
       "Single commit, self-contained in UserManagerService.java. Add the constant and the truncateString helper, then apply it at the serializer, the creation path and the seed account setter. The test uses createUserWithThrow and USER_TYPE_FULL_SECONDARY in the mocking test harness."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 8,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r4",
      "date": "2024-01-03",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r4",
      "date": "2024-01-03",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "b8331285ad4fbc62ef5f5486eee2fbd8aed29df2",
       "tag": "android-security-14.0.0_r4",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 119,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2024-0025",
     "osv_id": "ASB-A-279428283",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "ActivityManagerService.sendIntentSender no longer forwards the caller-supplied allowlistToken to a target IIntentSender that is not a PendingIntentRecord; it passes null instead and logs a Slog.wtf when a non-null token was supplied on that path.",
      "confidence": "high",
      "backport_notes": [
       "Single-hunk change in one file. The fix applies where the else branch of sendIntentSender calls target.send with the token parameter. Older branches may name it whitelistToken, as the commit title does. The material does not show whether ActivityManagerService.java already imports AppGlobals, Binder and Slog."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 5,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r4",
      "date": "2024-01-03",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r4",
      "date": "2024-01-03",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "2c3fb40bca6265fb0259763cb38a4bf5df8a009c",
       "tag": "android-security-14.0.0_r4",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 119,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2024-0043",
     "osv_id": "ASB-A-295549388",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The fix changes the four Companion Device profile role behaviors (App Streaming, Computer, Glasses, Watch) in PermissionController's role-controller so they skip granting and revoking notification access when the role controller is running in a managed (work) profile.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit. It relies only on the existing role-controller helpers UserUtils.isManagedProfile and NotificationUtils. Permission is a mainline module, so on devices that receive module updates the fix may arrive through the Permission module update rather than the platform tag (general platform knowledge).",
       "When backporting to a tree where the set of behavior classes differs, add the same managed-profile guard to the grant() and revoke() of each existing CompanionDevice*RoleBehavior that calls NotificationUtils."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r5",
      "date": "2024-02-05",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r5",
      "date": "2024-02-05",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Permission",
       "sha": "70d22f185f27718203fe6f7a03ecb0d786fe4860",
       "tag": "android-security-14.0.0_r5",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 86,
     "projects": [
      "platform/packages/modules/Permission"
     ]
    },
    {
     "cve": "CVE-2024-23705",
     "osv_id": "ASB-A-293602970",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds string-length limits for user name, seed account name/type and seed accountOptions so that an oversized PersistableBundle is dropped in UserManagerService.setSeedAccountData and rejected in ConfirmUserCreationActivity instead of being persisted, where per the PersistableBundle comment an over-long string makes the XML write throw.",
      "confidence": "high",
      "backport_notes": [
       "The service-side change depends on an existing truncateString helper and MAX_USER_STRING_LENGTH in UserManagerService (removed/re-signatured here) and on the new @hide constants in UserManager; the new PersistableBundle method is @hide and self-contained, so it can be added first. Expect to update any test asserting a 500-char user name.",
       "Bulletin lists 12, 12L and 13 as affected; the material only shows the Android 14 commit, so the older-branch adaptations are unknown here."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 5,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r7",
      "date": "2024-04-01",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r7",
      "date": "2024-04-01",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "147715e733e6a998295dc980d932bcf21392065a",
       "tag": "android-security-14.0.0_r7",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 30,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2024-23707",
     "osv_id": "ASB-A-316891059",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "SearchResultTrampoline in Settings now identifies the caller of its authorization check with Activity.getLaunchedFromPackage() instead of getCallingActivity(), and SearchFeatureProvider.verifyLaunchSearchResultPageCaller is changed to take the launching package name as a String.",
      "confidence": "high",
      "backport_notes": [
       "Single commit across four files. The interface signature change in SearchFeatureProvider must be applied together with SearchFeatureProviderImpl, SearchResultTrampoline, and any downstream or OEM SearchFeatureProvider implementations that override verifyLaunchSearchResultPageCaller(Context, ComponentName).",
       "When porting, check that the getLaunchedFromPackage() call in SearchResultTrampoline.onCreate is present, because one line of the patched region differs in the latest tags."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 5,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/apps/Settings",
       "sha": "f1d0079c91734168c150f839168544f407b17b06",
       "tag": "android-security-14.0.0_r8",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/apps/Settings"
     ]
    },
    {
     "cve": "CVE-2024-23708",
     "osv_id": "ASB-A-293301736",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "NotificationManagerService now puts system-package toasts ahead of pending non-system toasts in mToastQueue (behind the toast currently on screen and after any queued system toasts) instead of adding them at the end, and ClipboardService's \"pasted from clipboard\" warning toast changes from LENGTH_SHORT to LENGTH_LONG, so apps can no longer delay system toasts by filling the queue.",
      "confidence": "high",
      "backport_notes": [
       "Single commit. It uses ToastRecord.isSystemToast, the mIsCurrentToastShown field and the isSystemToast parameter of getToastRecord without adding them, so these must already exist in the target branch. The bulletin lists 12, 12L and 13 as affected, but the material has no commits for those branches.",
       "The new tests use the mService.isSystemUid / isSystemAppId test hooks and the setToastRateIsWithinQuota / setIfPackageHasPermissionToAvoidToastRateLimiting helpers in NotificationManagerServiceTest."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 7,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "b9f175fb1f5ccc5ccf9bfd666286061633bccab2",
       "tag": "android-security-14.0.0_r8",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2024-23709",
     "osv_id": "ASB-A-317780080",
     "source": "osv",
     "announced": "2024-05-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Clamps the per-frame sample count in the sonivox wavetable synthesizer to BUFFER_SIZE_IN_MONO_SAMPLES, both where it is computed (WT_CheckSampleEnd in eas_wtsynth.c) and in each engine routine that uses it (eas_wtengine.c), so the gain, interpolation and filter loops cannot run past the frame audio and mix buffers.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit. Its hunks only extend the existing b/26366256 if-blocks, so the tree must already have those <= 0 checks for them to apply cleanly. Otherwise, add the clamp after whatever numSamples validation exists in each of the six engine sites and in WT_CheckSampleEnd."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 5,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r8",
      "date": "2024-05-06",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/external/sonivox",
       "sha": "0205dff2273fd26ab00b4526a96793da79242644",
       "tag": "android-security-14.0.0_r8",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/external/sonivox"
     ]
    }
   ],
   "tags": [
    "android-security-14.0.0_r8"
   ],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 30,
    "first_ingested_tag": "android-security-14.0.0_r1",
    "latest_ingested_tag": "android-security-14.0.0_r30",
    "window_base_tag": "android-14.0.0_r1",
    "window_start": "2023-10-04",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {
    "CVE-2024-23706": {
     "cve": "CVE-2024-23706",
     "summary": "Health Connect now rejects change-log token requests (and stored tokens) whose record-type set is empty, both in the framework ChangeLogTokenRequest constructor and in HealthConnectServiceImpl.getChangeLogToken / getChangeLogs. Previously the Builder documented that no record types meant all record types; getChangeLogToken now returns ERROR_INVALID_ARGUMENT in that case.",
     "component": "platform/packages/modules/HealthFitness (Health Connect), change logs API: framework ChangeLogTokenRequest and service HealthConnectServiceImpl",
     "weakness": "Likely improper authorization from an empty-set-means-all default: the fix blocks empty record-type sets right before read-permission enforcement, which suggests per-type permission checks could be skipped for an empty set (inferred; the enforcer code is not shown).",
     "root_cause": "Before the fix, ChangeLogTokenRequest.Builder documented that if no record type was added the request \"includes all record types\". In HealthConnectServiceImpl.getChangeLogToken the data permission check is mDataPermissionEnforcer.enforceRecordIdsReadPermissions(request.getRecordTypesList(), attributionSource), and getChangeLogs calls enforceRecordIdsReadPermissions on changeLogsTokenRequest.getRecordTypes() from the stored token. The fix adds empty-set rejection immediately before both calls. Taken together, this suggests an empty record-type set could get a token covering all types without matching read-permission enforcement; the internals of the enforcer and of ChangeLogsRequestHelper are not in the material. The Parcel constructor ChangeLogTokenRequest(Parcel in) does no validation, so a client-side check alone would not be enough.",
     "fix_analysis": [
      "framework/java/android/health/connect/changelog/ChangeLogTokenRequest.java: the private constructor ChangeLogTokenRequest(Set<DataOrigin>, Set<Class<? extends Record>>) now throws IllegalArgumentException(\"Requested record types must not be empty\") when recordTypes.isEmpty(). The Builder.addRecordType Javadoc changes from \"If not set includes all record types\" to \"At least one record type must be set\".",
      "service/java/com/android/server/healthconnect/HealthConnectServiceImpl.java: getChangeLogToken: after throwExceptionIfDataSyncInProgress() and before mDataPermissionEnforcer.enforceRecordIdsReadPermissions(...), adds `if (request.getRecordTypes().isEmpty()) throw new IllegalArgumentException(...)`. This is the server-side check for requests arriving over Binder, including those deserialized through the unvalidated Parcel constructor.",
      "service/java/com/android/server/healthconnect/HealthConnectServiceImpl.java: getChangeLogToken: adds a `catch (IllegalArgumentException)` block. It sets HealthConnectException.ERROR_INVALID_ARGUMENT on the logger builder, logs via Slog.e and reports the error to the callback through tryAndThrowException(callback, e, ERROR_INVALID_ARGUMENT).",
      "service/java/com/android/server/healthconnect/HealthConnectServiceImpl.java: getChangeLogs: after ChangeLogsRequestHelper.getRequest(packageName, token.getToken()) resolves the stored TokenRequest, adds `if (changeLogsTokenRequest.getRecordTypes().isEmpty()) throw new IllegalArgumentException(...)` before enforceRecordIdsReadPermissions. This also rejects stored tokens with an empty record-type set.",
      "Tests: CTS tests that built `new ChangeLogTokenRequest.Builder().build()` now add record types (new TestUtils.getChangeLogTokenRequestForTestRecordTypes()). The host-side test testAppCanReadChangeLogsUsingDataOriginFilters in HealthConnectDeviceTest is removed. The commit message names a new test, testGetChangeLogToken_emptyRecordTypes_throwsException."
     ],
     "completeness": [
      "Both service paths that use record types from a change-log token now have the check: getChangeLogToken (request from the client) and getChangeLogs (record types read back from the stored token).",
      "The server-side check in getChangeLogToken sits before enforceRecordIdsReadPermissions, so an empty list never reaches the permission enforcement step.",
      "The framework-side check is only in the private Set-based constructor. The Parcel constructor ChangeLogTokenRequest(Parcel) is still unvalidated, and the service-side re-check covers that case.",
      "In the constructor the new isEmpty() check runs before Objects.requireNonNull(recordTypes), so a null recordTypes now fails in isEmpty() rather than in requireNonNull (functional nit).",
      "The diff adds a throw of IllegalArgumentException in getChangeLogs but no new catch block there. Whether getChangeLogs already handled IllegalArgumentException is not visible in the material.",
      "No other API (for example read or aggregate paths) is modified. The material does not show whether other request types use a similar empty-means-all default."
     ],
     "behavior_changes": [
      "ChangeLogTokenRequest construction with no record types now throws IllegalArgumentException on the client.",
      "HealthConnectManager.getChangeLogToken with an empty record-type set now fails with HealthConnectException.ERROR_INVALID_ARGUMENT instead of returning a token.",
      "getChangeLogs with a token whose stored record-type set is empty now throws IllegalArgumentException instead of returning change logs.",
      "API documentation change: at least one record type is required. The commit message acknowledges that developers who requested change logs without record types will no longer be able to.",
      "In getChangeLogToken, the service logger now records ERROR_INVALID_ARGUMENT for this case."
     ],
     "preconditions": [
      "Caller is an app that can reach HealthConnectServiceImpl.getChangeLogToken through the IHealthConnectService Binder interface. Per index search, the users found are CTS tests and the service itself, with nothing outside HealthFitness.",
      "Caller passes a ChangeLogTokenRequest with an empty record-type set (before the fix, the documented Builder default) and passes the other pre-checks in getChangeLogToken: foreground user, package name matches uid, API quota, no data sync in progress.",
      "Caller then calls getChangeLogs with the returned token."
     ],
     "per_major": {
      "14": "same fix: commit 6e6896c3fd81 (cherry-pick of cd228a3e21c9, Change-Id I5dd49131fbe5eaa8bc138be03550f7fc739786d9) in android-security-14.0.0_r8. At android-security-14.0.0_r29 the code context shows the checks in the ChangeLogTokenRequest constructor and in HealthConnectServiceImpl.getChangeLogToken, including the IllegalArgumentException catch; 6/8 patched-region lines match.",
      "15": "not affected (not listed by the bulletin); at android-security-15.0.0_r17, 6/8 lines of the patched region are present.",
      "16": "not affected (not listed by the bulletin); at android-security-16.0.0_r8, 6/8 lines of the patched region are present.",
      "17": "not affected (not listed by the bulletin); at android-security-17.0.0_r1, 3/8 lines of the patched region are present, and the material does not show whether an equivalent check exists in another form."
     },
     "backport_notes": [
      "Single self-contained commit. The essential parts are the two service-side isEmpty() checks and the IllegalArgumentException catch in HealthConnectServiceImpl, because the framework constructor check does not cover the unvalidated Parcel constructor.",
      "If getChangeLogs in the target branch has no IllegalArgumentException handler, consider adding one that maps to ERROR_INVALID_ARGUMENT. The diff does not show the existing catch blocks in getChangeLogs."
     ],
     "confidence": "medium",
     "unknowns": [
      "Whether getChangeLogs already caught IllegalArgumentException and mapped it to ERROR_INVALID_ARGUMENT (not in the diff).",
      "How enforceRecordIdsReadPermissions handles an empty list, and how ChangeLogsRequestHelper.getToken / getRequest expanded an empty record-type set when reading change logs.",
      "Which 2 of the 8 patched-region lines differ at android-security-14.0.0_r29, 15.0.0_r17 and 16.0.0_r8.",
      "Whether the Android 17 code keeps an equivalent check (3/8 patched lines present).",
      "Why the host-side test testAppCanReadChangeLogsUsingDataOriginFilters was removed.",
      "Whether other Health Connect request types use a similar empty-means-all default."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 11,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-0024": {
     "cve": "CVE-2024-0024",
     "summary": "UserManagerService now truncates the user name and the seed account name and type to 500 characters at user creation, when seed account data is set, and when serializing the per-user XML, so an oversized string no longer causes the IOException that left user restrictions unwritten.",
     "component": "platform/frameworks/base, services/core com.android.server.pm.UserManagerService (multi-user / user restrictions persistence)",
     "weakness": "Missing length validation on caller-supplied strings leading to a failed persistence write (improper handling of exceptional condition); restrictions not stored.",
     "root_cause": "The per-user XML serializer in UserManagerService wrote userData.seedAccountName, userData.seedAccountType and userInfo.name without any size limit. According to the commit message, extras too long to be serialized caused an IOException, and the restrictions were not written in the file. In the diff context the synchronized(mRestrictionsLock) block follows the TAG_NAME element in the same document. The result is a user created with no restrictions in place, observable after reboot per the commit test notes.",
     "fix_analysis": [
      "UserManagerService.java: adds constant MAX_USER_STRING_LENGTH = 500 and helper truncateString(String). The helper returns the input unchanged if it is null or at most 500 chars, else original.substring(0, 500).",
      "UserManagerService.java (user XML serializer): the ATTR_SEED_ACCOUNT_NAME and ATTR_SEED_ACCOUNT_TYPE attributes and the TAG_NAME text are now written through truncateString().",
      "UserManagerService.java (user creation path): computes truncatedName = truncateString(name) up front. It uses it for convertPreCreatedUserIfPossible(userType, flags, truncatedName, token) and for new UserInfo(userId, truncatedName, null, flags, userType).",
      "UserManagerService.java (method that sets seed account data): stores truncateString(accountName) and truncateString(accountType) into userData. seedAccountOptions is stored unchanged.",
      "UserManagerServiceTest.java: the new test testCreateUserWithLongName_TruncatesName creates a user with a 66000-char name via createUserWithThrow and asserts the name length is 500. A 'Test' name stays 4 chars."
     ],
     "completeness": [
      "Covers the three string values touched in the serializer (user name, seed account name, seed account type), both at write time and where they are set (creation, seed account data).",
      "The approach bounds the inputs. It does not change the ordering of the XML write or make the restrictions block resilient to a serialization failure.",
      "userData.seedAccountOptions is stored without a size check in the diff. Whether it is serialized in the same document is not shown."
     ],
     "behavior_changes": [
      "User names longer than 500 characters are silently truncated to 500 at creation. The returned UserInfo.name reflects the truncated value (the test asserts length 500).",
      "Seed account name and type longer than 500 characters are silently truncated when set and when persisted.",
      "No new error is reported to callers."
     ],
     "preconditions": [
      "Ability to trigger user creation or setting of seed account data with an oversized string. Per the commit message, this was done by creating an intent to create a user with extras too long to be serialized.",
      "Exact permission requirements of the triggering entry point are not shown in the material."
     ],
     "per_major": {
      "14": "same fix: commit b8331285ad4f in android-security-14.0.0_r4 (Change-Id I633dc10974a64ef2abd07e67ff2d209847129989). At android-security-14.0.0_r29, 7/8 lines of the patched region are present. The shown r29 context of UserManagerService.java does not show MAX_USER_STRING_LENGTH between USER_VERSION and EPOCH_PLUS_30_YEARS.",
      "15": "not affected (not listed by the bulletin); at android-security-15.0.0_r17, 7/8 lines of the patched region are present.",
      "16": "not affected (not listed by the bulletin); at android-security-16.0.0_r8, 7/8 lines of the patched region are present.",
      "17": "not affected (not listed by the bulletin); at android-security-17.0.0_r1, 7/8 lines of the patched region are present."
     },
     "backport_notes": [
      "Single commit, self-contained in UserManagerService.java. Add the constant and the truncateString helper, then apply it at the serializer, the creation path and the seed account setter. The test uses createUserWithThrow and USER_TYPE_FULL_SECONDARY in the mocking test harness."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which public API or intent path the triggering app used and what permission it required.",
      "The full list of fields serialized in the user XML (only the seed-data and name region is shown), so whether other oversized values could still abort the write is unknown.",
      "Which of the 8 patched lines is absent at the latest tags and why; the r29 context does not show MAX_USER_STRING_LENGTH at its original location."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 8,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-0025": {
     "cve": "CVE-2024-0025",
     "summary": "ActivityManagerService.sendIntentSender no longer forwards the caller-supplied allowlistToken to a target IIntentSender that is not a PendingIntentRecord; it passes null instead and logs a Slog.wtf when a non-null token was supplied on that path.",
     "component": "platform/frameworks/base, services/core ActivityManagerService (PendingIntent / IIntentSender dispatch)",
     "weakness": "Caller-supplied allowlistToken forwarded to a custom, possibly non-system IIntentSender target (improper handling of a security token; bulletin rates it EoP)",
     "root_cause": "In ActivityManagerService.sendIntentSender, when the target IIntentSender is not a PendingIntentRecord (the else branch, which the code comment describes as \"someone has given us their own custom IIntentSender ... this isn't really a PendingIntent\"), the code called target.send(code, intent, resolvedType, allowlistToken, null, requiredPermission, options) and passed the allowlistToken argument unchanged to the custom target. The code comment in the same branch notes that such an intent sender may come from outside the system, so the token could reach a party outside the system.",
     "fix_analysis": [
      "services/core/java/com/android/server/am/ActivityManagerService.java:sendIntentSender (non-PendingIntent else branch): the target.send(...) call now passes null in place of allowlistToken, so a custom IIntentSender never receives the token.",
      "Same location: if allowlistToken != null, the fix resolves the calling package via AppGlobals.getPackageManager().getNameForUid(Binder.getCallingUid()) under Binder.clearCallingIdentity()/restoreCallingIdentity(), then emits Slog.wtf(TAG, \"Send a non-null allowlistToken to a non-PI target...\") with the calling package, intent and options. The commit message says this logging is meant to detect whether real callers hit this case.",
      "The commit message combines two descriptions (\"Log to detect usage of whitelistToken when sending non-PI target\" and \"Do not pass whitelistToken when sending non-PI target\"). In the provided diff both are in a single RESTRICT AUTOMERGE cherry-pick (Change-Id I017486354a1ab2f14d0472c355583d53c27c4810)."
     ],
     "completeness": [
      "Covers only the non-PendingIntentRecord branch of sendIntentSender. The PendingIntentRecord branch (sendWithResult, for both originalRecord and the visible-background-user redirected newRecord) still passes allowlistToken on.",
      "The token is dropped no matter who the caller is. On this path there is no check or exception for system callers.",
      "The later finishedReceiver.performReceive(...) call in the same branch is unchanged.",
      "The Slog.wtf is diagnostic only; it does not reject the send."
     ],
     "behavior_changes": [
      "Custom (non-PendingIntent) IIntentSender targets now always receive a null allowlistToken from sendIntentSender.",
      "A Slog.wtf is logged whenever a non-null allowlistToken is passed to a non-PI target. This adds an IPackageManager.getNameForUid lookup performed with cleared calling identity. Slog.wtf produces a wtf report, typically recorded in DropBox (general platform knowledge)."
     ],
     "preconditions": [
      "A caller invokes ActivityManagerService.sendIntentSender with a non-null allowlistToken and a target IIntentSender that is not a PendingIntentRecord (an app-supplied IIntentSender implementation).",
      "The code path is reached through the IActivityManager binder interface. The material does not show which client APIs reach it with a non-null token."
     ],
     "per_major": {
      "14": "same fix: commit 2c3fb40bca62 in android-security-14.0.0_r4 (RESTRICT AUTOMERGE cherry-pick). At android-security-14.0.0_r29, 3/4 lines of the patched region are present, and the code shown there contains the null-token call and the wtf log.",
      "15": "not affected per the bulletin. At android-security-15.0.0_r17, 3/4 lines of the patched region are present (code not shown).",
      "16": "not affected per the bulletin. At android-security-16.0.0_r8, 3/4 lines of the patched region are present (code not shown).",
      "17": "not affected per the bulletin. At android-security-17.0.0_r1, 3/4 lines of the patched region are present (code not shown)."
     },
     "backport_notes": [
      "Single-hunk change in one file. The fix applies where the else branch of sendIntentSender calls target.send with the token parameter. Older branches may name it whitelistToken, as the commit title does. The material does not show whether ActivityManagerService.java already imports AppGlobals, Binder and Slog."
     ],
     "confidence": "high",
     "unknowns": [
      "How a recipient of the allowlistToken could use it; the material does not show the consumer side of the token.",
      "Which client-facing APIs reach sendIntentSender with a non-null allowlistToken and a custom IIntentSender.",
      "Whether the one unmatched line in later tags is only a formatting difference in the log statement or a further change.",
      "The exact content of the patched region in the 15, 16 and 17 tags."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 5,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-0043": {
     "cve": "CVE-2024-0043",
     "summary": "The fix changes the four Companion Device profile role behaviors (App Streaming, Computer, Glasses, Watch) in PermissionController's role-controller so they skip granting and revoking notification access when the role controller is running in a managed (work) profile.",
     "component": "platform/packages/modules/Permission, PermissionController role-controller (CompanionDevice*RoleBehavior)",
     "weakness": "Missing user/profile-type check before granting a privileged capability (notification access) as a side effect of a role grant",
     "root_cause": "CompanionDeviceAppStreamingRoleBehavior, CompanionDeviceComputerRoleBehavior, CompanionDeviceGlassesRoleBehavior and CompanionDeviceWatchRoleBehavior implemented RoleBehavior.grant() by always calling NotificationUtils.grantNotificationAccessForPackage(context, packageName), and revoke() by always calling NotificationUtils.revokeNotificationAccessForPackage(context, packageName). Neither checked which profile the role controller was running in. As a result, a package given one of these companion device profile roles in a managed (work) profile also got notification access there. The commit message states the intent: \"Do not grant notification access for work apps.\" The bulletin rates this as a High severity EoP.",
     "fix_analysis": [
      "CompanionDeviceAppStreamingRoleBehavior.java:grant and :revoke: obtain UserHandle user = Process.myUserHandle() and wrap the NotificationUtils.grantNotificationAccessForPackage / revokeNotificationAccessForPackage call in if (!UserUtils.isManagedProfile(user, context)). Imports for android.os.Process, android.os.UserHandle and com.android.role.controller.util.UserUtils are added.",
      "CompanionDeviceComputerRoleBehavior.java:grant and :revoke: identical change.",
      "CompanionDeviceGlassesRoleBehavior.java:grant and :revoke: identical change.",
      "CompanionDeviceWatchRoleBehavior.java:grant and :revoke: identical change.",
      "The check uses the user of the role controller process itself (Process.myUserHandle()), not a user passed in as a parameter. A role controller running in a managed profile therefore no longer changes notification access at all. UserUtils.isManagedProfile is an existing helper: the diff only adds its import, and its body is not shown."
     ],
     "completeness": [
      "Covers all four companion device profile role behaviors in this diff that call NotificationUtils: App Streaming, Computer, Glasses and Watch. Both grant() and revoke() are gated.",
      "revoke() is also skipped in a managed profile. Going by the code, notification access granted in a work profile before the fix would not be revoked by these behaviors when the role is later revoked. The commit contains no migration or one-time revocation logic.",
      "The gate depends only on managed-profile status. The material does not show how NotificationUtils or UserUtils behave, or whether other role behaviors grant notification access, so coverage beyond these four files cannot be judged."
     ],
     "behavior_changes": [
      "In a managed (work) profile, granting a Companion Device App Streaming, Computer, Glasses or Watch role to a package no longer grants it notification access.",
      "In a managed profile, revoking those roles no longer revokes notification access either.",
      "No change for users that are not managed profiles. No new error is raised: the calls are simply skipped."
     ],
     "preconditions": [
      "A package must be granted one of the companion device profile roles handled by CompanionDeviceAppStreamingRoleBehavior, CompanionDeviceComputerRoleBehavior, CompanionDeviceGlassesRoleBehavior or CompanionDeviceWatchRoleBehavior, with the role controller running in a managed (work) profile (UserUtils.isManagedProfile(Process.myUserHandle(), context) is true).",
      "How the role grant itself is triggered is not shown in the material."
     ],
     "per_major": {
      "14": "Same fix: commit 70d22f185f27 in android-security-14.0.0_r5 (cherry-picked from commit fd6c9ab8f4a5, Change-Id Ie6078a1081bf9f98466bfbf2bc0b54a7af7b4951). At android-security-14.0.0_r29, 8/8 lines of the patched region are present.",
      "15": "Not affected (not listed by the bulletin). At android-security-15.0.0_r17, CompanionDeviceAppStreamingRoleBehavior.java, CompanionDeviceComputerRoleBehavior.java and CompanionDeviceGlassesRoleBehavior.java are absent at the patched paths. The Watch file is not reported absent.",
      "16": "Not affected (not listed by the bulletin). At android-security-16.0.0_r8 the same three files are absent at the patched paths. The Watch file is not reported absent.",
      "17": "Not affected (not listed by the bulletin). At android-security-17.0.0_r1 the same three files are absent at the patched paths. The Watch file is not reported absent."
     },
     "backport_notes": [
      "Single self-contained commit. It relies only on the existing role-controller helpers UserUtils.isManagedProfile and NotificationUtils. Permission is a mainline module, so on devices that receive module updates the fix may arrive through the Permission module update rather than the platform tag (general platform knowledge).",
      "When backporting to a tree where the set of behavior classes differs, add the same managed-profile guard to the grant() and revoke() of each existing CompanionDevice*RoleBehavior that calls NotificationUtils."
     ],
     "confidence": "high",
     "unknowns": [
      "The implementations of UserUtils.isManagedProfile and NotificationUtils.grantNotificationAccessForPackage are not in the material, so the exact type of notification access granted is not shown.",
      "How the role grant is reached from an unprivileged context (the EoP path) is not shown.",
      "Why Android 15 and later are considered not affected is not shown. The material only shows that three of the four files are absent at the original paths.",
      "Whether CompanionDeviceWatchRoleBehavior.java in 15/16/17 still exists at that path and contains the managed-profile check."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-23705": {
     "cve": "CVE-2024-23705",
     "summary": "Adds string-length limits for user name, seed account name/type and seed accountOptions so that an oversized PersistableBundle is dropped in UserManagerService.setSeedAccountData and rejected in ConfirmUserCreationActivity instead of being persisted, where per the PersistableBundle comment an over-long string makes the XML write throw.",
     "component": "platform/frameworks/base, UserManagerService / UserManager / ConfirmUserCreationActivity (multi-user, seed account data)",
     "weakness": "Missing input length validation (improper input validation) on persisted user data, leading to a failed persistence step and a user created without its restrictions (per commit message)",
     "root_cause": "UserManagerService.setSeedAccountData stored the caller-supplied accountOptions PersistableBundle into userData.seedAccountOptions with no check on the length of its String keys/values (only seedAccountName/seedAccountType and the user name were truncated to a 500-char MAX_USER_STRING_LENGTH). The new PersistableBundle comment states that strings longer than 65535 characters cannot be saved to XML as part of a bundle and an IOException is thrown, so persisting the user record with an oversized bundle fails. Per the commit message, this resulted in a user being created with no restrictions. ConfirmUserCreationActivity also passed user name, account name, account type and accountOptions through without any length check.",
     "fix_analysis": [
      "core/java/android/os/PersistableBundle.java: new @hide isBundleContentsWithinLengthLimit(int limit) walks mMap after unparcel(); returns false if any key, String value, element of a String[] value, or (recursively) any nested PersistableBundle exceeds limit.",
      "core/java/android/os/UserManager.java: adds @hide constants MAX_USER_NAME_LENGTH = 100, MAX_ACCOUNT_STRING_LENGTH = 500, MAX_ACCOUNT_OPTIONS_LENGTH = 1000 and documents the limits in the createUserCreationIntent javadoc.",
      "services/core/java/com/android/server/pm/UserManagerService.java: removes MAX_USER_STRING_LENGTH; truncateString now takes a limit. setSeedAccountData truncates accountName/accountType to MAX_ACCOUNT_STRING_LENGTH and only assigns userData.seedAccountOptions when accountOptions != null && isBundleContentsWithinLengthLimit(MAX_ACCOUNT_OPTIONS_LENGTH); otherwise the assignment is skipped (seedAccountOptions is null in the test after clearSeedAccountData). The user XML serialization code truncates seed account name/type to 500 and user name to 100; the internal create-user method truncates name to MAX_USER_NAME_LENGTH (100).",
      "core/java/com/android/internal/app/ConfirmUserCreationActivity.java: checkUserCreationRequirements adds a branch after the cantCreateUser check: if mUserName > 100, mAccountName or mAccountType > 500, or mAccountOptions fails isBundleContentsWithinLengthLimit(1000), it sets result USER_CREATION_FAILED_NOT_PERMITTED, logs, and returns null (same handling as the cantCreateUser branch).",
      "Tests: UserManagerServiceTest adjusted to MAX_USER_NAME_LENGTH; UserManagerTest adds testAddUserAccountData_validStringValuesAreSaved_validBundleIsSaved and testAddUserAccountData_invalidStringValuesAreTruncated_invalidBundleIsDropped."
     ],
     "completeness": [
      "Covers the service entry point (setSeedAccountData) and the UI entry point (ConfirmUserCreationActivity); other paths, if any, are not visible in the material.",
      "isBundleContentsWithinLengthLimit bounds individual String key/value lengths (including String[] elements and nested bundles) but not the number of entries or the total serialized size of the bundle; non-String value types are not inspected.",
      "In the service the bundle is silently dropped (no log) rather than rejected with an error to the caller; name/type are truncated rather than rejected. The activity path rejects outright.",
      "Only the setSeedAccountData assignment of seedAccountOptions is guarded; the diff does not show any other writer of userData.seedAccountOptions, so whether others exist is not visible in the material."
     ],
     "behavior_changes": [
      "User name truncation limit lowered from 500 to 100 characters (internal create-user path and user XML serialization); existing test updated accordingly.",
      "setSeedAccountData: accountOptions containing any String key/value longer than 1000 chars is not stored (getSeedAccountOptions returns null in the test); accountName/accountType truncated to 500.",
      "ConfirmUserCreationActivity now sets USER_CREATION_FAILED_NOT_PERMITTED when any supplied property exceeds its limit, checked before the no-more-users check."
     ],
     "preconditions": [
      "Service path: a caller able to invoke UserManagerService.setSeedAccountData with an accountOptions PersistableBundle containing a very long String (permission requirements of that method are not shown in the material).",
      "UI path: supplying user name / account name / account type / accountOptions to ConfirmUserCreationActivity, which on confirmation calls mUserManager.createUser (per the shown context). The createUserCreationIntent javadoc, whose parameters match the activity's fields, says the current user should be an admin user."
     ],
     "per_major": {
      "14": "same fix: commit 147715e733e6 in android-security-14.0.0_r7 (cherry-pick of 33a90988cf3b); patched region fully present at android-security-14.0.0_r29 (8/8 lines).",
      "15": "not affected per the bulletin; the patched code is present at android-security-15.0.0_r17 (8/8 lines), i.e. the branch carries the fix.",
      "16": "not affected per the bulletin; patched code present at android-security-16.0.0_r8 (8/8 lines).",
      "17": "not affected per the bulletin; patched code present at android-security-17.0.0_r1 (8/8 lines)."
     },
     "backport_notes": [
      "The service-side change depends on an existing truncateString helper and MAX_USER_STRING_LENGTH in UserManagerService (removed/re-signatured here) and on the new @hide constants in UserManager; the new PersistableBundle method is @hide and self-contained, so it can be added first. Expect to update any test asserting a 500-char user name.",
      "Bulletin lists 12, 12L and 13 as affected; the material only shows the Android 14 commit, so the older-branch adaptations are unknown here."
     ],
     "confidence": "high",
     "unknowns": [
      "The exact failure mode by which an oversized bundle leaves the user without restrictions (the user XML write path and how a serializer exception is handled) is only indicated by the commit title and the PersistableBundle comment, not shown in the diff.",
      "Permission/caller requirements of setSeedAccountData and whether ConfirmUserCreationActivity is exported to untrusted apps are not shown.",
      "How the caller of checkUserCreationRequirements handles a null return is not shown.",
      "The corresponding commits for Android 12, 12L and 13 are not in the material."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 5,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-23707": {
     "cve": "CVE-2024-23707",
     "summary": "SearchResultTrampoline in Settings now identifies the caller of its authorization check with Activity.getLaunchedFromPackage() instead of getCallingActivity(), and SearchFeatureProvider.verifyLaunchSearchResultPageCaller is changed to take the launching package name as a String.",
     "component": "platform/packages/apps/Settings, search (SearchResultTrampoline / SearchFeatureProviderImpl)",
     "weakness": "Improper authorization based on an unreliable caller identity: the privilege check used getCallingActivity() (the component that will receive the activity result) rather than the package that actually launched the activity.",
     "root_cause": "SearchResultTrampoline.onCreate() called getCallingActivity() and passed the resulting ComponentName to SearchFeatureProviderImpl.verifyLaunchSearchResultPageCaller(). That method allowed the launch only if the package name was the Settings package, the SettingsIntelligence package (getSettingsIntelligencePkgName), or signature-allowlisted (isSignatureAllowlisted). The same ComponentName also drove isSettingsIntelligence(), which selects the launch path for the result page. Per the commit message, getCallingActivity() reports who will get the result of the Activity, not who launched it, so the identity the check relied on did not reliably reflect the launching package. getLaunchedFromPackage() reports who launched the Activity or built the PendingIntent used to launch it.",
     "fix_analysis": [
      "src/com/android/settings/search/SearchResultTrampoline.java:onCreate - replaces `final ComponentName callingActivity = getCallingActivity();` with `final String callerPackage = getLaunchedFromPackage();` and passes callerPackage to verifyLaunchSearchResultPageCaller(this, callerPackage) and to isSettingsIntelligence(callerPackage). The ComponentName import is dropped.",
      "src/com/android/settings/search/SearchResultTrampoline.java:isSettingsIntelligence - signature changed from (ComponentName callingActivity) to (String callerPackage). It is now simply TextUtils.equals(callerPackage, getSettingsIntelligencePkgName(this)), with the null check removed (TextUtils.equals handles null).",
      "src/com/android/settings/search/SearchFeatureProvider.java:verifyLaunchSearchResultPageCaller - interface signature changed to (@NonNull Context context, @NonNull String callerPackage).",
      "src/com/android/settings/search/SearchFeatureProviderImpl.java:verifyLaunchSearchResultPageCaller - takes the String callerPackage and throws IllegalArgumentException when TextUtils.isEmpty(callerPackage) (previously when the ComponentName was null). isSettingsPackage and isAllowlistedPackage are computed directly from callerPackage. Otherwise unchanged (SecurityException for non-allowed callers). The unused TAG constant and the ComponentName import are removed.",
      "tests/robotests/src/com/android/settings/search/SearchFeatureProviderImplTest.java - the three verifyLaunchSearchResultPageCaller tests (badCaller_shouldCrash, settingsCaller_shouldNotCrash, settingsIntelligenceCaller_shouldNotCrash) are updated to pass package name Strings."
     ],
     "completeness": [
      "The fix covers both uses of the caller identity in SearchResultTrampoline: the privilege gate (verifyLaunchSearchResultPageCaller) and the launch-path selection (isSettingsIntelligence). This commit touches no other getCallingActivity() call sites in Settings, and the material does not show whether any exist.",
      "The allow decision logic itself (Settings package, SettingsIntelligence package, isSignatureAllowlisted) is unchanged; only the source of the identity changes.",
      "Per the commit message, getLaunchedFromPackage() also reports the creator of a PendingIntent used to launch the activity, so a launch through a PendingIntent built by an allowed package is accepted. The material does not show whether any such PendingIntent exists.",
      "The IllegalArgumentException message still says 'must be called with startActivityForResult', which no longer matches the new check (empty launching package)."
     ],
     "behavior_changes": [
      "The caller identity for the trampoline is now the launching package (or PendingIntent creator) instead of the result-receiving component. Allowed packages no longer need to use startActivityForResult to pass the check, and non-allowed launching packages receive a SecurityException.",
      "IllegalArgumentException is now thrown when getLaunchedFromPackage() returns null or empty, instead of when getCallingActivity() returned null.",
      "isSettingsIntelligence() now compares the launching package String instead of the result receiver's package, so the embedded-activity launch path is chosen based on the launching package.",
      "The SearchFeatureProvider.verifyLaunchSearchResultPageCaller interface signature changed (ComponentName to String), which breaks any out-of-tree implementations or callers of the old signature."
     ],
     "preconditions": [
      "A caller must be able to start SearchResultTrampoline in the Settings app with an intent carrying search-result extras (the exception message refers to 'ExternalSettingsTrampoline intents'). The material does not show whether the activity is exported or under what intent filter.",
      "Before the fix, the authorization outcome depended on the result-receiver identity reported by getCallingActivity() rather than the actual launching package."
     ],
     "per_major": {
      "14": "same fix: commit f1d0079c9173 (cherry-pick of 901880a1d2e6, Change-Id If97018c2741caef622f0596bbfeaa42ef1788b78) in android-security-14.0.0_r8. At android-security-14.0.0_r29, 7/8 lines of the patched region are present; the context shows the String-based interface and the SearchFeatureProviderImpl check.",
      "15": "not affected per the bulletin; at android-security-15.0.0_r17, 7/8 lines of the patched region are present.",
      "16": "not affected per the bulletin; at android-security-16.0.0_r8, 7/8 lines of the patched region are present.",
      "17": "not affected per the bulletin; at android-security-17.0.0_r1, 7/8 lines of the patched region are present."
     },
     "backport_notes": [
      "Single commit across four files. The interface signature change in SearchFeatureProvider must be applied together with SearchFeatureProviderImpl, SearchResultTrampoline, and any downstream or OEM SearchFeatureProvider implementations that override verifyLaunchSearchResultPageCaller(Context, ComponentName).",
      "When porting, check that the getLaunchedFromPackage() call in SearchResultTrampoline.onCreate is present, because one line of the patched region differs in the latest tags."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show the AndroidManifest declaration of SearchResultTrampoline (exported status, intent filters, permissions).",
      "The material does not show which line of the 8-line patched region differs in the latest security tags, or why.",
      "The material does not show, beyond the EoP rating, what a non-allowed caller could reach through the trampoline (which Settings pages or extras).",
      "The material does not show whether other Settings activities use getCallingActivity() for authorization."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 5,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-23708": {
     "cve": "CVE-2024-23708",
     "summary": "NotificationManagerService now puts system-package toasts ahead of pending non-system toasts in mToastQueue (behind the toast currently on screen and after any queued system toasts) instead of adding them at the end, and ClipboardService's \"pasted from clipboard\" warning toast changes from LENGTH_SHORT to LENGTH_LONG, so apps can no longer delay system toasts by filling the queue.",
     "component": "platform/frameworks/base, system_server: NotificationManagerService toast queue and ClipboardService clipboard-access toast",
     "weakness": "Missing prioritization of system UI messages in a shared FIFO queue, so an app can delay security-relevant system toasts (resource contention / UI ordering)",
     "root_cause": "In NotificationManagerService's toast enqueue path (inside synchronized (mToastQueue)), every new ToastRecord was appended with mToastQueue.add(record) and index = mToastQueue.size() - 1, whatever the value of isSystemToast. Within this block, the only cap on queue entries was the per-package MAX_PACKAGE_TOASTS. A non-system package could queue up to MAX_PACKAGE_TOASTS toasts, and any system toast requested later waited behind all of them. The commit also lengthens the ClipboardService paste warning toast, which used Toast.LENGTH_SHORT.",
     "fix_analysis": [
      "services/core/java/com/android/server/notification/NotificationManagerService.java, toast enqueue path (the block under synchronized (mToastQueue) that builds the ToastRecord via getToastRecord): after the record is created, a new local systemToastInsertIdx defaults to mToastQueue.size(). If isSystemToast is true, it is set from the new getInsertIndexForSystemToastLocked(). If the index is less than mToastQueue.size(), the record is inserted there with mToastQueue.add(index, record). Otherwise the old behaviour is kept (append, index = size()-1). The existing 'if (index == 0) showNextToastLocked(false)' logic is unchanged.",
      "services/core/java/com/android/server/notification/NotificationManagerService.java: the new @GuardedBy(\"mToastQueue\") getInsertIndexForSystemToastLocked() walks mToastQueue. It skips index 0 when mIsCurrentToastShown is true, then returns the index of the first ToastRecord whose isSystemToast is false. If no such record exists, it returns mToastQueue.size(), so the new toast goes after the last system toast.",
      "services/core/java/com/android/server/clipboard/ClipboardService.java, clipboard-access toast code (the Binder.withCleanCallingIdentity block that builds the R.string.pasted_from_clipboard message): both Toast.makeCustomToastWithIcon and Toast.makeText now use Toast.LENGTH_LONG instead of Toast.LENGTH_SHORT.",
      "services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java adds two tests. testPrioritizeSystemToasts queues MAX_PACKAGE_TOASTS non-system toasts, then one system toast, and asserts the system toast lands at index 1. testPrioritizeSystemToasts_enqueueAfterExistingSystemToast queues MAX_PACKAGE_TOASTS system toasts, then another system toast, and asserts the new one is last."
     ],
     "completeness": [
      "Only covers newly enqueued ToastRecords. A toast already in the queue (indexOfToastLocked(pkg, token) >= 0) is updated in place and not moved; this is unchanged behaviour.",
      "The toast currently on screen is not preempted, because index 0 is skipped when mIsCurrentToastShown is true.",
      "The per-package MAX_PACKAGE_TOASTS check runs before the insertion logic and applies to system packages too. The fix changes ordering, not capacity.",
      "Priority depends only on the isSystemToast flag passed into getToastRecord. How that flag is derived is outside the diff.",
      "Only the ClipboardService toast duration changed."
     ],
     "behavior_changes": [
      "When system and non-system toasts are both queued, system toasts are shown before pending non-system toasts (after the one currently on screen).",
      "System toasts keep FIFO order among themselves.",
      "The clipboard 'pasted from clipboard' toast now shows for LENGTH_LONG instead of LENGTH_SHORT.",
      "Non-system toasts are still appended to the end of the queue. The diff adds no new rejections."
     ],
     "preconditions": [
      "A non-system app can enqueue toasts through NotificationManagerService (subject to the existing enqueue checks and up to MAX_PACKAGE_TOASTS queued toasts per package) before a system toast is requested.",
      "A system-package toast whose timely display matters; the commit also changes the ClipboardService clipboard-access warning toast."
     ],
     "per_major": {
      "14": "same fix: commit b9f175fb1f5c (Change-Id I13547f853476bc88d12026c545aba9f857ce8724) in android-security-14.0.0_r8. At android-security-14.0.0_r29, 7/8 lines of the patched region are present, and the code context shows the insertion logic and the LENGTH_LONG clipboard toast.",
      "15": "not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); 7/8 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single commit. It uses ToastRecord.isSystemToast, the mIsCurrentToastShown field and the isSystemToast parameter of getToastRecord without adding them, so these must already exist in the target branch. The bulletin lists 12, 12L and 13 as affected, but the material has no commits for those branches.",
      "The new tests use the mService.isSystemUid / isSystemAppId test hooks and the setToastRateIsWithinQuota / setIfPackageHasPermissionToAvoidToastRateLimiting helpers in NotificationManagerServiceTest."
     ],
     "confidence": "high",
     "unknowns": [
      "How isSystemToast is computed for a caller, and therefore which callers get priority (not in the diff).",
      "The name of the enclosing ClipboardService method that builds the clipboard-access toast.",
      "Which commits fix Android 12, 12L and 13.",
      "Why one line of the eight-line patched region differs at the latest security tags."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 7,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2024-23709": {
     "cve": "CVE-2024-23709",
     "summary": "Clamps the per-frame sample count in the sonivox wavetable synthesizer to BUFFER_SIZE_IN_MONO_SAMPLES, both where it is computed (WT_CheckSampleEnd in eas_wtsynth.c) and in each engine routine that uses it (eas_wtengine.c), so the gain, interpolation and filter loops cannot run past the frame audio and mix buffers.",
     "component": "platform/external/sonivox, arm-wt-22k wavetable synth engine (eas_wtsynth.c, eas_wtengine.c)",
     "weakness": "Missing upper bounds check on a loop count (buffer overrun / out-of-bounds access)",
     "root_cause": "When a voice is about to reach loopEnd, WT_CheckSampleEnd in arm-wt-22k/lib_src/eas_wtsynth.c computes pWTIntFrame->numSamples as 1 + (numSamples / phaseIncrement), or uses the raw value when phaseIncrement is 0. It rejected only a negative result (the existing b/26366256 check) and had no upper bound. The engine routines in eas_wtengine.c (WT_VoiceGain, WT_Interpolate, WT_InterpolateNoLoop, WT_VoiceFilter, WT_InterpolateMono) copy pWTIntFrame->numSamples into a local count and also check only for <= 0 before processing pWTIntFrame->pAudioBuffer and/or pMixBuffer. WT_VoiceGain, for example, loops while(numSamples--) over both buffers. A count larger than the frame buffer size (BUFFER_SIZE_IN_MONO_SAMPLES) can therefore drive accesses past those buffers.",
     "fix_analysis": [
      "arm-wt-22k/lib_src/eas_wtsynth.c:WT_CheckSampleEnd: the sample-count formula changes from 1 + (numSamples / phaseIncrement) to a ceiling division, (numSamples + phaseIncrement - 1) / phaseIncrement. The old value is still computed, and ALOGE('b/317780080 old %ld new %ld') is logged when the two differ.",
      "arm-wt-22k/lib_src/eas_wtsynth.c:WT_CheckSampleEnd: after the existing < 0 check, a new else-if clips pWTIntFrame->numSamples to BUFFER_SIZE_IN_MONO_SAMPLES and logs ALOGE and android_errorWriteLog(0x534e4554, \"317780080\"). Because the clamp comes after both assignments, it also covers the phaseIncrement == 0 branch.",
      "arm-wt-22k/lib_src/eas_wtengine.c: the same clip (if numSamples > BUFFER_SIZE_IN_MONO_SAMPLES, set numSamples = BUFFER_SIZE_IN_MONO_SAMPLES, with ALOGE and android_errorWriteLog) is added as an else-if to the existing <= 0 check at six sites: WT_VoiceGain, WT_Interpolate, WT_InterpolateNoLoop, two sites whose hunk headers name WT_VoiceFilter (around lines 409 and 481), and WT_InterpolateMono. Only the local numSamples copy is clipped. pWTIntFrame->numSamples is not changed there."
     ],
     "completeness": [
      "Defense in depth: the code that computes the count (WT_CheckSampleEnd) and all six engine sites in the diff that already had the b/26366256 <= 0 check are now bounded by BUFFER_SIZE_IN_MONO_SAMPLES.",
      "The clamp assumes pAudioBuffer and pMixBuffer each hold at least BUFFER_SIZE_IN_MONO_SAMPLES entries. The buffer allocations are not in the material, so the diff cannot confirm this.",
      "The material does not show any other user of pWTIntFrame->numSamples outside the six patched engine sites (for example alternative or conditionally compiled engine paths), and this commit does not touch any.",
      "For a positive remaining distance, the formula change (ceiling instead of 1 + floor) lowers the count by one when the distance divides evenly by phaseIncrement. The clamp, not the formula change, is what enforces the bound."
     ],
     "behavior_changes": [
      "New ALOGE log lines tagged b/317780080 and android_errorWriteLog(0x534e4554, \"317780080\") events whenever a sample count is clipped.",
      "A sample count above the limit is clipped to BUFFER_SIZE_IN_MONO_SAMPLES (and logged) instead of overrunning, so that frame renders fewer samples than computed.",
      "WT_CheckSampleEnd yields one fewer sample than before when the remaining phase distance divides evenly by phaseIncrement. It logs an ALOGE whenever the new and old formulas differ, whether or not clipping happens."
     ],
     "preconditions": [
      "Audio content rendered through the sonivox arm-wt-22k wavetable synthesizer (EAS), with a voice whose endPhaseAccum reaches or passes pWTVoice->loopEnd within a frame. This is the branch in WT_CheckSampleEnd that computes numSamples.",
      "Voice state (loopEnd, phaseAccum, phaseFrac, phaseIncrement) that makes the computed count exceed BUFFER_SIZE_IN_MONO_SAMPLES. The material does not show how input data leads to that state."
     ],
     "per_major": {
      "14": "same fix: commit 0205dff2273f in android-security-14.0.0_r8 (cherry-picked from main, Change-Id I3609d6a36d89b26ae7eb3ae84cbe7772f6c3bee0). At android-security-14.0.0_r29 the full patched region (8/8 lines) is present.",
      "15": "not affected (not listed by the bulletin); the patched region (8/8 lines) is present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); the patched region (8/8 lines) is present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); the patched region (8/8 lines) is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained commit. Its hunks only extend the existing b/26366256 if-blocks, so the tree must already have those <= 0 checks for them to apply cleanly. Otherwise, add the clamp after whatever numSamples validation exists in each of the six engine sites and in WT_CheckSampleEnd."
     ],
     "confidence": "high",
     "unknowns": [
      "The sizes of pWTIntFrame->pAudioBuffer and pWTIntFrame->pMixBuffer relative to BUFFER_SIZE_IN_MONO_SAMPLES are not shown.",
      "Which function actually contains the second WT_VoiceFilter-labelled hunk in eas_wtengine.c (around line 481) is not shown. Its header names WT_VoiceFilter, but the body references phaseIncrement.",
      "How input data (MIDI/DLS) drives loopEnd or phaseIncrement to produce an oversized count. The material only references a POC in bug 317780080.",
      "Whether other engine paths that use pWTIntFrame->numSamples exist beyond the six patched sites.",
      "The loop bodies of the engine routines other than WT_VoiceGain are not shown."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 5,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    }
   }
  },
  "15": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 18,
    "first_ingested_tag": "android-security-15.0.0_r1",
    "latest_ingested_tag": "android-security-15.0.0_r18",
    "window_base_tag": "android-15.0.0_r1",
    "window_start": "2024-09-03",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  },
  "16": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 9,
    "first_ingested_tag": "android-security-16.0.0_r1",
    "latest_ingested_tag": "android-security-16.0.0_r9",
    "window_base_tag": "android-16.0.0_r2",
    "window_start": "2025-06-10",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  },
  "17": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 2,
    "first_ingested_tag": "android-security-17.0.0_r1",
    "latest_ingested_tag": "android-security-17.0.0_r2",
    "window_base_tag": "android-17.0.0_r1",
    "window_start": "2026-06-16",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  }
 },
 "bulletin": {
  "url": "https://source.android.com/docs/security/bulletin/2024-05-01",
  "latest_version": "1.0",
  "latest_revision": {
   "version": "1.0",
   "date": "May 6, 2024",
   "notes": "Bulletin Published."
  },
  "revisions": [
   {
    "version": "1.0",
    "date": "May 6, 2024",
    "notes": "Bulletin Published."
   }
  ],
  "tracked_since": "2026-09-30",
  "changes_since_tracking": [],
  "out_of_scope_rows": {
   "Arm components": 3,
   "Kernel": 1,
   "MediaTek components": 4,
   "Qualcomm closed-source components": 6,
   "Qualcomm components": 4
  },
  "note": "changes are only visible from `tracked_since`; earlier revisions of the bulletin cannot be reconstructed. Out-of-scope rows (vendor closed-source, kernel) have no public AOSP code to resolve."
 }
}