{
 "month": "2025-08",
 "generated": "2026-10-06T12:05+00:00",
 "majors": {
  "14": {
   "counts": {
    "announced": 2,
    "certain": 2,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-22441",
     "osv_id": "ASB-A-376028556",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "RemoteViews now builds the remote application Context from an ApplicationInfo fetched from PackageManager (keyed by package name and user id) instead of the parceled ApplicationInfo supplied by the RemoteViews-providing app, and the LoadedApk.checkAndUpdateApkPaths calls in RemoteViews and AppWidgetHostView are removed.",
      "confidence": "high",
      "backport_notes": [
       "Single commit, two files. The diff removes the android.app.LoadedApk import from both files, so a target branch must have no other LoadedApk uses in these files (or keep the import). The diff adds no import for UserHandle, so RemoteViews.java must already import it."
      ],
      "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_r19",
      "date": "2025-04-07",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r19",
      "date": "2025-04-07",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "60335b2eae7311fe6e10e140b64489008a38a5a8",
       "tag": "android-security-14.0.0_r19",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 116,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-48533",
     "osv_id": "ASB-A-383131643",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "When the keyguard is locked and the activity does not request showWhenLocked, WindowManager now waits for the transition to finish before it removes the activity's starting (splash) window. Until then it reports the activity's other windows as not visible, so app content is not shown on a locked device during the unocclude animation.",
      "confidence": "high",
      "backport_notes": [
       "For branches where StartingData.mRemoveAfterTransaction is still a boolean (as on Android 14), take the full Android 14 commit. It converts the field to the @AfterTransaction int and rewires the removal path, the sync-commit handler and the splash-transfer method. Any vendor code that reads this field as a boolean must be updated. On branches like Android 15, only AFTER_TRANSITION_FINISH and the logic hunks are needed.",
       "On Android 16-style branches, check whether the keep_app_window_hide_while_locked flag exists. If it does, the fix makes its gated logic unconditional and adds a null check."
      ],
      "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_r23",
      "date": "2025-11-03",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r23",
      "date": "2025-11-03",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "71773c9f03af1199720a2776a58f5be9f99c5d1a",
       "tag": "android-security-14.0.0_r23",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    }
   ],
   "tags": [],
   "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-2025-22441": {
     "cve": "CVE-2025-22441",
     "summary": "RemoteViews now builds the remote application Context from an ApplicationInfo fetched from PackageManager (keyed by package name and user id) instead of the parceled ApplicationInfo supplied by the RemoteViews-providing app, and the LoadedApk.checkAndUpdateApkPaths calls in RemoteViews and AppWidgetHostView are removed.",
     "component": "platform/frameworks/base, core/java/android/widget/RemoteViews and core/java/android/appwidget/AppWidgetHostView (widget / RemoteViews inflation in host processes)",
     "weakness": "Trust of untrusted, app-supplied parceled data (client-supplied ApplicationInfo used to create a Context without validation)",
     "root_cause": "When a host process inflated a RemoteViews, the code in RemoteViews.java that creates a Context for the remote app used the ApplicationInfo object (mApplication) read from the RemoteViews parcel/bundle supplied by the widget-providing app. It passed this object to LoadedApk.checkAndUpdateApkPaths(mApplication) and to context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED). The commit message says the fields of this object could not be relied on to be accurate, so the host built a Context from data provided by the sending app. AppWidgetHostView.getRemoteContextEnsuringCorrectCachedApkPath also called LoadedApk.checkAndUpdateApkPaths on mInfo.providerInfo.applicationInfo before creating the application Context.",
     "fix_analysis": [
      "core/java/android/widget/RemoteViews.java (the method that creates the application Context from mApplication, around line 6057; the hunk header does not show the method name): the call LoadedApk.checkAndUpdateApkPaths(mApplication) is deleted. The fix now gets a sanitizedApplication from context.getPackageManager().getApplicationInfoAsUser(mApplication.packageName, 0, UserHandle.getUserId(mApplication.uid)). Only the package name, and the user id derived from the parceled uid, come from the untrusted object.",
      "core/java/android/widget/RemoteViews.java (same method): context.createApplicationContext(sanitizedApplication, Context.CONTEXT_RESTRICTED) is called with the PackageManager-sourced object. The result is wrapped with applicationContext.createConfigurationContext(context.getResources().getConfiguration()); per the added comment, this gets the correct apk paths while keeping the current context's configuration. The existing catch (NameNotFoundException) now also covers the new getApplicationInfoAsUser call.",
      "core/java/android/appwidget/AppWidgetHostView.java:getRemoteContextEnsuringCorrectCachedApkPath: the lines that read expectedAppInfo = mInfo.providerInfo.applicationInfo and call LoadedApk.checkAndUpdateApkPaths(expectedAppInfo) are removed. The method still calls mContext.createApplicationContext(mInfo.providerInfo.applicationInfo, Context.CONTEXT_RESTRICTED). The android.app.LoadedApk import is removed from both files."
     ],
     "completeness": [
      "Covered: the RemoteViews path that turns the parceled mApplication into a Context now uses only packageName and uid (uid only to derive the user id) from the untrusted object; all other ApplicationInfo fields come from PackageManager.",
      "Not changed: mApplication.packageName and mApplication.uid are still read from the parcel without further validation. The code relies on PackageManager throwing NameNotFoundException for unknown packages.",
      "Not changed: the early-return check before the try block is kept as is; the material does not show its condition.",
      "AppWidgetHostView.getRemoteContextEnsuringCorrectCachedApkPath still passes mInfo.providerInfo.applicationInfo straight to createApplicationContext; only the checkAndUpdateApkPaths call was removed there. The material does not show where that object comes from or whether it can be trusted.",
      "The material does not show whether other uses of mApplication elsewhere in RemoteViews.java still trust parceled fields."
     ],
     "behavior_changes": [
      "Each time a remote-app Context is created from a RemoteViews, the host process now does a PackageManager lookup (getApplicationInfoAsUser with flags 0).",
      "If the package named in the RemoteViews is not found for the derived user, NameNotFoundException is caught and logged instead of a Context being created from the parceled data. The code after the catch block is not shown.",
      "The returned Context is now a configuration Context built with the host context's current Configuration, instead of the raw application Context.",
      "LoadedApk.checkAndUpdateApkPaths is no longer called from RemoteViews or AppWidgetHostView."
     ],
     "preconditions": [
      "A RemoteViews object created by another app (e.g. an app widget provider) must be inflated in a host process that reaches the context-creation code in RemoteViews.java with a parceled mApplication, and the early-return condition before the try block must not apply.",
      "Per index search, AppWidgetHostView.AdapterChildHostView overrides getRemoteContextEnsuringCorrectCachedApkPath to return null, so adapter child views do not take the AppWidgetHostView path."
     ],
     "per_major": {
      "14": "same fix: commit 60335b2eae73 in android-security-14.0.0_r19 (two files, RemoteViews.java and AppWidgetHostView.java); at android-security-14.0.0_r29 all 8/8 lines of the patched region are present.",
      "15": "same fix: commit f60fc2258f63 in android-security-15.0.0_r7, with the same changes at different line offsets; at android-security-15.0.0_r17 all 8/8 lines are present.",
      "16": "not affected (not listed by the bulletin); at android-security-16.0.0_r8 all 8/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, two files. The diff removes the android.app.LoadedApk import from both files, so a target branch must have no other LoadedApk uses in these files (or keep the import). The diff adds no import for UserHandle, so RemoteViews.java must already import it."
     ],
     "confidence": "high",
     "unknowns": [
      "The name of the RemoteViews method containing the patched hunk, the exact early-return condition before the try block, and what the method returns after the NameNotFoundException catch.",
      "Which ApplicationInfo fields were misused and what the concrete EoP consequence was in the host process; the commit message only says the fields could not be relied on.",
      "Whether LoadedApk.checkAndUpdateApkPaths itself was changed or removed in a separate commit, and what it does internally.",
      "Where mInfo.providerInfo.applicationInfo in AppWidgetHostView comes from and whether it is trusted.",
      "Whether the layoutlib RemoteViews_Delegate.getApplicationInfo found by index search relates to this code path.",
      "Whether the CTS test RemoteViewsActivityTest#testApplicationInfo was added in this change or a separate one."
     ],
     "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-2025-48533": {
     "cve": "CVE-2025-48533",
     "summary": "When the keyguard is locked and the activity does not request showWhenLocked, WindowManager now waits for the transition to finish before it removes the activity's starting (splash) window. Until then it reports the activity's other windows as not visible, so app content is not shown on a locked device during the unocclude animation.",
     "component": "platform/frameworks/base, services/core WindowManager (ActivityRecord, StartingData, Transition, WindowState)",
     "weakness": "Logic/timing flaw in keyguard visibility handling: the starting window is removed and the app window made visible before the keyguard unocclude transition has finished. This exposes app content over the keyguard. The bulletin rates it EoP.",
     "root_cause": "The starting window (splash screen) may carry FLAG_SHOW_WHEN_LOCKED because it holds no sensitive content. A WindowState method copies FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON from the app window into mActivityRecord.mStartingWindow.mAttrs. It just overwrote those flags: it did not re-check keyguard state (checkKeyguardFlagsChanged) and did not delay removal of the starting window. ActivityRecord.removeStartingWindow() had no keyguard-based deferral, and WindowState visibility depended only on atoken.isVisible() and animation state. So while the device was still locked, the app window of an activity that does not request showWhenLocked could briefly become visible, including through alpha blending during the unocclude animation. On Android 14, StartingData.mRemoveAfterTransaction was also only a boolean, so there was no state meaning 'remove after the transition finishes'.",
     "fix_analysis": [
      "StartingData.java: mRemoveAfterTransaction becomes an @AfterTransaction int. Android 14 adds all four states (AFTER_TRANSACTION_IDLE=0, AFTER_TRANSACTION_REMOVE_DIRECTLY=1, AFTER_TRANSACTION_COPY_TO_CLIENT=2, AFTER_TRANSITION_FINISH=3). Android 15 only adds AFTER_TRANSITION_FINISH to the IntDef it already had.",
      "WindowState.java, the method that copies keyguard flags into mActivityRecord.mStartingWindow.mAttrs (around line 2893): it computes wasShowWhenLocked (the starting window had FLAG_SHOW_WHEN_LOCKED) and removeShowWhenLocked (the app window does not have it). When both are true it calls mActivityRecord.checkKeyguardFlagsChanged() to trigger the unocclude animation, then mActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding().",
      "New ActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding(): sets mStartingData.mRemoveAfterTransaction = AFTER_TRANSITION_FINISH when all of these hold: mStartingData != null, the state is not already AFTER_TRANSITION_FINISH, isKeyguardLocked(), !canShowWhenLockedInner(this), !isVisibleRequested(), and mTransitionController.inTransition(this).",
      "ActivityRecord.removeStartingWindow(): returns early, keeping the splash screen, while mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH.",
      "WindowState.java visibility check (around line 1931, the branch that evaluates atoken.isVisible() / isAnimationRunningSelfOrParent()): returns false for every window of the activity that is not TYPE_APPLICATION_STARTING while atoken.mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH. This stops the app window from showing through alpha blending during the unocclude animation.",
      "Transition.java, loop over ActivityRecords next to the enterAutoPip handling (the enclosing method is not named in the hunk): when ar.mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH and (!ar.isVisible() || !ar.mTransitionController.inTransition(ar)), it resets the state to AFTER_TRANSACTION_IDLE and calls ar.removeStartingWindow(). This performs the deferred removal.",
      "ActivityRecord starting-window transfer path (where tStartingWindow.mToken = this is set): resets AFTER_TRANSITION_FINISH to AFTER_TRANSACTION_IDLE when the starting window is handed to another activity.",
      "ActivityRecord.canShowWhenLocked(ActivityRecord) is refactored to use a new static helper, canShowWhenLockedInner(r) (= !inPinnedWindowingMode && (mShowWhenLocked || containsShowWhenLockedWindow())). The new deferral check reuses this helper.",
      "Android 14 only (state machine bundled into the backport): (1) the splash-screen transfer method (the one that calls requestCopySplashScreen()) now sets AFTER_TRANSACTION_COPY_TO_CLIENT and returns true while mStartingData.mWaitForSyncTransactionCommit is set; (2) the method that clears mWaitForSyncTransactionCommit now dispatches on the state (REMOVE_DIRECTLY -> removeStartingWindowAnimation(mPrepareRemoveAnimation), COPY_TO_CLIENT -> removeStartingWindow()); (3) the removal path that used to set mRemoveAfterTransaction = true now sets AFTER_TRANSACTION_REMOVE_DIRECTLY.",
      "Android 16: the logic was already present behind the aconfig flag keep_app_window_hide_while_locked. The security commit removes the flag from windowing_frontend.aconfig and from the WindowState condition, so the behaviour becomes unconditional. It also adds the mStartingData != null guard in deferStartingWindowRemovalForKeyguardUnoccluding()."
     ],
     "completeness": [
      "The deferral is armed from only one place: the WindowState path where the app window's keyguard flags are merged into the starting window attrs. It is armed only when the starting window had FLAG_SHOW_WHEN_LOCKED and the app window does not.",
      "deferStartingWindowRemovalForKeyguardUnoccluding() requires mTransitionController.inTransition(this); if that is false, no deferral happens. The material shows the deferral released only in Transition.java and in the starting-window transfer path.",
      "The WindowState visibility override applies to every non-TYPE_APPLICATION_STARTING window of the activity while the state is AFTER_TRANSITION_FINISH. It is keyed on that window's own ActivityRecord.",
      "The state is cleared when the starting window is transferred to another activity and in the Transition.java loop. The material shows no other clearing path, for example for an aborted transition.",
      "Android 14 also gets the AFTER_TRANSACTION_COPY_TO_CLIENT deferral, which holds the splash-screen copy until the sync transaction commits. Android 15 already had this."
     ],
     "behavior_changes": [
      "When the keyguard is locked and a launching activity does not request showWhenLocked, the splash screen stays until the transition completes instead of being removed directly.",
      "During that time WindowState reports the activity's non-starting windows as not visible.",
      "When the app window drops FLAG_SHOW_WHEN_LOCKED relative to the starting window, ActivityRecord.checkKeyguardFlagsChanged() is now called, which may trigger an unocclude animation.",
      "Android 14: splash-screen copy-to-client is deferred while a sync transaction is pending, and mRemoveAfterTransaction changes type from boolean to int.",
      "Android 16: the behaviour is now unconditional instead of gated by the keep_app_window_hide_while_locked aconfig flag."
     ],
     "preconditions": [
      "The device keyguard is locked (isKeyguardLocked()).",
      "An activity is started whose starting window carries FLAG_SHOW_WHEN_LOCKED, while the activity itself does not request showWhenLocked (canShowWhenLockedInner is false) and is not yet visible-requested.",
      "A transition involving the activity is in progress (mTransitionController.inTransition). The commit's test note describes repeatedly launching a simulated app and checking that app content is not visible during the transition animation."
     ],
     "per_major": {
      "14": "Fixed by 71773c9f03af in android-security-14.0.0_r23. The change also bundles the boolean-to-int StartingData state machine and the COPY_TO_CLIENT deferral. 8/8 lines of the patched region present at android-security-14.0.0_r29.",
      "15": "Adapted fix 9916e7bbbf44 in android-security-15.0.0_r11. Only AFTER_TRANSITION_FINISH is added to the existing IntDef; the ActivityRecord, Transition and WindowState logic is the same, with the visibility hunk placed before the isStartingWindowAssociatedToTask() check. 8/8 lines present at android-security-15.0.0_r17.",
      "16": "Adapted fix 8874f3eae9a9 in android-security-16.0.0_r1. The logic was already present behind the aconfig flag keep_app_window_hide_while_locked; the commit removes the flag (making it unconditional) and adds the mStartingData null check. 5/8 lines of the patched region present at android-security-16.0.0_r8; the reason for the partial match is not shown.",
      "17": "Not affected (not listed by the bulletin). 3/8 lines of the patched region present at android-security-17.0.0_r1; the material does not explain why."
     },
     "backport_notes": [
      "For branches where StartingData.mRemoveAfterTransaction is still a boolean (as on Android 14), take the full Android 14 commit. It converts the field to the @AfterTransaction int and rewires the removal path, the sync-commit handler and the splash-transfer method. Any vendor code that reads this field as a boolean must be updated. On branches like Android 15, only AFTER_TRANSITION_FINISH and the logic hunks are needed.",
      "On Android 16-style branches, check whether the keep_app_window_hide_while_locked flag exists. If it does, the fix makes its gated logic unconditional and adds a null check."
     ],
     "confidence": "high",
     "unknowns": [
      "The exact names of the two patched WindowState methods, of the ActivityRecord splash-transfer and sync-commit methods, and of the Transition.java method holding the release loop are not shown in the hunk headers.",
      "Whether an aborted (rather than finished) transition leaves mRemoveAfterTransaction at AFTER_TRANSITION_FINISH is not visible.",
      "How the fix behaves on devices that do not use shell transitions (legacy app transitions) is not shown.",
      "The concrete scenario (which launch path over the keyguard) is not described beyond the commit's test note.",
      "Why Android 16 r8 and 17 r1 only partially match the patched region is 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": 2,
    "certain": 2,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-22441",
     "osv_id": "ASB-A-376028556",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "RemoteViews now gets the ApplicationInfo it uses to build the remote application Context from PackageManager (looked up by package name and user id) instead of trusting the parceled ApplicationInfo supplied by the RemoteViews-providing app. The LoadedApk.checkAndUpdateApkPaths calls are removed from RemoteViews and AppWidgetHostView.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit touching two files. The diff adds no new imports, so RemoteViews.java in the target tree must already import android.os.UserHandle and android.content.pm.ApplicationInfo. ApplicationInfo is imported in the Android 15 context shown; UserHandle is not visible in the material and should be checked."
      ],
      "meta": {
       "generated": "2026-10-03",
       "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-15.0.0_r7",
      "date": "2025-04-07",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r7",
      "date": "2025-04-07",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "f60fc2258f6393a2e7a4548656aa18a8966912f0",
       "tag": "android-security-15.0.0_r7",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 116,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-48533",
     "osv_id": "ASB-A-383131643",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "While the device is locked and the activity does not request showWhenLocked, WindowManager now defers removing the activity's starting window (splash screen) until the transition completes, triggers the keyguard unoccluding animation, and treats the activity's non-starting windows as not visible, so app content is no longer briefly shown on a locked device.",
      "confidence": "high",
      "backport_notes": [
       "For Android 14-level code, the fix depends on the StartingData refactor (boolean mRemoveAfterTransaction changed to an @AfterTransaction int, plus the canShowWhenLockedInner extraction), which Google included in the same 14 commit. For Android 15-level code these prerequisites already exist.",
       "On Android 16-level code, the logic may already exist behind the aconfig flag keep_app_window_hide_while_locked. The fix there removes the flag gate and adds the mStartingData null check."
      ],
      "meta": {
       "generated": "2026-10-03",
       "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-15.0.0_r11",
      "date": "2025-11-03",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r11",
      "date": "2025-11-03",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "9916e7bbbf44f77514f3ae31b601ebc6c8580d39",
       "tag": "android-security-15.0.0_r11",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    }
   ],
   "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": {
    "CVE-2025-22441": {
     "cve": "CVE-2025-22441",
     "summary": "RemoteViews now gets the ApplicationInfo it uses to build the remote application Context from PackageManager (looked up by package name and user id) instead of trusting the parceled ApplicationInfo supplied by the RemoteViews-providing app. The LoadedApk.checkAndUpdateApkPaths calls are removed from RemoteViews and AppWidgetHostView.",
     "component": "platform/frameworks/base, core/java/android/widget/RemoteViews.java and core/java/android/appwidget/AppWidgetHostView.java (RemoteViews / AppWidget host)",
     "weakness": "Use of untrusted, caller-supplied data (a deserialized ApplicationInfo) to create an application Context and update cached APK paths in the host process (improper input validation / trust of a client-provided object)",
     "root_cause": "The RemoteViews method that builds a Context for the remote application (hunk at RemoteViews.java ~line 6554; the method name is not shown in the hunk) used mApplication, an ApplicationInfo read from the RemoteViews parcel provided by the widget-providing app. It passed that object to LoadedApk.checkAndUpdateApkPaths(mApplication) and then to context.createApplicationContext(mApplication, Context.CONTEXT_RESTRICTED). The commit message says this object \"could not be relied on to have accurate data fields\". As a result, the process inflating the RemoteViews created a Context, and updated LoadedApk cached APK paths, from fields the provider controls. AppWidgetHostView.getRemoteContextEnsuringCorrectCachedApkPath likewise called LoadedApk.checkAndUpdateApkPaths(mInfo.providerInfo.applicationInfo) before createApplicationContext.",
     "fix_analysis": [
      "RemoteViews.java (method creating the remote application Context, hunk at ~6554): removes LoadedApk.checkAndUpdateApkPaths(mApplication). It now calls context.getPackageManager().getApplicationInfoAsUser(mApplication.packageName, 0, UserHandle.getUserId(mApplication.uid)) to get a 'sanitizedApplication' ApplicationInfo, then calls context.createApplicationContext(sanitizedApplication, Context.CONTEXT_RESTRICTED).",
      "RemoteViews.java (same method): the resulting application Context is wrapped with applicationContext.createConfigurationContext(context.getResources().getConfiguration()). Per the code comment, this is to 'Get the correct apk paths while maintaining the current context's configuration.'",
      "RemoteViews.java: the android.app.LoadedApk import is removed. The existing catch (NameNotFoundException) is kept and now also covers the PackageManager lookup.",
      "AppWidgetHostView.java:getRemoteContextEnsuringCorrectCachedApkPath: removes the lines 'ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;' and 'LoadedApk.checkAndUpdateApkPaths(expectedAppInfo)', plus the LoadedApk import. mContext.createApplicationContext(mInfo.providerInfo.applicationInfo, Context.CONTEXT_RESTRICTED) is unchanged."
     ],
     "completeness": [
      "Covers the RemoteViews path where mApplication (from the parcel) was used to create the Context. Only packageName and uid (for the user id) are still taken from the untrusted object, and only as lookup keys for PackageManager.",
      "In AppWidgetHostView.getRemoteContextEnsuringCorrectCachedApkPath only the checkAndUpdateApkPaths call is removed. createApplicationContext still uses mInfo.providerInfo.applicationInfo directly. The material does not show where mInfo comes from.",
      "The early 'return context;' before the try block (its condition is not shown in the hunk) is unchanged.",
      "Other uses of mApplication elsewhere in RemoteViews (if any) are not shown in the material and are not touched by this diff.",
      "This commit does not modify the LoadedApk.checkAndUpdateApkPaths method itself. It only removes the two calls to it shown here."
     ],
     "behavior_changes": [
      "The remote application Context is now built from PackageManager's ApplicationInfo for mApplication.packageName in user UserHandle.getUserId(mApplication.uid). Fields of the parceled ApplicationInfo other than packageName and uid no longer affect the Context.",
      "The returned Context is a configuration context (createConfigurationContext with the host context's Configuration), not the raw application context.",
      "A new getApplicationInfoAsUser lookup runs on this path. If the package is not found, NameNotFoundException is caught and logged as before.",
      "LoadedApk cached APK paths are no longer updated from the supplied ApplicationInfo, in either RemoteViews or AppWidgetHostView."
     ],
     "preconditions": [
      "A RemoteViews object from another app (e.g. an app widget provider) is inflated in a host process, so the RemoteViews method that creates the remote application Context runs with mApplication taken from the provider's parcel.",
      "The early-return condition before the try block in that method is not met (the condition is not visible in the material).",
      "AppWidgetHostView.getRemoteContextEnsuringCorrectCachedApkPath is reached when an app widget host creates the remote Context for mInfo.providerInfo (per index search; other callers are not shown)."
     ],
     "per_major": {
      "13": "Listed as affected by the bulletin, but the material gives no fix commit or patched-region status; status unknown.",
      "14": "Same fix: platform/frameworks/base 60335b2eae73 in android-security-14.0.0_r19. Identical diff with different line offsets (RemoteViews hunk at ~6057). 8/8 lines present at android-security-14.0.0_r29.",
      "15": "Same fix: platform/frameworks/base f60fc2258f63 in android-security-15.0.0_r7 (cherry-pick of 352fb4821076f0209ab2092d53444503dcec8992). 8/8 lines present at android-security-15.0.0_r17.",
      "16": "Not affected (not listed by the bulletin). 8/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; the material does not explain the difference."
     },
     "backport_notes": [
      "Single self-contained commit touching two files. The diff adds no new imports, so RemoteViews.java in the target tree must already import android.os.UserHandle and android.content.pm.ApplicationInfo. ApplicationInfo is imported in the Android 15 context shown; UserHandle is not visible in the material and should be checked."
     ],
     "confidence": "high",
     "unknowns": [
      "The name of the RemoteViews method containing the patched hunk, and the early-return condition before the try block (not shown in the material).",
      "Which ApplicationInfo fields were abused and the concrete EoP outcome. The material only says the object could not be relied on to have accurate fields.",
      "Whether getApplicationInfoAsUser can throw a SecurityException for a cross-user uid on this path (the code shown catches only NameNotFoundException).",
      "What happens after the NameNotFoundException catch block (not shown).",
      "Where mInfo in AppWidgetHostView comes from, and whether it can be trusted.",
      "Status of the fix on Android 13, which the bulletin lists as affected.",
      "Why only 7/8 lines of the patched region match on Android 17.",
      "Whether a CTS test change (RemoteViewsActivityTest#testApplicationInfo, named in the commit message) ships with this fix in cts."
     ],
     "meta": {
      "generated": "2026-10-03",
      "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-2025-48533": {
     "cve": "CVE-2025-48533",
     "summary": "While the device is locked and the activity does not request showWhenLocked, WindowManager now defers removing the activity's starting window (splash screen) until the transition completes, triggers the keyguard unoccluding animation, and treats the activity's non-starting windows as not visible, so app content is no longer briefly shown on a locked device.",
     "component": "platform/frameworks/base, services/core WindowManager (ActivityRecord, StartingData, Transition, WindowState)",
     "weakness": "Improper handling of window visibility state during a keyguard transition: there is no check when the starting window loses FLAG_SHOW_WHEN_LOCKED, so app content can be exposed while the device is locked.",
     "root_cause": "Per the commit message, the splash screen is treated as showWhenLocked because it contains no secure information. In WindowState, the keyguard-related flags (FLAG_SHOW_WHEN_LOCKED, FLAG_DISMISS_KEYGUARD, FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) of the activity's window are copied into mActivityRecord.mStartingWindow.mAttrs. Before the fix, when this copy cleared FLAG_SHOW_WHEN_LOCKED while the keyguard was locked, nothing re-evaluated keyguard occlusion (no checkKeyguardFlagsChanged call), and the starting window was removed on the normal ActivityRecord.removeStartingWindow path regardless of the lock state. During the transition animation the app window could then become visible through alpha blending, briefly exposing app content on a locked device even though the activity never requested showWhenLocked.",
     "fix_analysis": [
      "StartingData.java: adds a new @AfterTransaction state, AFTER_TRANSITION_FINISH = 3 ('remove the starting window after transition finish'), to the IntDef alongside AFTER_TRANSACTION_IDLE, AFTER_TRANSACTION_REMOVE_DIRECTLY and AFTER_TRANSACTION_COPY_TO_CLIENT.",
      "WindowState.java, flag-merge hunk near line 2892 (computes `mask` and writes `sa.flags`): records wasShowWhenLocked (the starting window attrs had FLAG_SHOW_WHEN_LOCKED) and removeShowWhenLocked (this window's attrs lack it). If both are true, it calls mActivityRecord.checkKeyguardFlagsChanged() to trigger the unoccluding animation, then mActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding().",
      "ActivityRecord.java: the new deferStartingWindowRemovalForKeyguardUnoccluding() sets mStartingData.mRemoveAfterTransaction = AFTER_TRANSITION_FINISH only when all of these hold: mStartingData != null, it is not already in that state, isKeyguardLocked(), !canShowWhenLockedInner(this), !isVisibleRequested(), and mTransitionController.inTransition(this).",
      "ActivityRecord.removeStartingWindow(): returns early when mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH, so the normal removal path (including transferSplashScreenIfNeeded) is skipped while removal is deferred.",
      "WindowState.java, visibility hunk near line 1909 (the method ending in `(!isParentWindowHidden() && isVisible) || isAnimationRunningSelfOrParent()`): returns false for windows that are not TYPE_APPLICATION_STARTING when their ActivityRecord's mStartingData is in AFTER_TRANSITION_FINISH. This keeps the app window hidden during the unoccluding animation.",
      "Transition.java, per-ActivityRecord loop near line 1290 (next to the enterAutoPip handling): if ar.mStartingData.mRemoveAfterTransaction == AFTER_TRANSITION_FINISH and (!ar.isVisible() || !ar.mTransitionController.inTransition(ar)), it resets the state to AFTER_TRANSACTION_IDLE and calls ar.removeStartingWindow(), performing the deferred removal.",
      "ActivityRecord.java, starting-window transfer hunk near line 4700 (`tStartingWindow.mToken = this`): when a starting window moves from another activity and its StartingData is in AFTER_TRANSITION_FINISH, the state is reset to AFTER_TRANSACTION_IDLE."
     ],
     "completeness": [
      "The deferral is set only from the WindowState flag-merge path, and only when the starting window had FLAG_SHOW_WHEN_LOCKED and the app window lacks it. It also requires isKeyguardLocked(), !isVisibleRequested() and mTransitionController.inTransition(this). If no transition is in progress for the activity at that moment, no deferral is set.",
      "Within the diff, the deferral is released only in the Transition.java per-ActivityRecord loop and by the reset on starting-window transfer. The material does not show handling for aborted transitions or for activities that never reach that loop.",
      "The WindowState visibility override applies only while atoken.mStartingData is non-null and in AFTER_TRANSITION_FINISH. Windows of type TYPE_APPLICATION_STARTING are excluded, so the splash screen stays visible.",
      "Transferring the starting window to another activity clears the deferral (reset to AFTER_TRANSACTION_IDLE) instead of re-evaluating the lock state for the new owner."
     ],
     "behavior_changes": [
      "When the merged flags drop FLAG_SHOW_WHEN_LOCKED that the starting window had, ActivityRecord.checkKeyguardFlagsChanged() is now called, which can start a keyguard unoccluding animation.",
      "On a locked device, while the deferral is set, the splash screen stays until the deferred removal in Transition.java runs, and the activity's non-starting windows report as not visible.",
      "A new StartingData @AfterTransaction value, AFTER_TRANSITION_FINISH, is added."
     ],
     "preconditions": [
      "The keyguard is locked (ActivityRecord.isKeyguardLocked()).",
      "An activity whose starting window has FLAG_SHOW_WHEN_LOCKED has a window without FLAG_SHOW_WHEN_LOCKED, and canShowWhenLockedInner(activity) is false.",
      "A transition is in progress for the activity (mTransitionController.inTransition(this)), and the activity is not visible-requested.",
      "The commit's Test line verifies the fix by running a simulated app repeatedly. The material does not detail the exact sequence that triggers the issue."
     ],
     "per_major": {
      "14": "Adapted fix: commit 71773c9f03af in android-security-14.0.0_r23. Android 14 still used a boolean StartingData.mRemoveAfterTransaction, so this commit also converts it to the @AfterTransaction int (adding AFTER_TRANSACTION_IDLE, REMOVE_DIRECTLY and COPY_TO_CLIENT), updates the existing handlers that read and set it, adds an early COPY_TO_CLIENT return when mWaitForSyncTransactionCommit is set, and extracts canShowWhenLockedInner() from canShowWhenLocked(). The WindowState visibility hunk uses the older `atoken.isVisible()` form. All 8 of 8 patched-region lines are present at android-security-14.0.0_r29.",
      "15": "Same fix: commit 9916e7bbbf44 in android-security-15.0.0_r11 (56 added lines across ActivityRecord, StartingData, Transition and WindowState). Android 15 already had the AfterTransaction constants and canShowWhenLockedInner. All 8 of 8 patched-region lines are present at android-security-15.0.0_r17.",
      "16": "Adapted fix: commit 8874f3eae9a9 in android-security-16.0.0_r1. The deferral logic was already present behind the aconfig flag keep_app_window_hide_while_locked (windowing_frontend, bug 378088391). The fix deletes the flag, makes the WindowState check unconditional, and adds a null check on mStartingData in deferStartingWindowRemovalForKeyguardUnoccluding(). 5 of 8 patched-region lines are present at android-security-16.0.0_r8.",
      "17": "Not affected per the bulletin (not listed). 4 of 8 patched-region lines match at android-security-17.0.0_r1. The material does not show further details."
     },
     "backport_notes": [
      "For Android 14-level code, the fix depends on the StartingData refactor (boolean mRemoveAfterTransaction changed to an @AfterTransaction int, plus the canShowWhenLockedInner extraction), which Google included in the same 14 commit. For Android 15-level code these prerequisites already exist.",
      "On Android 16-level code, the logic may already exist behind the aconfig flag keep_app_window_hide_while_locked. The fix there removes the flag gate and adds the mStartingData null check."
     ],
     "confidence": "high",
     "unknowns": [
      "The names of the two WindowState methods containing the hunks (near lines 1909 and 2892) and of the Transition.java method containing the release loop.",
      "Whether legacy (non-shell) app transitions were affected.",
      "Whether aborted transitions, or activities that never reach the Transition.java loop, release the AFTER_TRANSITION_FINISH deferral, and what happens to the starting window if they do not.",
      "Why only 5 of 8 and 4 of 8 lines match on Android 16 r8 and 17 r1."
     ],
     "meta": {
      "generated": "2026-10-03",
      "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."
     }
    }
   }
  },
  "16": {
   "counts": {
    "announced": 2,
    "certain": 2,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-48530",
     "osv_id": "ASB-A-419563680",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "Critical",
     "types": [
      "RCE"
     ],
     "status": "resolved",
     "brief": {
      "summary": "crabbyavif now allocates image planes with width and height rounded up to even values, allocates and reports only one chroma plane for the Android semi-planar formats (NV12/NV21/P010), and fixes per-format chroma plane width reporting, so plane buffers are no longer undersized for odd-dimension images.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit: the source changes depend only on the new round2_u32/round2_usize helpers in src/internal_utils/mod.rs and pre-existing conversion helpers (usize_from_u32, u32_from_u64 at line 145 of the r8 context); keep round2_u32 behind cfg(feature = \"capi\") to match its only user.",
       "Targets with a different crabbyavif snapshot should verify that the PixelFormat enum has the AndroidP010/AndroidNv12/AndroidNv21 variants used in the new match arms in crabby_avifImagePlaneWidth and avif_image_allocate_planes_helper; the plane-width match lists every variant and will fail to compile if variants differ."
      ],
      "meta": {
       "generated": "2026-10-02",
       "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-16.0.0_r1",
      "date": "2025-11-20",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-16.0.0_r1",
      "date": "2025-11-20",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/external/rust/crabbyavif",
       "sha": "9bcc1a311114ab844b417d3cdec50dcedfd0603f",
       "tag": "android-security-16.0.0_r1",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/external/rust/crabbyavif"
     ]
    },
    {
     "cve": "CVE-2025-48533",
     "osv_id": "ASB-A-383131643",
     "source": "osv",
     "announced": "2025-08-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Makes WindowManager defer removal of an activity's starting window (splash screen) until the transition finishes when the keyguard is locked and the activity does not request showWhenLocked; on Android 16 this is done by removing the keep_app_window_hide_while_locked aconfig gate and adding a null check, while 14/15 receive the full logic.",
      "confidence": "medium",
      "backport_notes": [
       "The Android 16 commit only applies to a tree that already has the flagged implementation; for trees lacking it, use the Android 15 commit as the template, or the Android 14 commit if StartingData.mRemoveAfterTransaction is still a boolean.",
       "Remove the Flags.keepAppWindowHideWhileLocked() call site together with the flag definition, otherwise the build breaks; is_fixed_read_only flags are compiled in at build time (general platform knowledge)."
      ],
      "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-16.0.0_r1",
      "date": "2025-11-20",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-16.0.0_r1",
      "date": "2025-11-20",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "8874f3eae9a911f6991d7df55bdf3d1e24b4f48c",
       "tag": "android-security-16.0.0_r1",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/frameworks/base",
       "sha": "b1c6890620070311e9a5b3ce7c0c6fd2b6ec8885",
       "tag": "android-security-16.0.0_r1",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/frameworks/base",
       "sha": "e595e2ba75092c1819cde4e15598334c956749aa",
       "tag": "android-security-16.0.0_r1",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 3,
     "projects": [
      "platform/frameworks/base"
     ]
    }
   ],
   "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": {
    "CVE-2025-48530": {
     "cve": "CVE-2025-48530",
     "summary": "crabbyavif now allocates image planes with width and height rounded up to even values, allocates and reports only one chroma plane for the Android semi-planar formats (NV12/NV21/P010), and fixes per-format chroma plane width reporting, so plane buffers are no longer undersized for odd-dimension images.",
     "component": "platform/external/rust/crabbyavif (AVIF decoder library), plane allocation and C API (src/capi/image.rs, src/image.rs, src/internal_utils/mod.rs)",
     "weakness": "Incorrect buffer size calculation (undersized plane allocation), CWE-131 class, as evidenced by the diff enlarging allocations to even dimensions; whether resulting accesses are reads or writes is not shown",
     "root_cause": "Plane buffers were sized from the exact image width and height (width * height * pixel_size) in crabby_avifImageCopy, avif_image_allocate_planes_helper and Image::allocate_planes_with_default_values. For images with odd width or height, particularly with the Android semi-planar formats (AndroidNv12, AndroidNv21, AndroidP010), these buffers and row strides were evidently too small for how the planes are used (the commit title refers to \"NV12 crashes\"); the accessing code is not in the diff. In addition, avif_image_allocate_planes_helper allocated planes 1 and 2 for all non-monochrome formats, and crabby_avifImagePlaneWidth computed chroma widths generically from chroma_shift_x for both plane 1 and plane 2, which does not match the semi-planar layout that the fix encodes (plane 1 full width, plane 2 width 0).",
     "fix_analysis": [
      "src/internal_utils/mod.rs: adds round2_function! macro generating round2_u32 (cfg(feature = \"capi\")) and round2_usize, which round an odd value up to the next even value.",
      "src/capi/image.rs:crabby_avifImageCopy: for YUV planes 0..3 and for the alpha plane, the destination allocation size is now alloc_plane_width * alloc_plane_height * pixel_size with both dimensions passed through round2_usize, and dst.yuvRowBytes / dst.alphaRowBytes are set from the rounded width. copy_plane_helper still copies only the real plane_width x plane_height, so the extra space is padding.",
      "src/capi/image.rs:avif_image_allocate_planes_helper: Y plane row bytes and size are computed from round2_u32(image.width) and round2_u32(image.height). Chroma width/height derived from chroma_shift_x/chroma_shift_y are converted with u32_from_u64 and rounded with round2_u32 before computing uv_row_bytes and uv_size. The chroma loop now runs 1..=plane_end where plane_end is 1 for AndroidP010/AndroidNv12/AndroidNv21 and 2 otherwise, so semi-planar formats allocate a single chroma plane.",
      "src/capi/image.rs:crabby_avifImagePlaneWidth: replaces the generic chroma_shift_x computation with explicit per-format results: plane 1 returns width for Yuv444/AndroidP010/AndroidNv12/AndroidNv21, width.div_ceil(2) for Yuv420/Yuv422, 0 for None/Yuv400; plane 2 returns width for Yuv444, width.div_ceil(2) for Yuv420/Yuv422, and 0 for None/Yuv400 and the three Android semi-planar formats.",
      "src/image.rs:Image::allocate_planes_with_default_values: width and height from self.width(plane)/self.height(plane) are passed through round2_usize before computing plane_size and row_bytes, so internally owned plane buffers also have even dimensions; the reuse check compares against the rounded size."
     ],
     "completeness": [
      "Covers the three allocation sites visible in the diff: the C API copy path (crabby_avifImageCopy), the C API allocate-planes helper (avif_image_allocate_planes_helper) and the core Rust allocator (Image::allocate_planes_with_default_values), for both YUV and alpha planes.",
      "The rounding is applied uniformly to all pixel formats, not only to the semi-planar Android formats, so planar odd-dimension images also get padded buffers.",
      "crabby_avifImagePlaneWidth is corrected for plane 1 and plane 2; crabby_avifImagePlaneHeight is not touched in the diff and its behavior for semi-planar plane 2 is not shown in the material.",
      "The fix enlarges buffers rather than adding bounds checks at the accessing code; the code that performs the accesses is not part of the diff, so any other consumer that assumes a different stride or size is not addressed here.",
      "round2_u32 is compiled only with the capi feature; the core path relies on round2_usize only."
     ],
     "behavior_changes": [
      "Plane allocations and row strides (yuvRowBytes, alphaRowBytes, Image::row_bytes) are now even-aligned; odd-width images get one extra sample of padding per row and odd-height images one extra padded row.",
      "For AndroidP010/AndroidNv12/AndroidNv21, avif_image_allocate_planes_helper no longer allocates yuvPlanes[2], and crabby_avifImagePlaneWidth reports 0 for plane 2 and the full image width for plane 1.",
      "In avif_image_allocate_planes_helper, chroma width/height are now converted with u32_from_u64 before use, so values exceeding u32 range return an error where previously they were handled as u64/usize.",
      "Existing planes whose size equals the old unrounded size will no longer pass the reuse check in allocate_planes_with_default_values and will be reallocated."
     ],
     "preconditions": [
      "An AVIF image is decoded or copied through crabbyavif with odd width and/or odd height (the rounding only changes behavior for odd dimensions).",
      "The output pixel format is one of the Android semi-planar formats (AndroidNv12, AndroidNv21, AndroidP010), per the commit title and the plane_end / plane-width special cases; the planar formats also receive padding but the material does not show a crash for them.",
      "Reached via the C API (crabby_avifImageCopy, avif_image_allocate_planes_helper, feature capi) or via the core Image::allocate_planes path; the exact Android caller is not shown in the material."
     ],
     "per_major": {
      "14": "not affected per bulletin; project platform/external/rust/crabbyavif not present in android-security-14.0.0_r29 (code absent)",
      "15": "not affected per bulletin; project not present in android-security-15.0.0_r17 (code absent)",
      "16": "same fix: commit 9bcc1a311114 (cherry-picked from ag/33332267) in android-security-16.0.0_r1; at android-security-16.0.0_r8 6/8 lines of the patched region are present, and the shown context for crabby_avifImageCopy, allocate_planes_with_default_values and the round2 helpers matches the fix",
      "17": "not affected per the bulletin (not listed); at android-security-17.0.0_r1 6/8 lines of the patched region are present"
     },
     "backport_notes": [
      "Single self-contained commit: the source changes depend only on the new round2_u32/round2_usize helpers in src/internal_utils/mod.rs and pre-existing conversion helpers (usize_from_u32, u32_from_u64 at line 145 of the r8 context); keep round2_u32 behind cfg(feature = \"capi\") to match its only user.",
      "Targets with a different crabbyavif snapshot should verify that the PixelFormat enum has the AndroidP010/AndroidNv12/AndroidNv21 variants used in the new match arms in crabby_avifImagePlaneWidth and avif_image_allocate_planes_helper; the plane-width match lists every variant and will fail to compile if variants differ."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which code performs the out-of-bounds access on the undersized planes (decoder output writer, YUV conversion, or mediacodec path) is not in the material.",
      "Whether the crashes were out-of-bounds writes or reads; the bulletin rates it Critical RCE but the diff only shows the allocation-size change.",
      "Why 2 of 8 lines of the patched region differ at android-security-16.0.0_r8 and android-security-17.0.0_r1.",
      "Whether crabby_avifImagePlaneHeight needs a matching per-format change for semi-planar plane 2; it is not in the diff.",
      "The exact Android framework caller and the attack surface (e.g. which image decoding service uses crabbyavif) are not shown."
     ],
     "meta": {
      "generated": "2026-10-02",
      "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-2025-48533": {
     "cve": "CVE-2025-48533",
     "summary": "Makes WindowManager defer removal of an activity's starting window (splash screen) until the transition finishes when the keyguard is locked and the activity does not request showWhenLocked; on Android 16 this is done by removing the keep_app_window_hide_while_locked aconfig gate and adding a null check, while 14/15 receive the full logic.",
     "component": "platform/frameworks/base, WindowManager (services/core/java/com/android/server/wm: ActivityRecord, WindowState, StartingData, Transition)",
     "weakness": "Missing keyguard-state handling on starting window removal: app window content could become visible while the device is locked; on Android 16 additionally a feature gate around the protection and a missing null check on mStartingData.",
     "root_cause": "The starting window inherits lock screen flags from the app's base window in WindowState.adjustStartingWindowFlags. The splash screen may be declared showWhenLocked (commit message), and when the app's TYPE_BASE_APPLICATION window lacks FLAG_SHOW_WHEN_LOCKED, the flag is dropped from the starting window attrs without tying starting window removal to the keyguard unoccluding transition, so app content could briefly appear while the keyguard was locked and the activity had not requested showWhenLocked (commit comment: 'prevents briefly appearing the app context and causing secure concern'). On Android 16 the trigger in adjustStartingWindowFlags was gated behind Flags.keepAppWindowHideWhileLocked() (is_fixed_read_only bugfix flag), and deferStartingWindowRemovalForKeyguardUnoccluding dereferenced mStartingData without a null check.",
     "fix_analysis": [
      "Android 16 commit (8874f3eae9a9 / b1c689062007 / e595e2ba7509 are the same change, Change-Id Id4db3772950059803883d00f9dd6b94aa98382f0): core/java/android/window/flags/windowing_frontend.aconfig removes the keep_app_window_hide_while_locked flag definition.",
      "Android 16: services/core/java/com/android/server/wm/WindowState.java:adjustStartingWindowFlags drops the Flags.keepAppWindowHideWhileLocked() condition, so whenever the starting window had FLAG_SHOW_WHEN_LOCKED and the base window lacks it, mActivityRecord.checkKeyguardFlagsChanged() and mActivityRecord.deferStartingWindowRemovalForKeyguardUnoccluding() are called.",
      "Android 16: services/core/java/com/android/server/wm/ActivityRecord.java:deferStartingWindowRemovalForKeyguardUnoccluding adds 'mStartingData != null &&' before reading mStartingData.mRemoveAfterTransaction. The method sets mRemoveAfterTransaction = AFTER_TRANSITION_FINISH when isKeyguardLocked() && !canShowWhenLockedInner(this) && !isVisibleRequested() && mTransitionController.inTransition(this).",
      "Android 16 context also shows ActivityRecord.removeStartingWindow returning early while mRemoveAfterTransaction == AFTER_TRANSITION_FINISH.",
      "Android 14 and 15 commits (71773c9f03af, 9916e7bbbf44): add StartingData.AFTER_TRANSITION_FINISH, deferStartingWindowRemovalForKeyguardUnoccluding, the removeStartingWindow early return, a Transition.java cleanup (reset to AFTER_TRANSACTION_IDLE and ar.removeStartingWindow() once the activity is not visible or not in transition), a WindowState visibility gate returning false for the activity's non-TYPE_APPLICATION_STARTING windows while AFTER_TRANSITION_FINISH is set, a reset to AFTER_TRANSACTION_IDLE when the starting window is moved from another activity, and the adjustStartingWindowFlags trigger, without any flag. Android 14 additionally converts StartingData.mRemoveAfterTransaction from boolean to an @AfterTransaction int, adjusts transferSplashScreenIfNeeded, the sync-commit handler and the removeStartingWindowAnimation deferral accordingly, and introduces the static canShowWhenLockedInner(ActivityRecord) helper used by canShowWhenLocked."
     ],
     "completeness": [
      "The deferral is only triggered from WindowState.adjustStartingWindowFlags for a TYPE_BASE_APPLICATION window whose activity still has mStartingWindow, and only when wasShowWhenLocked && removeShowWhenLocked.",
      "deferStartingWindowRemovalForKeyguardUnoccluding requires mTransitionController.inTransition(this); otherwise removal is not deferred.",
      "In the 14/15 diffs the visibility gate only hides windows of the activity owning mStartingData while mRemoveAfterTransaction == AFTER_TRANSITION_FINISH; the state is cleared in Transition.java and when the starting window is moved to another activity.",
      "On Android 16 the trigger is now unconditional (flag removed); the null check guards against mStartingData being null.",
      "canShowWhenLockedInner checks only the activity itself (mShowWhenLocked or containsShowWhenLockedWindow, not pinned); the mInheritShownWhenLocked case handled by canShowWhenLocked is not consulted by the deferral."
     ],
     "behavior_changes": [
      "When the keyguard is locked and an activity without showWhenLocked attaches its base window during a transition, the splash screen stays until the transition finishes instead of being removed, and checkKeyguardFlagsChanged may trigger an unoccluding animation.",
      "Per the 14/15 diffs, during that deferral the activity's non-starting windows report not visible, preventing the app window from showing during the un-occluding animation.",
      "Android 16: aconfig flag keep_app_window_hide_while_locked no longer exists and Flags.keepAppWindowHideWhileLocked() is no longer referenced.",
      "Android 14: StartingData.mRemoveAfterTransaction changes type from boolean to int."
     ],
     "preconditions": [
      "Keyguard locked (isKeyguardLocked()) while an activity is launched with a starting window.",
      "canShowWhenLockedInner is false for the activity (it is pinned, or has neither mShowWhenLocked nor a show-when-locked window) and the activity is not visible-requested.",
      "Starting window had FLAG_SHOW_WHEN_LOCKED and the app's TYPE_BASE_APPLICATION window lacks it.",
      "Activity is in a transition (mTransitionController.inTransition(this)).",
      "Android 16 only: the fix matters for builds where keep_app_window_hide_while_locked was not enabled; the material does not show the flag's default value."
     ],
     "per_major": {
      "13": "Listed as affected by the bulletin, but no Android 13 fix commit is included in the material; status unknown.",
      "14": "adapted fix: full logic added in android-security-14.0.0_r23 (71773c9f03af), including the boolean-to-int refactor of StartingData.mRemoveAfterTransaction, new canShowWhenLockedInner helper, Transition.java cleanup and WindowState visibility gate; 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "adapted fix: full logic added in android-security-15.0.0_r11 (9916e7bbbf44) on top of the existing int AFTER_TRANSACTION_* states (adds AFTER_TRANSITION_FINISH); 8/8 patched lines present at android-security-15.0.0_r17.",
      "16": "flag-removal fix in android-security-16.0.0_r1 (8874f3eae9a9, b1c689062007, e595e2ba7509, same Change-Id): removes the keep_app_window_hide_while_locked flag, makes the adjustStartingWindowFlags trigger unconditional and adds a null check in deferStartingWindowRemovalForKeyguardUnoccluding; 5/8 region lines present at android-security-16.0.0_r8, and the Java changes appear in the r8 context.",
      "17": "not listed by the bulletin (not affected); 4/8 patched-region lines present at android-security-17.0.0_r1; code not shown."
     },
     "backport_notes": [
      "The Android 16 commit only applies to a tree that already has the flagged implementation; for trees lacking it, use the Android 15 commit as the template, or the Android 14 commit if StartingData.mRemoveAfterTransaction is still a boolean.",
      "Remove the Flags.keepAppWindowHideWhileLocked() call site together with the flag definition, otherwise the build breaks; is_fixed_read_only flags are compiled in at build time (general platform knowledge)."
     ],
     "confidence": "medium",
     "unknowns": [
      "Default value of keep_app_window_hide_while_locked on shipped Android 16 builds.",
      "Whether the Transition.java cleanup, WindowState visibility gate and transfer reset exist on Android 16 (not shown in the 16 context).",
      "Which lines of the patched region are missing at 16.0.0_r8 and 17.0.0_r1.",
      "Android 13 fix commit and its content.",
      "Exact user-visible exposure duration and which keyguard transition types were affected."
     ],
     "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."
     }
    }
   }
  },
  "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/2025-08-01",
  "latest_version": "1.1",
  "latest_revision": {
   "version": "1.1",
   "date": "September 11, 2025",
   "notes": "AOSP links added"
  },
  "revisions": [
   {
    "version": "1.0",
    "date": "August 4, 2025",
    "notes": "Bulletin published"
   },
   {
    "version": "1.1",
    "date": "September 11, 2025",
    "notes": "AOSP links added"
   }
  ],
  "tracked_since": "2026-09-30",
  "changes_since_tracking": [],
  "out_of_scope_rows": {
   "Arm components": 1,
   "Qualcomm closed-source components": 1,
   "Qualcomm components": 1
  },
  "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."
 }
}