{
 "month": "2025-06",
 "generated": "2026-10-06T12:05+00:00",
 "majors": {
  "14": {
   "counts": {
    "announced": 14,
    "certain": 14,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-26441",
     "osv_id": "ASB-A-367274727",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a one-byte bounds check at the top of add_attr in system/stack/sdp/sdp_discovery.cc so the attribute type byte is not read when no bytes remain before p_end.",
      "confidence": "high",
      "backport_notes": [
       "Standalone 5-line insertion with no dependencies. Place it after `nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);` and before `type = *p++;`, and change only the logging call to match the target branch (SDP_TRACE_WARNING or log::warn)."
      ],
      "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_r20",
      "date": "2025-05-05",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r20",
      "date": "2025-05-05",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "d0377d694a8300d2601b249acb6495dd2256d191",
       "tag": "android-security-14.0.0_r20",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 27,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26443",
     "osv_id": "ASB-A-368319929",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "HtmlToSpannedParser in ManagedProvisioning now rejects any URLSpan whose URL is not http:// or https:// (returning null for the whole parsed text) before handing the URL to UrlIntentFactory, so links embedded in the TermsActivity HTML can no longer produce intents for other schemes.",
      "confidence": "medium",
      "backport_notes": [
       "The HtmlToSpannedParser change is self-contained. It needs only android.webkit.URLUtil and ProvisionLogger, which is in the same package. The Android 14 and 15 diffs are identical (same index hashes ca1a09cf7..25eec1833).",
       "The Android 16 DisclaimersParserImpl commit is a separate change in a different file. Decide separately whether to apply it on 14/15; the material does not show its 14/15 state."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/apps/ManagedProvisioning",
       "sha": "69a363847696f6f79f81038cad03c7950bc82054",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/apps/ManagedProvisioning"
     ]
    },
    {
     "cve": "CVE-2025-26445",
     "osv_id": "ASB-A-388828859",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a missing caller permission check to ConnectivityService.offerNetwork so that only holders of NETWORK_FACTORY/MAINLINE_NETWORK_STACK (or MANAGE_TEST_NETWORKS for TRANSPORT_TEST offers) can register a network offer.",
      "confidence": "high",
      "backport_notes": [
       "The fix is a single self-contained hunk. The only difference between branches is the enforceAnyPermissionOf call: with mContext on 14 and 15, without it on 16. When backporting, check that enforceNetworkFactoryPermission, a matching enforceAnyPermissionOf helper, TRANSPORT_TEST and Manifest are all available in ConnectivityService on the target tree."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 10,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Connectivity",
       "sha": "0eccf35b6b1b123996ee41e4cc078cf79c35be89",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Connectivity"
     ]
    },
    {
     "cve": "CVE-2025-26448",
     "osv_id": "ASB-A-309407957",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Replaces malloc with calloc for the inline CursorWindow data buffer in CursorWindow::create() so the buffer is zero-initialized before it can be parcelled to a remote process.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained one-line change with no dependencies; it applies wherever CursorWindow::create() still uses `malloc(window->mSize)` for mData. The bulletin lists Android 13 as affected, but the material includes no 13 commit."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "3c1515f4d1942f2453554315a576ed874703f78b",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26449",
     "osv_id": "ASB-A-387498139",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Changes Zen-mode rule parceling in frameworks/base so that the automatic rules inside ZenModeConfig and the INotificationManager.getZenRules() return value are carried in a ParceledListSlice instead of an inline typed array/List, and switches the string members of ZenModeConfig.ZenRule and AutomaticZenRule (and the rule id array) to String8 encoding.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit in frameworks/base; the AIDL change to getZenRules() requires updating in-tree users (NotificationManager.getAutomaticZenRules() in the diff) in the same change, and writer/reader of ZenModeConfig must be updated together since the parcel format changes. ParceledListSlice (android.content.pm) and Parcel.readString8/writeString8 must be available in the target branch (general platform knowledge).",
       "For branches that already have the Map<String, AutomaticZenRule> getAutomaticZenRules() Binder method or deletedRules (Android 15 style), take the 15/16 variant with AzrWithId and the writeRulesToParcel/readRulesFromParcel helpers rather than the 14 diff."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "e3c4ba3c7963138cb4c189fbec829c08ab27fa08",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26450",
     "osv_id": "ASB-A-331730488",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The IME-side input event receiver (IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent) now checks any KeyEvent with Ctrl/Alt/Fn/Meta modifiers using InputManager.verifyInputEvent plus a 100 ms age check before dispatching it to the InputMethodSession, and drops events that fail.",
      "confidence": "high",
      "backport_notes": [
       "The 14/15 patch is self-contained in IInputMethodSessionWrapper.java. It relies on InputManager.verifyInputEvent (public since API 30) (general platform knowledge). It uses pattern-matching instanceof; if the target branch's Java language level does not support that, use the explicit cast form. Prefer the 14/15 form over the 16 form when backporting: the 16 form depends on the aconfig flag and new API surface and has the weaker && condition.",
       "The bulletin lists Android 13 as affected, but the material includes no 13 commit or 13 code, so how the 14 diff applies there is not shown."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "f48bf9a2e7c728d7010f8c9ad047fa76a869d3d4",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26452",
     "osv_id": "ASB-A-383080440",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Restricts the \"frro:\" drawable-loading branch in ResourcesImpl. The file named in the resource value is now opened only if its canonical path is under /data/resource-cache/, ends in \".frro\" and is readable, and only if the offset parameter is non-negative and the size parameter is positive.",
      "confidence": "high",
      "backport_notes": [
       "Single commit touching two files. The ResourcesManager.java change only adds the RESOURCE_CACHE_DIR constant, which ResourcesImpl.java uses through a new import of android.app.ResourcesManager. Take both hunks together, or inline the constant.",
       "Check that the enclosing code in ResourcesImpl handles IOException from getCanonicalPath. The exception handling is not shown in the hunk."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "37a272435a238d8ca312b3ffeacac7dc348905e7",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26453",
     "osv_id": "ASB-A-395643490",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Changes BluetoothOppSendFileInfo.isContentUriForOtherUser to derive the user id from the decoded Uri authority (text before the last '@') instead of Uri.getUserInfo(), so Bluetooth OPP's cross-user content URI check agrees with how ContentProvider resolves the target user.",
      "confidence": "high",
      "backport_notes": [
       "Single-commit fix. The only functional change is the body of isContentUriForOtherUser. In the shown hunks, the `import android.content.ContentProvider;` added in 15/16 is referenced only by the Javadoc, and the Android 14 commit omits it. To backport the test, TestParameterInjector must be in the unit test static_libs. The Android 14 commit adds it to Android.bp; the 15/16 commits contain no Android.bp change."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "0d3683c8b1c137a8edeea2a6b386deabedfc42ff",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26455",
     "osv_id": "ASB-A-301470262",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Makes the pointer/size pairs returned by the NDK AMediaCodec_getInputBuffer and AMediaCodec_getOutputBuffer APIs consistent (input: base pointer with capacity; output: data pointer with actual size) and sets the offset reported by AMediaCodec_dequeueOutputBuffer to 0 because the output pointer is already offset.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit touching only media/ndk/NdkMediaCodec.cpp and media/ndk/include/media/NdkMediaCodec.h; the .cpp hunks are the same on 14, 15 and 16 (same pre-image on 14/15). The header text refers to behavior 'after API level 35', which does not match the 14/15 backports where behavior changes within an existing API level; this is documentation only.",
       "If a fork has its own code that fills AMediaCodecBufferInfo from the codec's internal offset, consider the same offset = 0 treatment for consistency with AMediaCodec_getOutputBuffer."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "e28ca0c3d70c67cda2a09dc2d663a3395b13c779",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/av"
     ]
    },
    {
     "cve": "CVE-2025-26456",
     "osv_id": "ASB-A-391895923",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Bounds the ART dex-use database in DexUseManagerLocal by capping secondary dex path length (4096), class loader context length (10000) and the number of secondary dex entries per owning package (500). Two follow-up commits first made the companion file-existence check symlink-safe and then removed it entirely because of sepolicy restrictions.",
      "confidence": "high",
      "backport_notes": [
       "Apply in order: the limits commit (Ic50bf22000730282d90a4f6aa1c49379357fe77a), then the symlink fix (Iaa9a716cfe262897e313b994db92855721e1dfcc), then omit-existence-check (Ib6d878a678ddafd02fb48d92ddfbabdfd6f4f14e). The third commit's removed hunk includes comment lines added by the second, so skipping the second needs manual conflict resolution. Required end state: the three MAX_* constants, the two length checks in notifyDexContainersLoaded, the capped computeIfAbsent in addSecondaryDexUse, Injector.getMaxSecondaryDexFilesPerOwner(), and no pathExists check.",
       "On branches where the validation loop uses ArtJni.validateDexPath and validateClassLoaderContext (Android 15 style) rather than Paths.get(...).isAbsolute() (Android 14 style), place the length checks as in ff0ca4365def: the path length check before ArtJni.validateDexPath and the context length check before ArtJni.validateClassLoaderContext."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/art",
       "sha": "06a99377e368b688dbeb4e6bb11b6e1dfca8bb70",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/art",
       "sha": "1aedae6e1049aa794b3554183bf07634c8fa291b",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/art",
       "sha": "3c76194d116bad95e11bda345feaedda6c02c8b4",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 3,
     "projects": [
      "platform/art"
     ]
    },
    {
     "cve": "CVE-2025-26458",
     "osv_id": "ASB-A-388828203",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds options.setPendingIntentBackgroundActivityLaunchAllowed(false) to the BroadcastOptions that LocationPendingIntentTransport in LocationProviderManager.java uses when system_server sends a client-supplied PendingIntent, so these sends explicitly deny background activity launch.",
      "confidence": "medium",
      "backport_notes": [
       "Single-file, two-line change. The diffs for 14, 15 and 16 are identical apart from line offsets. The target branch must provide BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "9d2acb2d3c5dae5ace5add3e1d0c0e3ab5cfb900",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26462",
     "osv_id": "ASB-A-386950836",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds an onNullBinding override to AccessibilityServiceConnection that calls unbindLocked() under mLock, so system_server no longer stays bound to an accessibility service whose onBind() returned null and that service can no longer launch activities from the background (BAL).",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained hunk: add the onNullBinding override after onServiceDisconnected in AccessibilityServiceConnection.java. It uses mLock (already used in the surrounding code) and unbindLocked(); check that unbindLocked() exists in your tree. ServiceConnection#onNullBinding has been a default interface method since API 28 (general platform knowledge).",
       "The commit references the CTS test android.security.cts.Bug_386950836. That test is not part of this diff."
      ],
      "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "7076b2b2bd3cceea45f5d3dfa5ee279da819c9e1",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26463",
     "osv_id": "ASB-A-303227969",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds hard upper bounds (223 chars for packageName, 32 bytes for certificate) to BlobStoreManager.Session.allowPackageAccess on the client side and to BlobStoreSession.allowPackageAccess in system_server, rejecting oversized inputs with IllegalArgumentException.",
      "confidence": "high",
      "backport_notes": [
       "The service file imports MAX_PACKAGE_NAME_LENGTH / MAX_CERTIFICATE_LENGTH from android.app.blob.BlobStoreManager, so both files must be applied together. Google applied the same hunk content on 14, 15 and 16; the only visible difference is a one-line offset in BlobStoreSession.java (base 8eef8cebec3f on 14 vs ede29ec168c0 on 15/16).",
       "The commit adds the Preconditions and Objects imports to BlobStoreManager.java; it adds no such imports to BlobStoreSession.java, so that file already has them on the patched branches."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "4b630be2e2b30ff3c57128c660bfef6514193d25",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-32312",
     "osv_id": "ASB-A-373467684",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a type check in PackageParser's createIntentsList so that a class read by name from a Parcel is only constructed if it is a subclass of IntentInfo. Before, the code reflectively constructed any class named in the parcel.",
      "confidence": "high",
      "backport_notes": [
       "A single self-contained hunk in createIntentsList. It should apply cleanly wherever the Class.forName/getConstructor(Parcel.class) sequence exists; the hunks for 14, 15 and 16 differ only in line offset (7763, 7764, 7782). Android 13 is listed as affected, but the material contains no Android 13 commit."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r21",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "577cdba1048ce04816c962264a11efd02f1f5b73",
       "tag": "android-security-14.0.0_r21",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    }
   ],
   "tags": [
    "android-security-14.0.0_r21"
   ],
   "unannounced": [
    {
     "bug_ids": [
      "315320090"
     ],
     "commits": [
      {
       "project": "platform/packages/modules/Permission",
       "sha": "89b9ab0ec7a47c9e3c2b56b35a13fac73f3b17f4",
       "subject": "Display the system gallery storage permission as system fixed",
       "tag": "android-security-14.0.0_r21",
       "merged": "2025-04-09",
       "markers": []
      }
     ],
     "tags": [
      "android-security-14.0.0_r21"
     ],
     "tag": "android-security-14.0.0_r21"
    }
   ],
   "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-26441": {
     "cve": "CVE-2025-26441",
     "summary": "Adds a one-byte bounds check at the top of add_attr in system/stack/sdp/sdp_discovery.cc so the attribute type byte is not read when no bytes remain before p_end.",
     "component": "platform/packages/modules/Bluetooth, system/stack/sdp (SDP discovery, libbluetooth)",
     "weakness": "Missing bounds check (out-of-bounds read)",
     "root_cause": "add_attr(p, p_end, ...) in system/stack/sdp/sdp_discovery.cc ran `type = *p++;` without first checking that at least one byte remained before p_end. The commit message says that in exceptional cases add_attr can be passed a p pointer 'one byte short of its p_end pointer', which leads to an out-of-bounds read of the next attribute's type byte. The added check rejects p >= p_end. The existing checks (the NULL return from sdpu_get_len_from_type, `(p + attr_len) > p_end`, and `p_attr_end > p_end`) all run after that first dereference.",
     "fix_analysis": [
      "system/stack/sdp/sdp_discovery.cc:add_attr: a new check `if (p + sizeof(uint8_t) > p_end)` is placed after SDP_ADDITIONAL_LIST_MASK is cleared from nest_level and before `type = *p++;`. When it fails, the function logs a warning (SDP_TRACE_WARNING on the 14 and 16 commits, log::warn on 15) and returns NULL.",
      "Returning NULL matches how add_attr already handles failure in its later length checks.",
      "Single commit: 5 inserted lines, no other files touched."
     ],
     "completeness": [
      "Guards the initial type-byte read, which was the read left unguarded before the existing length checks in the add_attr code shown (through line 886). The rest of add_attr is not shown in the material.",
      "The check is defensive and sits in the callee. It does not change the callers that can pass add_attr an exhausted p. Those call sites are not in the material.",
      "The log call passes __func__ as an extra argument to a format string with no %s placeholder (\"bad arguments to add_addr\"). This is cosmetic only."
     ],
     "behavior_changes": [
      "When called with no remaining bytes, add_attr now logs a warning and returns NULL instead of reading past the buffer.",
      "Well-formed input that has at least one byte remaining is not affected by the new check."
     ],
     "preconditions": [
      "SDP discovery parsing in sdp_discovery.cc must reach add_attr, which is static to that file. The existing warning text refers to attr_rsp, i.e. attribute response parsing.",
      "add_attr must be reached with an exhausted p (the commit calls this an exceptional case). The exact input layout that triggers it is not shown."
     ],
     "per_major": {
      "14": "same fix: commit d0377d694a83 in android-security-14.0.0_r20 (SDP_TRACE_WARNING logging); 3/3 lines present at android-security-14.0.0_r29.",
      "15": "adapted fix: commit 5e3953251ab5 in android-security-15.0.0_r8. The check is identical but the warning uses log::warn(\"bad arguments to add_addr\"), and the hunk is at line 304. 3/3 lines present at android-security-15.0.0_r17.",
      "16": "same fix: commit 3e234b3e3c0a in android-16.0.0_r2 (base), SDP_TRACE_WARNING form; 3/3 lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); the patched region is present (3/3 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Standalone 5-line insertion with no dependencies. Place it after `nest_level &= ~(SDP_ADDITIONAL_LIST_MASK);` and before `type = *p++;`, and change only the logging call to match the target branch (SDP_TRACE_WARNING or log::warn)."
     ],
     "confidence": "high",
     "unknowns": [
      "Which caller or path in sdp_discovery.cc passes add_attr an exhausted p. The commit says only 'exceptional cases', and the index search returned no caller chunks.",
      "How callers handle the NULL return.",
      "Whether the rest of add_attr (beyond line 886) has other unguarded reads.",
      "Whether Android 13, which the bulletin lists as affected, received a corresponding commit. The material has no data for 13."
     ],
     "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-2025-26443": {
     "cve": "CVE-2025-26443",
     "summary": "HtmlToSpannedParser in ManagedProvisioning now rejects any URLSpan whose URL is not http:// or https:// (returning null for the whole parsed text) before handing the URL to UrlIntentFactory, so links embedded in the TermsActivity HTML can no longer produce intents for other schemes.",
     "component": "platform/packages/apps/ManagedProvisioning, terms HTML rendering (common/HtmlToSpannedParser, links handled via WebActivity per class javadoc)",
     "weakness": "Missing input validation of the URL scheme on HTML links (improper input validation)",
     "root_cause": "In src/com/android/managedprovisioning/common/HtmlToSpannedParser.java, the parse method iterated all URLSpan objects in the Html.fromHtml result and passed urlSpan.getURL() straight to mUrlIntentFactory.create(), using any non-null intent for the span. It did not check the URL scheme, so links with non-web schemes produced intents. The commit message states this allowed an app to be installed via a link embedded in the TermsActivity.",
     "fix_analysis": [
      "HtmlToSpannedParser.java (URLSpan loop in the parse method): the URL is read into a local `url`, and `isValidURL(url)` runs before `mUrlIntentFactory.create(url)`. If the check fails, the code logs `ProvisionLogger.logw(\"Invalid URL provided. Only HTTP and HTTPS URLs are allowed.\")` and the method returns null at once, so no Spanned is produced for that HTML.",
      "HtmlToSpannedParser.java: adds a new private helper `isValidURL(String url)` that returns `URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url)`, plus a new import of `android.webkit.URLUtil`.",
      "The fix listed for Android 16 is a different commit (5d67902f6a74, DisclaimersParserImpl.java). It adds `validateUriSchemeAndPermission(Uri)`: the disclaimer content Uri must use the scheme `content` or `android.resource`, and `mContext.checkUriPermission(uri, Binder.getCallingPid(), Binder.getCallingUid(), Intent.FLAG_GRANT_READ_URI_PERMISSION)` must be granted. Otherwise a SecurityException is caught and that disclaimer is skipped. This hardening is separate from the HtmlToSpannedParser scheme check."
     ],
     "completeness": [
      "Covers every URLSpan in the Html.fromHtml result inside HtmlToSpannedParser, which is the only place in the diff where URLs become intents. A single non-http(s) link drops the entire result (return null); the span is not just left unclickable.",
      "The validation is a scheme allow-list via URLUtil.isHttpUrl/isHttpsUrl. It does not check host or path.",
      "The fix does not touch the UrlIntentFactory or ClickableSpanFactory implementations, or WebActivity. Whether other code paths turn terms links into intents is not shown.",
      "The DisclaimersParserImpl Uri scheme/permission check seen on Android 16 is not part of the Android 14/15 commits shown."
     ],
     "behavior_changes": [
      "HTML containing any link whose URL is not http:// or https:// now makes HtmlToSpannedParser return null instead of a Spanned with clickable links.",
      "A warning is logged via ProvisionLogger.logw when an invalid URL is found.",
      "On Android 16 (separate commit): a disclaimer is skipped with an error log if its content Uri is not content: or android.resource:, or if the calling pid/uid cannot read it."
     ],
     "preconditions": [
      "HTML rendered through HtmlToSpannedParser in the terms flow (TermsActivity, per the commit message) contains a link with a non-http(s) scheme.",
      "Where that HTML comes from and how the link click is handled are not shown in the material.",
      "The index search surfaced DevicePolicyManager provisioning entry points (createAndProvisionManagedProfile, provisionFullyManagedDevice). These only hint at reachability; the path from them to TermsActivity is not shown."
     ],
     "per_major": {
      "14": "Same fix: commit 69a363847696 in android-security-14.0.0_r21, a cherry-pick of 0eb898e8737f (Change-Id I58a5f31812ec5e1ae5675f959201d4237c888ee3) that changes only HtmlToSpannedParser.java. At android-security-14.0.0_r29, 7 of the 8 lines of the patched region are present; the material does not show which line differs.",
      "15": "Same fix: commit a3172895010e in android-security-15.0.0_r9, with a diff identical to the Android 14 commit. At android-security-15.0.0_r17, 7 of the 8 lines are present.",
      "16": "Resolved in base (android-16.0.0_r2). The HtmlToSpannedParser patched region is fully present (8 of 8 lines) at android-security-16.0.0_r8. The fix listed for Android 16 is a different change, 5d67902f6a74 in DisclaimersParserImpl.java (Uri scheme and caller URI-permission validation).",
      "17": "Not affected: the bulletin does not list Android 17. At android-security-17.0.0_r1, 7 of the 8 lines of the HtmlToSpannedParser patched region are present."
     },
     "backport_notes": [
      "The HtmlToSpannedParser change is self-contained. It needs only android.webkit.URLUtil and ProvisionLogger, which is in the same package. The Android 14 and 15 diffs are identical (same index hashes ca1a09cf7..25eec1833).",
      "The Android 16 DisclaimersParserImpl commit is a separate change in a different file. Decide separately whether to apply it on 14/15; the material does not show its 14/15 state."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which line of the 8-line patched region differs at the latest 14, 15 and 17 security tags.",
      "Whether the DisclaimersParserImpl change (Android 16) was also applied to 14/15, and whether it is formally part of this CVE.",
      "The name of the HtmlToSpannedParser method that contains the URLSpan loop, and how callers (TermsActivity) handle the new null return.",
      "Where the terms HTML comes from (for example, whether it comes from EXTRA_PROVISIONING_DISCLAIMERS) and how a link click launches the intent.",
      "The concrete UrlIntentFactory implementation used in production."
     ],
     "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-2025-26445": {
     "cve": "CVE-2025-26445",
     "summary": "Adds a missing caller permission check to ConnectivityService.offerNetwork so that only holders of NETWORK_FACTORY/MAINLINE_NETWORK_STACK (or MANAGE_TEST_NETWORKS for TRANSPORT_TEST offers) can register a network offer.",
     "component": "platform/packages/modules/Connectivity, ConnectivityService (network provider / network offer binder API)",
     "weakness": "missing permission check",
     "root_cause": "The binder entry point ConnectivityService.offerNetwork(providerId, score, caps, callback) only null-checked its arguments. It then posted EVENT_REGISTER_NETWORK_OFFER with a NetworkOffer built from the score, capabilities and callback that the caller supplied. The sibling entry points registerNetworkProvider and unregisterNetworkProvider call enforceNetworkFactoryOrSettingsPermission, but offerNetwork enforced no caller permission, although the ConnectivityManager API annotations require NETWORK_FACTORY or MAINLINE_NETWORK_STACK. Per the commit message, an unauthorized app could register a network offer under an existing provider ID (trivially guessed) and intercept all NetworkRequests. This leaked information about other apps (bulletin type ID, severity High).",
     "fix_analysis": [
      "service/src/com/android/server/ConnectivityService.java:offerNetwork: after the Objects.requireNonNull checks and before the NetworkOffer is built, the fix branches on caps.hasTransport(TRANSPORT_TEST).",
      "If the offered capabilities include TRANSPORT_TEST, the fix calls enforceAnyPermissionOf(mContext, Manifest.permission.MANAGE_TEST_NETWORKS). The commit message says this is consistent with similar APIs in the class.",
      "Otherwise the fix calls enforceNetworkFactoryPermission(). Per the commit message, this requires NETWORK_FACTORY or MAINLINE_NETWORK_STACK, matching the ConnectivityManager annotations.",
      "The enforce calls run before EVENT_REGISTER_NETWORK_OFFER is posted to mHandler, so a caller that fails the check does not get an offer queued."
     ],
     "completeness": [
      "Covers the unguarded binder entry point offerNetwork. The check runs before the offer is posted to mHandler.",
      "The check covers only the caller's permission. At this entry point, providerId is still not validated against a provider registered by the caller, but the permission check now limits offerNetwork to privileged callers.",
      "unofferNetwork(callback) still has no permission check. The commit message says this is consistent with the ConnectivityManager API annotations. The function acts only on the callback the caller supplies.",
      "TRANSPORT_TEST offers are gated by MANAGE_TEST_NETWORKS rather than the factory permission. Because caps.hasTransport(TRANSPORT_TEST) is checked first, an offer whose capabilities include TRANSPORT_TEST takes the test branch even if it also lists other transports."
     ],
     "behavior_changes": [
      "offerNetwork now rejects callers that lack NETWORK_FACTORY or MAINLINE_NETWORK_STACK (non-test offers) or MANAGE_TEST_NETWORKS (offers with TRANSPORT_TEST). The material does not show the exact exception thrown.",
      "registerNetworkProvider accepts callers that pass enforceNetworkFactoryOrSettingsPermission, but offerNetwork now requires enforceNetworkFactoryPermission (or the test permission). A provider allowed to register only through the settings side of that check may now be refused at offerNetwork."
     ],
     "preconditions": [
      "The caller can reach the IConnectivityManager binder. offerNetwork is @hide and exposed via NetworkProvider. The commit message says an unauthorized app could call it.",
      "The caller supplies a providerId matching an existing registered provider (per the commit message, trivially guessable) and capabilities and score that match outstanding requests.",
      "Before the fix no permission was needed. After the fix the caller must hold the factory/mainline-stack permission or the test-network permission."
     ],
     "per_major": {
      "14": "same fix: commit 0eccf35b6b1b in android-security-14.0.0_r21 (cherry-pick of ff65257bd07c), using enforceAnyPermissionOf(mContext, ...). All 6/6 lines of the patched region are present at android-security-14.0.0_r29.",
      "15": "same fix: commit a2d3f541c78e in android-security-15.0.0_r9. The hunk is identical apart from the line offset. All 6/6 lines are present at android-security-15.0.0_r17.",
      "16": "adapted fix: commit f27bca2d7d23 in android-16.0.0_r2 (base). It calls enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS) without the mContext argument. All 6/6 lines are present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). The patched region is fully present (6/6 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The fix is a single self-contained hunk. The only difference between branches is the enforceAnyPermissionOf call: with mContext on 14 and 15, without it on 16. When backporting, check that enforceNetworkFactoryPermission, a matching enforceAnyPermissionOf helper, TRANSPORT_TEST and Manifest are all available in ConnectivityService on the target tree."
     ],
     "confidence": "high",
     "unknowns": [
      "The diff does not show the exact permission set checked by enforceNetworkFactoryPermission and enforceAnyPermissionOf, or the exception they throw. The NETWORK_FACTORY / MAINLINE_NETWORK_STACK description comes from the commit message.",
      "The bulletin lists Android 13 as affected, but the material contains no Android 13 commit, so it does not show whether 13 received the fix.",
      "The commit says 'Test: TH'. The shown diff contains no test changes."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 10,
      "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-26448": {
     "cve": "CVE-2025-26448",
     "summary": "Replaces malloc with calloc for the inline CursorWindow data buffer in CursorWindow::create() so the buffer is zero-initialized before it can be parcelled to a remote process.",
     "component": "platform/frameworks/base, libs/androidfw CursorWindow (android.database cursor window native backing)",
     "weakness": "Use of uninitialized heap memory leading to information disclosure (uninitialized buffer contents sent across process boundary)",
     "root_cause": "CursorWindow::create() allocated the inline window buffer (mSize = min(kInlineSize=16384, inflatedSize)) with malloc(window->mSize), leaving the bytes uninitialized. Per the commit message, the caller might not fully fill that buffer before sending it to the remote end, so uninitialized heap contents of the creating process could be transmitted. The commit message says createFromParcel() does not need zeroing because its buffer is immediately filled from the far end.",
     "fix_analysis": [
      "libs/androidfw/CursorWindow.cpp:CursorWindow::create(): change `window->mData = malloc(window->mSize);` to `window->mData = calloc(window->mSize, 1);` so every byte of the inline buffer is zero before window->clear() and updateSlotsData() run and before any later writes or parcelling. The failure check (`if (!window->mData) goto fail;`) is unchanged."
     ],
     "completeness": [
      "Covers only the inline (heap) buffer allocated in CursorWindow::create(). This is the single allocation the commit identifies as reaching the remote end partially filled.",
      "CursorWindow::createFromParcel() is intentionally left unchanged; the commit message states its buffer is immediately filled from the far end.",
      "This diff does not touch the ashmem-backed buffer allocated in CursorWindow::maybeInflate() (which starts at line 75 of the context; its body is not shown). The material does not show whether that buffer needed zeroing."
     ],
     "behavior_changes": [
      "Inline CursorWindow buffers (up to 16 KiB) are now zero-filled at allocation, with a slight extra cost from calloc versus malloc.",
      "No API, error code, or control-flow change; failure handling is identical."
     ],
     "preconditions": [
      "A process creates a CursorWindow through CursorWindow::create() (the inline allocation path, not createFromParcel()).",
      "Per the commit message, the creator does not fully fill the inline buffer before the window is sent to the remote end.",
      "The material does not show the exact caller chain into CursorWindow::create(). The index results for 'create' (per index search) were unrelated Telephony/UserManager/SQLiteDatabase matches and did not help."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 3c1515f4d194 in android-security-14.0.0_r21 (one-line malloc->calloc in CursorWindow::create), cherry-picked from 9dc64621d896 per its commit message; 6/6 lines of the patched region present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/base b7d9d1744c4f in android-security-15.0.0_r9, identical diff; 6/6 lines present at android-security-15.0.0_r17.",
      "16": "same fix: platform/frameworks/base 9dc64621d896 in android-16.0.0_r2; 6/6 lines present at android-security-16.0.0_r8.",
      "17": "not affected: not listed by the bulletin; the calloc line is present at android-security-17.0.0_r1 (6/6 lines)."
     },
     "backport_notes": [
      "Single self-contained one-line change with no dependencies; it applies wherever CursorWindow::create() still uses `malloc(window->mSize)` for mData. The bulletin lists Android 13 as affected, but the material includes no 13 commit."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show which caller or Java-side path leaves the inline buffer partially filled before parcelling.",
      "The material does not show whether the maybeInflate() ashmem path needs zeroing or was assessed separately.",
      "No Android 13 fix commit is present in the material, although the bulletin lists 13 as affected.",
      "The Android 15 commit message is not shown in full, so its cherry-pick origin is not confirmed."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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-26449": {
     "cve": "CVE-2025-26449",
     "summary": "Changes Zen-mode rule parceling in frameworks/base so that the automatic rules inside ZenModeConfig and the INotificationManager.getZenRules() return value are carried in a ParceledListSlice instead of an inline typed array/List, and switches the string members of ZenModeConfig.ZenRule and AutomaticZenRule (and the rule id array) to String8 encoding.",
     "component": "platform/frameworks/base, NotificationManagerService / Zen mode (ZenModeConfig, AutomaticZenRule, INotificationManager)",
     "weakness": "unknown (bulletin type: DoS); the fix design (moving the rule list into a ParceledListSlice) suggests the concern is serialization of a variable-size rule list in a single parcel, but the material does not state the concrete flaw",
     "root_cause": "Before the fix, ZenModeConfig.writeToParcel serialized every entry of automaticRules inline (dest.writeStringArray(ids) plus dest.writeTypedArray(rules, 0)) and ZenModeConfig(Parcel) read them back with readStringArray/readTypedArray, so the whole rule set was written into a single parcel. NotificationManagerService.getZenRules() returned a plain List<ZenModeConfig.ZenRule> over Binder. String members of ZenRule (name, id, enabler, pkg) and AutomaticZenRule (name, mPkg) were written with writeString. The bulletin classifies the issue as DoS; the exact failure mechanism is inferred from the fix, not shown in the material.",
     "fix_analysis": [
      "core/java/android/service/notification/ZenModeConfig.java: writeToParcel now builds an ArrayList<ZenRule> and writes dest.writeString8Array(ids) followed by dest.writeParcelable(new ParceledListSlice<>(rules), flags) after the length int, instead of writeStringArray/writeTypedArray.",
      "core/java/android/service/notification/ZenModeConfig.java: the ZenModeConfig(Parcel) constructor reads ids with readString8Array, reads a ParceledListSlice via source.readParcelable(ZenRule.class.getClassLoader(), ParceledListSlice.class), tolerates a null slice (empty list), and if the slice size differs from the declared len it logs Slog.wtf and sets len = 0 so no rules are inserted; otherwise entries are cast to ZenRule and put into automaticRules.",
      "core/java/android/service/notification/ZenModeConfig.java ZenRule(Parcel)/ZenRule.writeToParcel: name, id, enabler and pkg switched from readString/writeString to readString8/writeString8.",
      "core/java/android/app/AutomaticZenRule.java AutomaticZenRule(Parcel)/writeToParcel: name and mPkg switched to readString8/writeString8.",
      "core/java/android/app/INotificationManager.aidl: getZenRules() return type changed from List<ZenModeConfig.ZenRule> to ParceledListSlice<ZenModeConfig.ZenRule>.",
      "services/core/java/com/android/server/notification/NotificationManagerService.java getZenRules(): still calls enforcePolicyAccess(Binder.getCallingUid(), \"getAutomaticZenRules\") and now wraps mZenModeHelper.getZenRules() in new ParceledListSlice<ZenModeConfig.ZenRule>(...).",
      "core/java/android/app/NotificationManager.java getAutomaticZenRules(): consumes the ParceledListSlice and iterates rules.getList() to build the Map<String, AutomaticZenRule>.",
      "services/tests/uiservicestests/.../ZenModeConfigTest.java: adds testWriteConfigToParcel, a round-trip of a ZenModeConfig with two automatic rules through Parcel asserting equality."
     ],
     "completeness": [
      "Covers the automaticRules map in ZenModeConfig parceling and the getZenRules() Binder return path; on Android 15/16 the same treatment is also applied to deletedRules (writeRulesToParcel/readRulesFromParcel) and to the Map-returning getAutomaticZenRules() via a new AutomaticZenRule.AzrWithId parcelable.",
      "The reader drops all rules (Slog.wtf) when the slice size differs from the declared count rather than throwing; a null slice is treated as empty.",
      "manualRule in ZenModeConfig is still written with a single dest.writeParcelable(manualRule, 0); it is a single rule and is not changed.",
      "Strings in nested parcelables referenced from rules (ZenPolicy, Condition, Uri, ComponentName) are not touched by this change; only ZenRule and AutomaticZenRule string members move to String8.",
      "getZenModeConfig() in INotificationManager still returns a ZenModeConfig directly (restricted by enforceSystemOrSystemUI); it is affected only through the ZenModeConfig parcel format change.",
      "No cap on the number or size of rules is introduced; the fix changes transport encoding, not the amount of data stored."
     ],
     "behavior_changes": [
      "ZenModeConfig's parcel wire format changes (String8 arrays, ParceledListSlice for rules); writer and reader must both be patched to interoperate.",
      "INotificationManager.getZenRules() AIDL signature changes to ParceledListSlice<ZenModeConfig.ZenRule>; any out-of-tree caller or implementer of this hidden interface must be updated.",
      "If the deserialized rule count does not match the declared count, all automatic rules are discarded from that ZenModeConfig instance with a Slog.wtf log.",
      "AutomaticZenRule and ZenModeConfig.ZenRule string fields are encoded as String8 (UTF-8) on the wire.",
      "On Android 15 the getZenRules() enforcePolicyAccess label changed from \"getZenRules\" to \"getAutomaticZenRules\"."
     ],
     "preconditions": [
      "Caller must hold notification policy access (enforcePolicyAccess in NotificationManagerService.getZenRules / addAutomaticZenRule) to add rules or fetch them via NotificationManager.getAutomaticZenRules().",
      "Inferred from the fix, not shown: the issue presumably involves serializing a ZenModeConfig or rule list with many rules and/or long string fields across Binder (getZenRules() or getZenModeConfig()); no threshold is shown."
     ],
     "per_major": {
      "14": "adapted fix: commit e3c4ba3c7963 in android-security-14.0.0_r21 (cherry-picked from 3965123f4403 and a35b3ddd3893). Only getZenRules() and the automaticRules parcel path are changed in 14 (no getAutomaticZenRules Binder method in the 14 AIDL context, no deletedRules, no AzrWithId); 7/8 patched lines present at android-security-14.0.0_r29.",
      "15": "adapted fix: commit e0a1e45a3d20 in android-security-15.0.0_r9. Additionally adds AutomaticZenRule.AzrWithId (declared in AutomaticZenRule.aidl), changes getAutomaticZenRules() to ParceledListSlice<AzrWithId> under Flags.modesApi(), applies ParceledListSlice to both automaticRules and deletedRules via writeRulesToParcel/readRulesFromParcel, and converts the flag-gated String fields (mTriggerDescription, iconResName, triggerDescription); 7/8 lines present at android-security-15.0.0_r17.",
      "16": "base fix: commit 3965123f4403 in android-16.0.0_r2. getZenRules() is not present in the 16 AIDL; getAutomaticZenRules() returns a raw ParceledListSlice of AzrWithId; the modesApi flag checks are absent from these parcel paths (modesUi checks remain); 7/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); 6/8 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained commit in frameworks/base; the AIDL change to getZenRules() requires updating in-tree users (NotificationManager.getAutomaticZenRules() in the diff) in the same change, and writer/reader of ZenModeConfig must be updated together since the parcel format changes. ParceledListSlice (android.content.pm) and Parcel.readString8/writeString8 must be available in the target branch (general platform knowledge).",
      "For branches that already have the Map<String, AutomaticZenRule> getAutomaticZenRules() Binder method or deletedRules (Android 15 style), take the 15/16 variant with AzrWithId and the writeRulesToParcel/readRulesFromParcel helpers rather than the 14 diff."
     ],
     "confidence": "medium",
     "unknowns": [
      "The material does not state the concrete failure mode (which process fails, which exception) or any size threshold.",
      "Why the String8 switch is part of the security fix is not explained in the material.",
      "Whether any limit on the number of automatic zen rules per package or per user exists in these branches is not shown.",
      "The index results labelled Android 14 contain Flags.modesApi code that does not match the 14 security-branch diff, so the index snapshot's branch is uncertain."
     ],
     "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-2025-26450": {
     "cve": "CVE-2025-26450",
     "summary": "The IME-side input event receiver (IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent) now checks any KeyEvent with Ctrl/Alt/Fn/Meta modifiers using InputManager.verifyInputEvent plus a 100 ms age check before dispatching it to the InputMethodSession, and drops events that fail.",
     "component": "platform/frameworks/base, input method framework (android.inputmethodservice, IME-side InputChannel receiver)",
     "weakness": "Missing check that input events come from the system (trust of data received over an IPC channel)",
     "root_cause": "ImeInputEventReceiver.onInputEvent in core/java/android/inputmethodservice/IInputMethodSessionWrapper.java accepted InputEvents arriving on the IME's InputChannel and passed KeyEvents straight to mInputMethodSession.dispatchKeyEvent without checking that they came from the system. Per the commit message, a malicious app can inject fabricated InputEvents into the IME's FD. Modifier-key shortcuts handled by the IME (the message cites switching IME) could therefore be triggered by events that did not come from the system.",
     "fix_analysis": [
      "core/java/android/inputmethodservice/IInputMethodSessionWrapper.java: the constructor now stores the Context in a new field mContext, so the receiver can obtain InputManager.",
      "IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent: after the existing early-return path and before mPendingEvents.put/dispatch, if the event is a KeyEvent and hasKeyModifiers(keyEvent) is true, it fetches InputManager (Objects.requireNonNull) and computes age = SystemClock.uptimeMillis() - keyEvent.getEventTime(). If age >= KEY_EVENT_ALLOW_PERIOD_MS (100 ms) OR im.verifyInputEvent(keyEvent) == null, it logs a warning, calls finishInputEvent(event, false) and returns, so the event never reaches InputMethodSession.dispatchKeyEvent.",
      "New private helper ImeInputEventReceiver.hasKeyModifiers(KeyEvent): returns false if event.hasNoModifiers(), otherwise returns true when isCtrlPressed() || isAltPressed() || isFunctionPressed() || isMetaPressed().",
      "The dispatch code is otherwise unchanged, apart from switching to pattern-matching instanceof (event instanceof KeyEvent keyEvent)."
     ],
     "completeness": [
      "Only KeyEvents for which hasKeyModifiers() is true (Ctrl, Alt, Function, Meta) are verified. KeyEvents with no modifiers, or with only other modifiers (e.g. Shift alone, for which hasKeyModifiers returns false), are still dispatched without verification.",
      "The MotionEvent branch of the same onInputEvent gets no verification.",
      "The check lives only in the IME-process receiver (IInputMethodSessionWrapper). Nothing in the diff changes how the InputChannel is created or who can write to it, so the fix filters on the receiving side rather than hardening the channel.",
      "The Android 16 variant (47414432d61c) is weaker in two visible ways. First, the drop condition uses && (age >= 100 ms AND unverified), so modifier KeyEvents younger than 100 ms are dispatched without HMAC verification. Second, hasKeyModifiers uses hasModifiers(META_CTRL_ON) || hasModifiers(META_ALT_ON) || hasModifiers(KeyEvent.KEYCODE_FUNCTION) (KEYCODE_FUNCTION is a key code constant, not a meta flag) and no longer checks Meta. The check is also gated by the verify_key_event aconfig flag. The 16 diff contains a TODO(b/331730488) noting that accessibility events are not yet handled.",
      "The 14 and 15 backports verify every modifier KeyEvent (|| condition) and are the stricter form."
     ],
     "behavior_changes": [
      "Modifier (Ctrl/Alt/Fn/Meta) KeyEvents whose eventTime is 100 ms or more behind SystemClock.uptimeMillis() are dropped by the IME even if legitimate (14/15 variant).",
      "Modifier KeyEvents that InputManager.verifyInputEvent cannot verify are dropped with Log.w \"Unverified or Invalid KeyEvent injected into IME. Dropping ...\" and finished with handled=false. They are not delivered to the IME and are reported back as unhandled.",
      "Objects.requireNonNull on the InputManager service: a null service now throws instead of dispatching.",
      "Android 16 only: a new public API, onShouldVerifyKeyEvent(KeyEvent), on InputMethodService / AbstractInputMethodService (with a hidden default on InputMethodSession) lets an IME request verification for additional keys. A new fixed-read-only flag, android.view.inputmethod.verify_key_event, controls the whole check."
     ],
     "preconditions": [
      "An IME session must exist. The receiver is created when IInputMethodWrapper.InputMethodSessionCallbackWrapper.sessionCreated constructs new IInputMethodSessionWrapper(mContext, session, mChannel) in the IME process (per index search).",
      "Per the commit message, an attacker app must be able to write fabricated InputEvents into the IME's InputChannel FD. How the app gets that access is not shown in the material.",
      "Before the fix, any KeyEvent delivered on that channel was dispatched. The 14/15 fix only intercepts those with Ctrl/Alt/Fn/Meta modifiers."
     ],
     "per_major": {
      "14": "same fix: DO NOT MERGE cherry-pick f48bf9a2e7c7 in android-security-14.0.0_r21 (single file, || drop condition, isCtrlPressed/isAltPressed/isFunctionPressed/isMetaPressed, no flag); 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "same fix: identical DO NOT MERGE diff 4cafc04ee7db in android-security-15.0.0_r9; 8/8 lines present at android-security-15.0.0_r17.",
      "16": "adapted fix: Revert^2 \"Verify KeyEvents in IME\" 47414432d61c in android-16.0.0_r2. It is gated by the aconfig flag verify_key_event (is_fixed_read_only), adds the onShouldVerifyKeyEvent API to InputMethodService/AbstractInputMethodService/InputMethodSession and current.txt, and uses an && drop condition and a different hasKeyModifiers; 8/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin; the patched region is present (8/8 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The 14/15 patch is self-contained in IInputMethodSessionWrapper.java. It relies on InputManager.verifyInputEvent (public since API 30) (general platform knowledge). It uses pattern-matching instanceof; if the target branch's Java language level does not support that, use the explicit cast form. Prefer the 14/15 form over the 16 form when backporting: the 16 form depends on the aconfig flag and new API surface and has the weaker && condition.",
      "The bulletin lists Android 13 as affected, but the material includes no 13 commit or 13 code, so how the 14 diff applies there is not shown."
     ],
     "confidence": "high",
     "unknowns": [
      "How an unprivileged app gets write access to the IME's InputChannel FD is not shown; only the commit message asserts it.",
      "Whether the 16 variant's && condition and KEYCODE_FUNCTION usage were intentional or later corrected is not shown in the material.",
      "Whether legitimate sources without a valid HMAC (e.g. accessibility or instrumentation injection) are affected by the drop is not shown, beyond the TODO about a11y events in the 16 diff.",
      "The Android 13 fix commit and the Android 13 code are not included, so whether the 14 diff applies cleanly to 13 is unknown."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26452": {
     "cve": "CVE-2025-26452",
     "summary": "Restricts the \"frro:\" drawable-loading branch in ResourcesImpl. The file named in the resource value is now opened only if its canonical path is under /data/resource-cache/, ends in \".frro\" and is readable, and only if the offset parameter is non-negative and the size parameter is positive.",
     "component": "platform/frameworks/base, core resources (ResourcesImpl drawable loading for fabricated runtime resource overlays, ResourcesManager)",
     "weakness": "Missing validation of a file path and an offset/size taken from resource data (improper limitation of a pathname / improper input validation)",
     "root_cause": "In core/java/android/content/res/ResourcesImpl.java, when a drawable resource's string value started with \"frro://\", the code parsed it as a Uri and built a File from '/' + host + path. It opened that file with ParcelFileDescriptor.open(MODE_READ_ONLY), wrapped it in an AssetFileDescriptor using the unchecked \"offset\" and \"size\" query parameters, and decoded it as an image. Nothing limited the file to the fabricated-overlay cache directory or to .frro files. Any process loading such a resource value would therefore open and decode whatever readable file the value pointed to, at any offset and size.",
     "fix_analysis": [
      "core/java/android/app/ResourcesManager.java: adds public static final String RESOURCE_CACHE_DIR = \"/data/resource-cache/\" and makes overlayPathToIdmapPath use it. This is a pure refactor so that ResourcesImpl can share the constant.",
      "core/java/android/content/res/ResourcesImpl.java (frro drawable-loading branch; the enclosing method is not shown in the hunk): widens the prefix test from \"frro://\" to \"frro:/\". Values that start with \"frro:/\" but not \"frro://\" now go through the validated branch instead of falling through to the following else branch.",
      "ResourcesImpl.java: parses offset and size up front and throws NotFoundException(\"invalid frro parameters\") if offset < 0 or size <= 0.",
      "ResourcesImpl.java: after building File f, requires that f.getCanonicalPath() starts with ResourcesManager.RESOURCE_CACHE_DIR, that it ends with \".frro\", and that f.canRead() is true. Otherwise it throws NotFoundException(\"invalid frro path\"). Only after these checks does it open the ParcelFileDescriptor and build the AssetFileDescriptor with the already-validated offset and size."
     ],
     "completeness": [
      "Covers the single frro drawable branch in ResourcesImpl. The material shows no other consumer of frro: values.",
      "getCanonicalPath() resolves symlinks before the prefix check, so a symlink inside /data/resource-cache/ that points elsewhere is rejected. A null host yields \"/null...\", which also fails the prefix check.",
      "Does not check that offset+size lies within the file, or that the .frro file belongs to the overlay the resource value came from. Any readable .frro file under /data/resource-cache/ is accepted.",
      "A missing or non-numeric offset or size still makes Long.parseLong throw NumberFormatException. How that exception, and an IOException from getCanonicalPath, are handled depends on enclosing exception handling that the hunk does not show."
     ],
     "behavior_changes": [
      "frro drawable values that point outside /data/resource-cache/, do not end in .frro, or are not readable now fail with Resources.NotFoundException(\"invalid frro path\") instead of loading.",
      "A negative offset or a non-positive size now fails with NotFoundException(\"invalid frro parameters\").",
      "Values starting with \"frro:/\" (single slash) now go to the frro branch rather than the following else branch.",
      "New public constant ResourcesManager.RESOURCE_CACHE_DIR (the class is @hide)."
     ],
     "preconditions": [
      "A process loads, through ResourcesImpl, a drawable resource whose resolved string value begins with \"frro:/\" (a fabricated-overlay style value).",
      "The value's host/path, offset and size come from resource data and were used without validation before the fix. The file must be readable by the loading process."
     ],
     "per_major": {
      "14": "same fix: cherry-pick 37a272435a23 in android-security-14.0.0_r21 (Merged-In I4247e54f3ea0d9e4bf0d9f404e0272751a258ba2). 7/8 lines of the patched region are still present at android-security-14.0.0_r29.",
      "15": "same fix: 26c58543f19d in android-security-15.0.0_r9. Same diff content at different line offsets. 6/8 lines present at android-security-15.0.0_r17.",
      "16": "same fix: original commit 12e49e7a4e56 in android-16.0.0_r2. 6/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). 5/8 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single commit touching two files. The ResourcesManager.java change only adds the RESOURCE_CACHE_DIR constant, which ResourcesImpl.java uses through a new import of android.app.ResourcesManager. Take both hunks together, or inline the constant.",
      "Check that the enclosing code in ResourcesImpl handles IOException from getCanonicalPath. The exception handling is not shown in the hunk."
     ],
     "confidence": "high",
     "unknowns": [
      "Which privileged processes load attacker-supplied resource values through this branch (the bulletin only states EoP, High).",
      "The name of the enclosing method and its exception handling, which the hunk does not show.",
      "What the else branch after the frro branch does.",
      "Whether other code paths consume frro: values (none shown in the material)."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26453": {
     "cve": "CVE-2025-26453",
     "summary": "Changes BluetoothOppSendFileInfo.isContentUriForOtherUser to derive the user id from the decoded Uri authority (text before the last '@') instead of Uri.getUserInfo(), so Bluetooth OPP's cross-user content URI check agrees with how ContentProvider resolves the target user.",
     "component": "platform/packages/modules/Bluetooth, OPP (Object Push Profile) send path, android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java",
     "weakness": "Inconsistent URI parsing between a security check and the component that acts on the URI (the check used Uri.getUserInfo(), while ContentProvider uses the decoded authority). This let a percent-encoded '@' bypass the other-user check.",
     "root_cause": "isContentUriForOtherUser() in BluetoothOppSendFileInfo.java got the user id from uri.getUserInfo(). The new Javadoc in the diff explains that ContentProvider APIs instead pass the decoded Uri.getAuthority() to ContentProvider#getUserIdFromAuthority. ContentProvider therefore treats an encoded '@' ('%40') in the authority as the separator between userInfo and host, but Uri.getUserInfo() does not treat it as a separator. A content URI that put another user's id in front of an encoded '@' could pass the OPP check while being resolved by ContentProvider as another user's URI. This is consistent with the bulletin type ID (information disclosure).",
     "fix_analysis": [
      "BluetoothOppSendFileInfo.java:isContentUriForOtherUser: replaces `String uriUserId = uri.getUserInfo();` with these steps: get `uri.getAuthority()` (decoded form); return false if it is null; find `authority.lastIndexOf('@')`; return false if there is none; take `authority.substring(0, atIndex)` as uriUserId. The existing tail is kept: return true if and only if uriUserId is non-empty and differs from String.valueOf(myUserId()). Per the Javadoc, this mirrors the ContentProvider parsing.",
      "BluetoothOppSendFileInfoTest.java: switches the runner to TestParameterInjector and parameterizes generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError and generateFileInfo_withContentUriForSameUser_returnsInfoWithCorrectLength on `boolean encodedAt`, building authorities with either '@media' or '%40media'. In the Android 14 commit, the other-user test is also marked @Ignore (b/377774165, prebuilt BT APEX).",
      "android/app/tests/unit/Android.bp (Android 14 commit only): adds \"TestParameterInjector\" to static_libs of BluetoothInstrumentationTestsDefaults."
     ],
     "completeness": [
      "Only the helper isContentUriForOtherUser is changed. Per the Javadoc, getAuthority() returns the decoded authority, so the fix covers both a literal '@' and a percent-encoded '%40'.",
      "The check compares strings rather than parsing an int, so any non-empty userInfo that is not exactly the current user's id string is treated as another user.",
      "An authority with an '@' but an empty prefix still returns false (TextUtils.isEmpty), as before. The material does not show how ContentProvider treats that case.",
      "The material does not show where isContentUriForOtherUser is called inside generateFileInfo, so it cannot confirm that every content-URI path in OPP goes through this check."
     ],
     "behavior_changes": [
      "Content URIs whose decoded authority has a userInfo prefix before '@' that differs from the current user id are now treated as other-user URIs, including when the '@' was percent-encoded. Per the test name, generateFileInfo returns SEND_FILE_INFO_ERROR for them.",
      "URIs whose userInfo equals the current user id are still accepted (covered by the same-user test in both encoded and unencoded forms).",
      "Test-only: BluetoothOppSendFileInfoTest now uses TestParameterInjector. The Android 14 commit also adds the TestParameterInjector static_lib and an @Ignore on one test."
     ],
     "preconditions": [
      "A content URI reaches the Bluetooth OPP send path and is processed by BluetoothOppSendFileInfo.generateFileInfo. The exact entry points are not shown in the material.",
      "The URI authority has a user id prefix followed by a percent-encoded '@' separator.",
      "Another user exists whose content provider data could be targeted (implied by the other-user check; not detailed in the material)."
     ],
     "per_major": {
      "14": "Resolved via bug_id in android-security-14.0.0_r21, commit 0d3683c8b1c1 (RESTRICT AUTOMERGE, double cherry-pick). Same source change to isContentUriForOtherUser. Unlike 15/16, it does not add the `import android.content.ContentProvider;` line, and it adds TestParameterInjector to tests/unit/Android.bp plus an @Ignore on the other-user test. At android-security-14.0.0_r29, 7/8 lines of the patched region are present.",
      "15": "Resolved via bug_id in android-security-15.0.0_r9, commit 495d32429fd8. Same fix, plus `import android.content.ContentProvider;` (referenced by the Javadoc {@link} in the shown hunks). The commit has no Android.bp change. At android-security-15.0.0_r17, 7/8 lines are present.",
      "16": "Resolved in base android-16.0.0_r2, commit bb8a03783901. Same fix as Android 15. At android-security-16.0.0_r8, 7/8 lines 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 fix. The only functional change is the body of isContentUriForOtherUser. In the shown hunks, the `import android.content.ContentProvider;` added in 15/16 is referenced only by the Javadoc, and the Android 14 commit omits it. To backport the test, TestParameterInjector must be in the unit test static_libs. The Android 14 commit adds it to Android.bp; the 15/16 commits contain no Android.bp change."
     ],
     "confidence": "high",
     "unknowns": [
      "The call sites of isContentUriForOtherUser within generateFileInfo, and the OPP entry points that reach it, are not in the provided code context.",
      "The material does not show why the per-major line match is 7/8 rather than 8/8 in every tag.",
      "The exact semantics of ContentProvider#getUserIdFromAuthority (for example, empty userInfo or multiple '@') are described only by the fix's Javadoc, not by framework code 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-2025-26455": {
     "cve": "CVE-2025-26455",
     "summary": "Makes the pointer/size pairs returned by the NDK AMediaCodec_getInputBuffer and AMediaCodec_getOutputBuffer APIs consistent (input: base pointer with capacity; output: data pointer with actual size) and sets the offset reported by AMediaCodec_dequeueOutputBuffer to 0 because the output pointer is already offset.",
     "component": "platform/frameworks/av, media/ndk (libmediandk AMediaCodec wrapper)",
     "weakness": "Inconsistent buffer pointer/size/offset reported to API callers (incorrect size/offset calculation)",
     "root_cause": "In media/ndk/NdkMediaCodec.cpp, AMediaCodec_getInputBuffer returned abuf->data() while reporting *out_size = abuf->capacity(); per the commit message this erroneously considered the buffer offset and could result in a smaller input buffer being returned and client confusion. AMediaCodec_getOutputBuffer returned data() but reported capacity() rather than size(), so per the commit message the reported size included padding after the output buffer. AMediaCodec_dequeueOutputBuffer copied the codec's internal offset into AMediaCodecBufferInfo.offset even though, per the fix comment, the output buffer address is already offset in AMediaCodec_getOutputBuffer, so a client honoring info.offset would apply it twice. The pattern existed in both the asynchronous (mCodec->getInputBuffer/getOutputBuffer) and synchronous (getInputBuffers/getOutputBuffers vector) branches.",
     "fix_analysis": [
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getInputBuffer (async branch using mCodec->getInputBuffer): return abuf->base() instead of abuf->data(), keeping *out_size = abuf->capacity(). A comment explains the input buffer is empty when handed out and the offset is set at queueInputBuffer time.",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getInputBuffer (sync branch using mCodec->getInputBuffers vector): return abufs[idx]->base() instead of abufs[idx]->data().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getOutputBuffer (async branch): *out_size = abuf->size() instead of abuf->capacity(); pointer stays abuf->data().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getOutputBuffer (sync vector branch): *out_size = abufs[idx]->size() instead of abufs[idx]->capacity().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_dequeueOutputBuffer: on OK, info->offset = 0 instead of the offset returned by mCodec->dequeueOutputBuffer, since AMediaCodec_getOutputBuffer already returns the offset pointer; info->size, flags and presentationTimeUs unchanged.",
      "media/ndk/include/media/NdkMediaCodec.h: documentation only. Adds notes on AMediaCodec_getOutputBuffer and AMediaCodec_dequeueOutputBuffer describing behavior at or before API level 35 (out_size invalid, offset invalid) versus after, and removes mentions of non-existent AMediaCodec_getInputBuffers/AMediaCodec_getOutputBuffers from the asynchronous-callback doc comment."
     ],
     "completeness": [
      "Covers both the asynchronous single-buffer paths and the synchronous vector paths of AMediaCodec_getInputBuffer and AMediaCodec_getOutputBuffer, plus the offset reported by AMediaCodec_dequeueOutputBuffer.",
      "For input buffers the fix changes the pointer (base()) rather than the size, so out_size still reports capacity().",
      "For output buffers the fix changes only the size (size()) and keeps the data() pointer; the internal offset is not exposed to the client.",
      "The diff does not touch any other place that might fill an AMediaCodecBufferInfo (for example an asynchronous output-available callback path); the material does not show whether such a path reports an offset.",
      "No validation is added inside libmediandk. Clients that used info.size from AMediaCodec_dequeueOutputBuffer rather than out_size (as ImsMediaAudioSource::dequeueOutputBuffer does, per index search) were already using the payload size."
     ],
     "behavior_changes": [
      "AMediaCodec_getInputBuffer now returns the buffer base address; if the internal offset is nonzero this pointer differs from the pre-fix value (same reported capacity).",
      "AMediaCodec_getOutputBuffer now reports size() instead of capacity(); clients relying on out_size for output buffers will see a smaller value.",
      "AMediaCodec_dequeueOutputBuffer always sets AMediaCodecBufferInfo.offset to 0.",
      "No new error codes or return paths; apart from the value changes above, the remaining changes are header documentation."
     ],
     "preconditions": [
      "A client uses the NDK libmediandk AMediaCodec API (AMediaCodec_getInputBuffer, AMediaCodec_getOutputBuffer or AMediaCodec_dequeueOutputBuffer) in synchronous or asynchronous mode. Callers include frameworks/av/media/ndk/fuzzer/NdkMediaCodecFuzzerBase.cpp, frameworks/av/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp, and packages/modules/ImsMedia ImsMediaAudioSource::dequeueOutputBuffer (per index search).",
      "The underlying MediaCodecBuffer must have a nonzero internal offset or a capacity larger than its valid size for the old and new values to differ; which codecs or configurations produce this is not shown in the material."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/av e28ca0c3d70c in android-security-14.0.0_r21 (cherry-pick of d69fe7b73a0e, Change-Id I6bbd9b85023aef56a608362afde0662d3df7284a); identical hunks to the 15 commit; at android-security-14.0.0_r29 all 8 patched lines are present.",
      "15": "same fix: platform/frameworks/av a5c1d4f8d6d5 in android-security-15.0.0_r9, identical diff (same blob ids b230df5179..240848096a as 14); at android-security-15.0.0_r17 all 8 patched lines are present.",
      "16": "same fix: original commit d69fe7b73a0e in android-16.0.0_r2; identical content, only hunk line numbers differ (NdkMediaCodec.cpp d22a5ba147..62ef6118ca); at android-security-16.0.0_r8 all 8 patched lines are present.",
      "17": "not affected per the bulletin (not listed); the patched region is fully present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained commit touching only media/ndk/NdkMediaCodec.cpp and media/ndk/include/media/NdkMediaCodec.h; the .cpp hunks are the same on 14, 15 and 16 (same pre-image on 14/15). The header text refers to behavior 'after API level 35', which does not match the 14/15 backports where behavior changes within an existing API level; this is documentation only.",
      "If a fork has its own code that fills AMediaCodecBufferInfo from the codec's internal offset, consider the same offset = 0 treatment for consistency with AMediaCodec_getOutputBuffer."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which codec implementations or buffer allocators produce a nonzero internal offset or capacity larger than size for NDK-visible buffers.",
      "Whether the old pointer/size mismatch could lead clients to access memory outside the buffer; the material describes only incorrect sizes and client confusion.",
      "Whether any asynchronous callback path in NdkMediaCodec.cpp also reports AMediaCodecBufferInfo.offset; the diff does not touch such a path.",
      "The concrete EoP scenario behind the bulletin's High rating."
     ],
     "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-2025-26456": {
     "cve": "CVE-2025-26456",
     "summary": "Bounds the ART dex-use database in DexUseManagerLocal by capping secondary dex path length (4096), class loader context length (10000) and the number of secondary dex entries per owning package (500). Two follow-up commits first made the companion file-existence check symlink-safe and then removed it entirely because of sepolicy restrictions.",
     "component": "platform/art, libartservice (ART Service) DexUseManagerLocal",
     "weakness": "Missing resource limit / unbounded growth of persisted state from untrusted input (DoS)",
     "root_cause": "Per its own class comment, DexUseManagerLocal collects data sent directly by apps. Before the fix, addSecondaryDexUse ran computeIfAbsent on mSecondaryDexUseByDexFile for any dexPath, with no cap on the number of distinct secondary dex paths per owning package. The input validation loop in notifyDexContainersLoaded only checked that the path was non-empty and absolute, with no length limit on the dex path or the class loader context strings. The resulting entries are persisted to /data/system/package-dex-usage.pb, so the in-memory map and the on-disk database could grow without bound. The commit message puts the size at O(owning package x dex path x loading package), with secondary dex paths potentially unbounded.",
     "fix_analysis": [
      "Commit 1aedae6e1049 (Ensure the dex use database cannot grow unboundedly), DexUseManagerLocal.java: adds the constants MAX_PATH_LENGTH = 4096, MAX_CLASS_LOADER_CONTEXT_LENGTH = 10000 and MAX_SECONDARY_DEX_FILES_PER_OWNER = 500. The last one is exposed through a new Injector.getMaxSecondaryDexFilesPerOwner().",
      "Same commit, validation loop in DexUseManagerLocal.notifyDexContainersLoaded: throws IllegalArgumentException if dexPath.length() > MAX_PATH_LENGTH or classLoaderContext.length() > MAX_CLASS_LOADER_CONTEXT_LENGTH. The existing path check is kept (Paths.get(dexPath).isAbsolute() on 14, ArtJni.validateDexPath on 15).",
      "Same commit, DexUseManagerLocal.addSecondaryDexUse: the computeIfAbsent lambda for mSecondaryDexUseByDexFile returns null when packageDexUse.mSecondaryDexUseByDexFile.size() >= mInjector.getMaxSecondaryDexFilesPerOwner(). In that case no entry is created, a Log.w is written, and the method returns early. Loader records can still be added to an existing dex path entry after the cap is reached (test testLimitSecondaryDexFiles).",
      "Same commit, addSecondaryDexUse: also adds an early return when isLoaderOtherApp(loader, owningPackageName) && !mInjector.pathExists(dexPath), where Injector.pathExists is new File(path).exists(). dex_use.proto only gains '// key' comments.",
      "Commit 3c76194d116b (Fix SELinux denial on GMS Core's symlinks), DexUseManagerLocal.Injector.pathExists: changed to Files.exists(Paths.get(path), LinkOption.NOFOLLOW_LINKS), because system_server lacks permission to follow GMS Core's symlinks to its secondary dex files.",
      "Commit 06a99377e368 (Omit file existence check on notifyDexContainersLoaded), DexUseManagerLocal.addSecondaryDexUse and Injector: removes the pathExists check, the pathExists() method and the LinkOption import 'due to sepolicy restrictions on some platforms'. In the tests, testNonexistingExternalSecondaryDexPath and testInternalSecondaryDexPath are deleted and testExistingExternalSecondaryDexPath is renamed to testSecondaryDexPath. The length and per-owner count limits remain."
     ],
     "completeness": [
      "The final code bounds three things for secondary dex use: path string length, class loader context string length, and the number of distinct secondary dex paths per owning package. Per the commit message, owning and loading packages are already bounded by the package database, and primary dex paths by installed packages. The diff adds no limits there.",
      "Commit 06a99377e368 removes the existence check whose stated purpose was to stop a loading package from using up another package's SecondaryDexUse entries. After it, nothing in the shown code prevents another app's nonexistent paths from counting toward an owner's 500-entry cap. Growth stays bounded, and the material shows no other mitigation.",
      "The per-owner cap is applied only at insertion. The diff shows no pruning of entries persisted before the fix.",
      "Over-long inputs are rejected with IllegalArgumentException. The material does not show how the caller handles it."
     ],
     "behavior_changes": [
      "notifyDexContainersLoaded throws IllegalArgumentException for a dex path longer than 4096 chars or a class loader context longer than 10000 chars. These inputs were previously accepted.",
      "New secondary dex path entries beyond 500 per owning package are dropped with a Log.w (AsLog.w on 15) warning. Records for existing dex paths can still be added or updated.",
      "Between the first and third commits, secondary dex loads by another app were not recorded if the path did not exist from system_server's point of view (with NOFOLLOW_LINKS after the second commit). In the final state they are recorded regardless of existence.",
      "Injector gains getMaxSecondaryDexFilesPerOwner(). pathExists() was added and then removed. The DexUseManagerTest stubs change accordingly."
     ],
     "preconditions": [
      "notifyDexContainersLoaded receives secondary dex container paths and class loader context strings from apps. The class comment says this data is sent directly by apps and should be trusted as little as possible.",
      "Paths must pass the existing validation: non-empty and absolute on Android 14; ArtJni.validateDexPath and validateClassLoaderContext on Android 15."
     ],
     "per_major": {
      "14": "Same fix: three commits 1aedae6e1049, 3c76194d116b and 06a99377e368 in android-security-14.0.0_r21 (cherry-picks of e29eb53ebf11, abeeacd90204 and d62d66437f3b). At android-security-14.0.0_r29 the patched region is fully present (8/8 lines), and the code context shows the limits present and the LinkOption import gone.",
      "15": "Adapted fix: ff0ca4365def in android-security-15.0.0_r9 is the limits commit adapted to the 15 code base. It uses AsLog.w instead of Log.w, and the length checks sit around ArtJni.validateDexPath and ArtJni.validateClassLoaderContext. The per-major facts show 8/8 patched lines at android-security-15.0.0_r17. The material does not explicitly show the 15 cherry-picks of the symlink and omit-existence-check commits.",
      "16": "Resolved in base (android-16.0.0_r2) by d62d66437f3b (Omit file existence check). Its pre-image already contains the existence check with the NOFOLLOW_LINKS pathExists and the per-owner limit. 7/8 patched lines are present at android-security-16.0.0_r8.",
      "17": "Not affected: the bulletin does not list Android 17. 7/8 patched lines are present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Apply in order: the limits commit (Ic50bf22000730282d90a4f6aa1c49379357fe77a), then the symlink fix (Iaa9a716cfe262897e313b994db92855721e1dfcc), then omit-existence-check (Ib6d878a678ddafd02fb48d92ddfbabdfd6f4f14e). The third commit's removed hunk includes comment lines added by the second, so skipping the second needs manual conflict resolution. Required end state: the three MAX_* constants, the two length checks in notifyDexContainersLoaded, the capped computeIfAbsent in addSecondaryDexUse, Injector.getMaxSecondaryDexFilesPerOwner(), and no pathExists check.",
      "On branches where the validation loop uses ArtJni.validateDexPath and validateClassLoaderContext (Android 15 style) rather than Paths.get(...).isAbsolute() (Android 14 style), place the length checks as in ff0ca4365def: the path length check before ArtJni.validateDexPath and the context length check before ArtJni.validateClassLoaderContext."
     ],
     "confidence": "high",
     "unknowns": [
      "How notifyDexContainersLoaded is reached from an app (the system_server caller and binder path).",
      "How the caller handles the new IllegalArgumentException.",
      "Which inputs notifyDexContainersLoaded routes to addSecondaryDexUse rather than primary dex handling.",
      "Whether Android 15 security tags carry the symlink and omit-existence-check follow-ups (only the limits commit diff is provided for 15).",
      "Whether entries persisted before the fix are ever pruned to the new cap."
     ],
     "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-2025-26458": {
     "cve": "CVE-2025-26458",
     "summary": "Adds options.setPendingIntentBackgroundActivityLaunchAllowed(false) to the BroadcastOptions that LocationPendingIntentTransport in LocationProviderManager.java uses when system_server sends a client-supplied PendingIntent, so these sends explicitly deny background activity launch.",
     "component": "platform/frameworks/base, services/core location (LocationProviderManager.LocationPendingIntentTransport)",
     "weakness": "Missing explicit denial of background activity launch (BAL) on a PendingIntent sent by system_server on behalf of an app",
     "root_cause": "LocationPendingIntentTransport in services/core/java/com/android/server/location/provider/LocationProviderManager.java sends the client's PendingIntent from system_server in two places: deliverOnLocationChanged via PendingIntentSender.send, and the provider-enabled delivery via mPendingIntent.send with KEY_PROVIDER_ENABLED. The BroadcastOptions built with BroadcastOptions.makeBasic() set setDontSendToRestrictedApps(true) and, for location results, a temporary app allowlist for foreground services. They did not explicitly set whether background activity launches are allowed for the PendingIntent send. The commit describes the fix as 'fixing the default values for pending intent'. The bulletin rates the issue as a High EoP.",
     "fix_analysis": [
      "LocationProviderManager.java:LocationPendingIntentTransport.deliverOnLocationChanged: adds options.setPendingIntentBackgroundActivityLaunchAllowed(false) after options.setDontSendToRestrictedApps(true). This is before the temporary allowlist is set and before PendingIntentSender.send(mPendingIntent, mContext, intent, callback, options.toBundle()).",
      "LocationProviderManager.java:LocationPendingIntentTransport (provider-enabled delivery, second hunk at line ~316 in 14): adds the same options.setPendingIntentBackgroundActivityLaunchAllowed(false) before mPendingIntent.send(mContext, 0, new Intent().putExtra(KEY_PROVIDER_ENABLED, enabled), null, null, null, options.toBundle()).",
      "Net effect: both PendingIntent sends from this transport now explicitly carry the BAL-denied option. The foreground-service temporary allowlist for location results is unchanged."
     ],
     "completeness": [
      "Covers both PendingIntent send sites inside LocationPendingIntentTransport (location changed and provider enabled changed). No other code paths are modified.",
      "The fix changes send options only. It does not change who may register a PendingIntent and does not validate the PendingIntent itself.",
      "Other PendingIntent sends in location services or elsewhere in system_server are not shown in the material and are not touched by this commit. Whether they need the same option is unknown from the material."
     ],
     "behavior_changes": [
      "PendingIntent sends for location updates and provider enabled/disabled changes now explicitly pass setPendingIntentBackgroundActivityLaunchAllowed(false). Background activity launches tied to these sends are expected to be denied, subject to the platform BAL policy.",
      "The foreground service start allowance for location PendingIntents (setTemporaryAppAllowlist with TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED) is preserved."
     ],
     "preconditions": [
      "A client has registered a location or provider listener backed by a PendingIntent, so that LocationProviderManager uses LocationPendingIntentTransport for delivery.",
      "A location result or provider enabled state change is delivered to that client, causing system_server to send the PendingIntent."
     ],
     "per_major": {
      "14": "same fix: commit 9d2acb2d3c5d in android-security-14.0.0_r21 (cherry-pick of 225602a7d0fe); 8/8 lines of the patched region present at android-security-14.0.0_r29.",
      "15": "same fix: commit 937c2903736f in android-security-15.0.0_r9, identical two-line diff (hunks at lines 283/325); 8/8 lines present at android-security-15.0.0_r17.",
      "16": "same fix: original commit 225602a7d0fe in android-16.0.0_r2, identical diff (hunks at lines 285/327); 8/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (not listed); the patched region is present 8/8 at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single-file, two-line change. The diffs for 14, 15 and 16 are identical apart from line offsets. The target branch must provide BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed."
     ],
     "confidence": "medium",
     "unknowns": [
      "The exact name of the second patched method. The hunk shows only its body sending KEY_PROVIDER_ENABLED, and the r29 code context ends before it.",
      "How Android 13 was fixed. The bulletin lists 13 as affected, but the material has no Android 13 commit and does not show whether the API is available there.",
      "The actual default BAL behaviour for a PendingIntent sent by system_server without this option.",
      "Whether other PendingIntent send sites in location services lack the same option."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26462": {
     "cve": "CVE-2025-26462",
     "summary": "Adds an onNullBinding override to AccessibilityServiceConnection that calls unbindLocked() under mLock, so system_server no longer stays bound to an accessibility service whose onBind() returned null and that service can no longer launch activities from the background (BAL).",
     "component": "platform/frameworks/base, services/accessibility (AccessibilityServiceConnection)",
     "weakness": "Missing cleanup on a ServiceConnection callback (onNullBinding not handled), leaving a binding and its tracking state in place (improper resource release).",
     "root_cause": "AccessibilityServiceConnection, a ServiceConnection used by system_server, handled onServiceDisconnected but did not override onNullBinding. When an accessibility service returned null from onBind(), nothing in the connection released the binding. Per the commit message, the service therefore stayed bound by system_server and could launch activities from the background.",
     "fix_analysis": [
      "services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java: a new @Override onNullBinding(ComponentName) is added after onServiceDisconnected. It takes mLock and calls unbindLocked(). The comment in the diff says Context#unbindService must be called here to release the tracking resources associated with the ServiceConnection and so prevent BAL.",
      "No other files change. The fix is a single 10-line addition, and the same hunk is applied on Android 14, 15 and 16; only the line offset differs (@@ -252 on 14, @@ -310 on 15, @@ -309 on 16)."
     ],
     "completeness": [
      "Covers only the onNullBinding path of AccessibilityServiceConnection. onServiceConnected and onServiceDisconnected are unchanged.",
      "onServiceDisconnected also calls mActivityTaskManagerService.setAllowAppSwitches(mComponentName.flattenToString(), -1, userState.mUserId). The new onNullBinding does not call it directly, and the material does not show whether unbindLocked() clears that allowance.",
      "The body of unbindLocked() is not in the material, so exactly what it releases cannot be confirmed from the diff."
     ],
     "behavior_changes": [
      "An accessibility service whose onBind() returns null is now unbound by system_server instead of staying bound.",
      "Such a service can no longer launch activities from the background (per the commit message and its test description).",
      "No API change or new error code is visible in the diff. The change is limited to system_server's handling of the connection."
     ],
     "preconditions": [
      "An accessibility service bound by system_server through AccessibilityServiceConnection returns null from onBind(), so onNullBinding is delivered.",
      "The bulletin rates this as a High-severity EoP. The commit message describes the impact as the ability to launch activities from the background."
     ],
     "per_major": {
      "14": "same fix: commit 7076b2b2bd3c in android-security-14.0.0_r21 (cherry-pick, Change-Id Id04111b061881d23346aa90a0b5d08a28bed2c6f). Patched region fully present at android-security-14.0.0_r29.",
      "15": "same fix: commit af2f9c246ef0 in android-security-15.0.0_r9, identical hunk at a different offset. Patched region fully present at android-security-15.0.0_r17.",
      "16": "same fix: commit eeac12b27c64 in android-16.0.0_r2, identical hunk. Patched region fully present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). The patched region is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained hunk: add the onNullBinding override after onServiceDisconnected in AccessibilityServiceConnection.java. It uses mLock (already used in the surrounding code) and unbindLocked(); check that unbindLocked() exists in your tree. ServiceConnection#onNullBinding has been a default interface method since API 28 (general platform knowledge).",
      "The commit references the CTS test android.security.cts.Bug_386950836. That test is not part of this diff."
     ],
     "confidence": "high",
     "unknowns": [
      "The implementation of unbindLocked() is not shown, so the exact resources it releases, including whether it resets the setAllowAppSwitches allowance, cannot be confirmed.",
      "How and when system_server binds an accessibility service (for example, after the user enables it) is not shown.",
      "Which BAL check the lingering binding satisfied is not shown. Only the commit message states the outcome.",
      "The content of the CTS test Bug_386950836 and the reproduction steps in bug 386950836 are not included."
     ],
     "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-2025-26463": {
     "cve": "CVE-2025-26463",
     "summary": "Adds hard upper bounds (223 chars for packageName, 32 bytes for certificate) to BlobStoreManager.Session.allowPackageAccess on the client side and to BlobStoreSession.allowPackageAccess in system_server, rejecting oversized inputs with IllegalArgumentException.",
     "component": "platform/frameworks/base, BlobStore (apex/blobstore framework and service)",
     "weakness": "missing input length validation (unbounded caller-controlled String/byte[] accepted by a system service)",
     "root_cause": "BlobStoreSession.allowPackageAccess (service side) only verified that the caller owned the session and that packageName was non-null. It accepted a packageName of any length and a certificate byte[] of any length, and did not null-check the certificate. The framework wrapper BlobStoreManager.Session.allowPackageAccess forwarded the arguments without any validation. A session owner could therefore get arbitrarily large package name / certificate values accepted by the system_server session. The bulletin rates the impact as High-severity DoS; the material does not show which downstream consumer fails.",
     "fix_analysis": [
      "apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java: adds two @hide constants, MAX_PACKAGE_NAME_LENGTH = 223 (stated to mirror android.content.pm.parsing.FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE) and MAX_CERTIFICATE_LENGTH = 32.",
      "BlobStoreManager.java:Session.allowPackageAccess: before calling mSession.allowPackageAccess, requires packageName and certificate to be non-null (Objects.requireNonNull) and enforces packageName.length() <= 223 and certificate.length <= 32 via Preconditions.checkArgument.",
      "apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java:allowPackageAccess: after assertCallerIsOwner() and the existing packageName null check, adds the same two Preconditions.checkArgument length checks plus Objects.requireNonNull(certificate), before taking mSessionLock and the STATE_OPENED check. This server-side check is the authoritative one; the client-side check only gives an early failure.",
      "Single commit, two files; the service imports the constants statically from the framework class."
     ],
     "completeness": [
      "Covers both the public framework wrapper and the binder-facing service method, so a direct IBlobStoreSession call that bypasses the client wrapper is also rejected.",
      "Validation runs before mSessionLock is taken and before the STATE_OPENED check, so no partial update occurs.",
      "Only the allowPackageAccess path (package name and certificate) is bounded by this commit; other caller-supplied strings/arrays in the blobstore API (for example BlobHandle fields) are not touched by this diff and their limits are not shown in the material.",
      "The certificate limit of 32 bytes is a fixed value; the diff does not show how previously stored oversize entries (if any were persisted) are handled on load."
     ],
     "behavior_changes": [
      "BlobStoreManager.Session.allowPackageAccess now throws IllegalArgumentException for packageName longer than 223 chars or certificate longer than 32 bytes, and NullPointerException for null arguments, before any IPC.",
      "BlobStoreSession.allowPackageAccess (system_server) throws IllegalArgumentException for the same oversize cases and now also NullPointerException for a null certificate (previously only packageName was null-checked).",
      "Any caller passing a certificate longer than 32 bytes is now rejected."
     ],
     "preconditions": [
      "Caller must hold a BlobStore session and be its owner (assertCallerIsOwner passes).",
      "Session must be in STATE_OPENED for the call to proceed past the new checks.",
      "No special permission is shown as required in the material."
     ],
     "per_major": {
      "14": "same fix: commit 4b630be2e2b3 (cherry-picked) in android-security-14.0.0_r21; BlobStoreSession.java base differs slightly (hunk at line 327 vs 328 on 15/16); 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "same fix: commit 89c67cf1d19e in android-security-15.0.0_r9, identical content; 8/8 lines present at android-security-15.0.0_r17.",
      "16": "same fix: commit aaa1cb20b89f in android-16.0.0_r2; 8/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); patched region fully present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The service file imports MAX_PACKAGE_NAME_LENGTH / MAX_CERTIFICATE_LENGTH from android.app.blob.BlobStoreManager, so both files must be applied together. Google applied the same hunk content on 14, 15 and 16; the only visible difference is a one-line offset in BlobStoreSession.java (base 8eef8cebec3f on 14 vs ede29ec168c0 on 15/16).",
      "The commit adds the Preconditions and Objects imports to BlobStoreManager.java; it adds no such imports to BlobStoreSession.java, so that file already has them on the patched branches."
     ],
     "confidence": "high",
     "unknowns": [
      "The concrete failure mode of the DoS (which component fails on the oversize package name / certificate, e.g. XML persistence or memory in system_server) is not shown in the material.",
      "Whether other BlobStore inputs already had length limits before this fix is not shown.",
      "Handling of any pre-existing persisted oversize access-mode entries after upgrade is not shown.",
      "Which apps can create a BlobStore session, and whether any permission is required, is not shown."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-32312": {
     "cve": "CVE-2025-32312",
     "summary": "Adds a type check in PackageParser's createIntentsList so that a class read by name from a Parcel is only constructed if it is a subclass of IntentInfo. Before, the code reflectively constructed any class named in the parcel.",
     "component": "platform/frameworks/base, core/java/android/content/pm/PackageParser.java (component parcel deserialization, createIntentsList)",
     "weakness": "Unsafe reflection: a class name taken from input is used to select a class to load and construct, with no validation, during Parcel deserialization",
     "root_cause": "createIntentsList(Parcel in) reads a count N and then a String componentName from the Parcel. It calls Class.forName(componentName), looks up a constructor that takes a Parcel, and calls cons.newInstance(in) N times. Nothing checked that the named class was an IntentInfo subclass, so any class with a public (Parcel) constructor named in the parcel data would be loaded and constructed from the rest of the parcel. The writer side (writeIntentsList) only ever writes info.getClass().getName() of a real IntentInfo, but the reader trusted the string without checking it.",
     "fix_analysis": [
      "core/java/android/content/pm/PackageParser.java : createIntentsList(Parcel): right after Class.forName(componentName), the fix adds `if (!IntentInfo.class.isAssignableFrom(cls)) throw new AssertionError(\"Intent list requires subclass of IntentInfo, not: \" + componentName);`. As a result, getConstructor(Parcel.class) and newInstance(in) are only reached for IntentInfo subclasses.",
      "The new AssertionError is thrown inside the existing try block. It is not a ReflectiveOperationException, so it propagates out of createIntentsList instead of being caught and rewrapped by the existing catch.",
      "Single-file, four-line change. writeIntentsList and the IntentInfo subclasses are not changed."
     ],
     "completeness": [
      "Covers the only reflective construction site shown: createIntentsList now rejects any class that is not an IntentInfo subtype before it looks up or calls a constructor.",
      "Class.forName(componentName) still runs before the check, so the named class is still loaded and statically initialized. Only construction is prevented.",
      "Any IntentInfo subclass with a (Parcel) constructor is still accepted. The fix enforces the type bound only and does not restrict the class to specific known subclasses.",
      "A rejected class causes an AssertionError to propagate out of createIntentsList, the same way existing reflective failures are reported."
     ],
     "behavior_changes": [
      "Unparceling an intents list that names a class which is not an IntentInfo subclass now throws AssertionError (\"Intent list requires subclass of IntentInfo, not: <name>\") instead of constructing that class.",
      "Well-formed parcels produced by writeIntentsList behave as before, because they always name an IntentInfo subclass."
     ],
     "preconditions": [
      "Attacker-influenced Parcel data must reach createIntentsList(Parcel), which reads the count and the class name from it. The material does not show which callers or processes do this.",
      "The receiving process must be able to reach, via Class.forName, a class with a public constructor that takes a Parcel."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 577cdba1048c in android-security-14.0.0_r21 (cherry-pick of 65c1a90bf4af). All 4 patched lines are present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/base 95eda53ff1d0 in android-security-15.0.0_r9, identical hunk (offset +1 line). All 4 lines are present at android-security-15.0.0_r17.",
      "16": "same fix: commit 65c1a90bf4af in android-16.0.0_r2, identical hunk. All 4 lines are present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (Android 17 is not listed). The patched region (4/4 lines) is already present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "A single self-contained hunk in createIntentsList. It should apply cleanly wherever the Class.forName/getConstructor(Parcel.class) sequence exists; the hunks for 14, 15 and 16 differ only in line offset (7763, 7764, 7782). Android 13 is listed as affected, but the material contains no Android 13 commit."
     ],
     "confidence": "high",
     "unknowns": [
      "Which binder interfaces or callers pass untrusted Parcels into createIntentsList. The material shows no callers.",
      "Whether a fix landed on Android 13, which is listed as affected but has no commit in the material.",
      "Whether a test covers the rejection path. The commit only cites atest PackageParsingPerfTest."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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": 16,
    "certain": 16,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-26432",
     "osv_id": "ASB-A-386802855",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a 1024-character upper bound on the tag string accepted by CompanionDeviceManagerService's setAssociationTag binder method, rejecting longer tags with IllegalArgumentException before they reach AssociationRequestsProcessor.",
      "confidence": "high",
      "backport_notes": [
       "Single 4-line, self-contained change in the stub method. When backporting, consider guarding the null case (clearAssociationTag passes null), since the upstream check dereferences tag unconditionally."
      ],
      "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "a928f327359247449c214dbc0504b8af3648bacf",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26437",
     "osv_id": "ASB-A-370477460",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a caller identity check to the CredentialManagerService binder entry point that creates a GetCandidateRequestSession. Only the package configured as the device's credential autofill service (R.string.config_defaultCredentialManagerAutofillService) can invoke it; all other callers get a SecurityException.",
      "confidence": "high",
      "backport_notes": [
       "Single-file change. It needs the framework string resource R.string.config_defaultCredentialManagerAutofillService to exist in the target branch and to be set correctly; otherwise the API fails closed for every caller. If the target branch carries the flag-gated variant (Flags.safeguardCandidateCredentialsApiCaller()), follow the Android 16 unflag commit b3d70aab1515 rather than relying on the aconfig flag being enabled."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "c623bbe683082b602ecff0f33fbb439ffc1d2da3",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26441",
     "osv_id": "ASB-A-367274727",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a one-byte bounds check in add_attr (system/stack/sdp/sdp_discovery.cc) before reading the attribute type byte, returning NULL when no byte remains before p_end.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained hunk with no dependencies. Only the logging call differs (SDP_TRACE_WARNING in the 14 and 16 commits, log::warn on 15), so use whichever logger the target file already uses. The 14 and 16 variants pass an extra __func__ argument to SDP_TRACE_WARNING that the format string does not use."
      ],
      "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_r8",
      "date": "2025-05-05",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r8",
      "date": "2025-05-05",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "5e3953251ab50bcdb6058f5e5afc82d6271c6e1e",
       "tag": "android-security-15.0.0_r8",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "public_before_announcement_days": 27,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26443",
     "osv_id": "ASB-A-368319929",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "ManagedProvisioning's HtmlToSpannedParser now rejects HTML that contains any link whose URL is not http:// or https:// (the whole parse returns null) before building a click Intent for it. As a result, non-web URL schemes embedded in TermsActivity content are no longer turned into intents.",
      "confidence": "medium",
      "backport_notes": [
       "The HtmlToSpannedParser change is self-contained: it uses android.webkit.URLUtil and the existing ProvisionLogger. It applied with an identical diff on 14 and 15. Check for one differing line, since only 7/8 lines are present at the latest 14/15 tags.",
       "Consider also checking for the Android 16 DisclaimersParserImpl commit (5d67902f6a74). It is independent of the HtmlToSpannedParser change but concerns the same TermsActivity feature."
      ],
      "meta": {
       "generated": "2026-10-03",
       "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-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/apps/ManagedProvisioning",
       "sha": "a3172895010e1253a6070b6414c2398a1ed6d886",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/apps/ManagedProvisioning"
     ]
    },
    {
     "cve": "CVE-2025-26445",
     "osv_id": "ASB-A-388828859",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a permission check to ConnectivityService.offerNetwork so that only holders of NETWORK_FACTORY/MAINLINE_NETWORK_STACK (or MANAGE_TEST_NETWORKS for TRANSPORT_TEST offers) can register a network offer.",
      "confidence": "high",
      "backport_notes": [
       "The only difference between branches is the enforceAnyPermissionOf call: Android 14/15 use enforceAnyPermissionOf(mContext, perm) and Android 16 uses enforceAnyPermissionOf(perm). Use whichever overload exists in the target ConnectivityService. The 14, 15 and 16 diffs call enforceNetworkFactoryPermission() without adding it, so that helper already existed on those branches.",
       "Connectivity ships as part of the Tethering/Connectivity mainline module, so devices may also get this fix through a module update, not only through the platform security tag (general platform knowledge)."
      ],
      "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Connectivity",
       "sha": "a2d3f541c78ef1a90797dd0278ed1d151572a1f4",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Connectivity"
     ]
    },
    {
     "cve": "CVE-2025-26448",
     "osv_id": "ASB-A-309407957",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Replaces malloc with calloc for the inline CursorWindow data buffer in CursorWindow::create() so the buffer is zero-initialized rather than containing stale heap content if the caller does not fully fill it before sending it to the remote end.",
      "confidence": "high",
      "backport_notes": [
       "Single-commit, one-line change with no dependencies; applies cleanly wherever CursorWindow::create() uses `malloc(window->mSize)`. If a fork has customized CursorWindow.cpp, apply the same calloc replacement to the inline buffer allocation and review any custom allocation paths."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "b7d9d1744c4f0a9a7698e87d8d8c4cf4e1bc7f10",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26449",
     "osv_id": "ASB-A-387498139",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Wraps zen rule lists crossing Binder (INotificationManager.getZenRules/getAutomaticZenRules and the automaticRules/deletedRules maps inside ZenModeConfig) in ParceledListSlice and switches zen-related string parceling to writeString8/readString8, apparently so that large sets of zen rules are no longer carried as one flat array or map in a single parcel.",
      "confidence": "medium",
      "backport_notes": [
       "Apply all files together: the change alters the Parcel format of AutomaticZenRule/ZenModeConfig/ZenRule and the hidden INotificationManager signatures, so framework and services code (and any test doubles implementing INotificationManager) must be updated together. For trees without the modes API (no Flags.modesApi, no getAutomaticZenRules AIDL method, no deletedRules), use the Android 14 commit e3c4ba3c7963 as the template."
      ],
      "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "e0a1e45a3d203e420e7a4ac8fc0e144664e0517f",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26450",
     "osv_id": "ASB-A-331730488",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent now drops KeyEvents carrying Ctrl/Alt/Fn/Meta modifiers unless they are younger than 100 ms and pass InputManager.verifyInputEvent, so fabricated events written into the IME's input channel can no longer trigger modifier shortcuts in the IME.",
      "confidence": "high",
      "backport_notes": [
       "For 14/15 branches use the standalone DO NOT MERGE variant (single file, no aconfig flag, no new public API); the 16 variant depends on the verify_key_event flag, API txt changes and InputMethodSession.onShouldVerifyKeyEvent. The two variants differ in the drop condition (|| vs &&) and in the modifier set; the 14/15 drop condition is the stricter one."
      ],
      "meta": {
       "generated": "2026-10-03",
       "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-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "4cafc04ee7db3486fd8f90e7b66c087887d271e2",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26452",
     "osv_id": "ASB-A-383080440",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Restricts the \"frro:/\" drawable loading branch in ResourcesImpl.java so that the file named by the URI must canonicalize under /data/resource-cache/, end with \".frro\", be readable, and have a non-negative offset and positive size; otherwise a NotFoundException is thrown.",
      "confidence": "high",
      "backport_notes": [
       "Single commit touching two files. The only branch-specific delta shown is that the Android 14 diff adds 'import android.app.ResourcesManager;' to ResourcesImpl.java; the 15 and 16 diffs do not add it. The ResourcesImpl check references the ResourcesManager.RESOURCE_CACHE_DIR constant, so add that constant too (or inline the literal).",
       "No 'Fix in fork' section was provided, so no per-file fork verdict can be reported."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "26c58543f19dcd2f7879ca6ee88bcbc55004c200",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26453",
     "osv_id": "ASB-A-395643490",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Changes BluetoothOppSendFileInfo.isContentUriForOtherUser to derive the user id from the decoded Uri authority (text before the last '@') instead of Uri.getUserInfo(), so Bluetooth OPP rejects cross-user content URIs the same way ContentProvider interprets them, including URIs that use an encoded '%40' separator.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit. The production change is confined to the body of isContentUriForOtherUser, plus a ContentProvider import that the javadoc references. For test parity, older branches need TestParameterInjector in static_libs in android/app/tests/unit/Android.bp, as in the Android 14 backport. That backport @Ignore'd the other-user test with the note 'TODO: b/377774165 - Use source-built BT APEX instead of prebuilt'."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "495d32429fd801c6cd7fe5e568b9c805f47fb4ed",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26455",
     "osv_id": "ASB-A-301470262",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Makes the NDK AMediaCodec buffer accessors self-consistent: AMediaCodec_getInputBuffer returns the buffer base instead of the offset data pointer, AMediaCodec_getOutputBuffer reports size() instead of capacity(), and AMediaCodec_dequeueOutputBuffer reports offset 0 because the returned output pointer is already offset.",
      "confidence": "high",
      "backport_notes": [
       "A single self-contained commit that touches only media/ndk/NdkMediaCodec.cpp and media/ndk/include/media/NdkMediaCodec.h. The Android 14 and 15 patches are byte-identical, and the 16 patch differs only in line offsets. The header hunks are documentation only."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 4,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "a5c1d4f8d6d59ec0960b2c13b76431bbbbc61b26",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/av"
     ]
    },
    {
     "cve": "CVE-2025-26456",
     "osv_id": "ASB-A-391895923",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Limits the secondary dex use entries per owning package (500), dex path length (4096) and class loader context length (10000) that DexUseManagerLocal.notifyDexContainersLoaded accepts, so the persisted dex use database cannot grow without limit. A file-existence pre-check added in the first commit was later changed to not follow symlinks (NOFOLLOW_LINKS), then removed because of sepolicy restrictions.",
      "confidence": "high",
      "backport_notes": [
       "Apply in order ff0ca4365def, 9c88cbbf0028, 74a27958637c, or squash to the net result: the limits and length validation, without the pathExists/isLoaderOtherApp pre-check and without Injector.pathExists. The test file must also drop the pathExists mock in setUp and the two tests that commit 3 deletes. For 14-style branches, use Log.w(TAG, ...) instead of AsLog.w and keep the Paths.get(dexPath).isAbsolute() validation, as in 1aedae6e1049."
      ],
      "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/art",
       "sha": "74a27958637cf5f6327fe3c6d3022e7d91368360",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/art",
       "sha": "9c88cbbf00284cc00e44b5ee8c2628356f02754e",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/art",
       "sha": "ff0ca4365def3cc16c3033f56766d04d041d0768",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 3,
     "projects": [
      "platform/art"
     ]
    },
    {
     "cve": "CVE-2025-26458",
     "osv_id": "ASB-A-388828203",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Explicitly disables background activity launch on the BroadcastOptions used when LocationPendingIntentTransport sends an app-supplied PendingIntent for location updates and provider-enabled changes.",
      "confidence": "high",
      "backport_notes": [
       "Single two-line commit with no dependencies shown; it applies identically on 14, 15 and 16. It calls BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed, which exists on those branches because the fix landed there."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "937c2903736feb9ee415b92432a31bca7fbb059c",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26462",
     "osv_id": "ASB-A-386950836",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds an onNullBinding override to AccessibilityServiceConnection that calls unbindLocked(). An accessibility service whose onBind() returns null is then no longer kept bound by system_server and can no longer launch activities from the background.",
      "confidence": "high",
      "backport_notes": [
       "The change is self-contained: a 10-line method added to AccessibilityServiceConnection.java that uses the existing mLock and unbindLocked(). It applied identically on 14, 15 and 16, differing only in line offset."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "af2f9c246ef05fc5d7c4426c6f341157de758c0e",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26463",
     "osv_id": "ASB-A-303227969",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds upper bounds on the length of the packageName (223 chars) and certificate (32 bytes) accepted by BlobStoreManager.Session.allowPackageAccess, enforced both in the client wrapper and in the system_server BlobStoreSession.allowPackageAccess Binder implementation.",
      "confidence": "high",
      "backport_notes": [
       "Single commit: apply both files together because BlobStoreSession.java statically imports MAX_PACKAGE_NAME_LENGTH and MAX_CERTIFICATE_LENGTH from BlobStoreManager.java; the hunks are pure insertions, identical on 14, 15 and 16 apart from a one-line offset in the service hunk on 14.",
       "Test: atest CtsBlobStoreTestCases per the commit message; the TODO b/404309424 notes the constants are hardcoded in tests rather than exposed via a test API."
      ],
      "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "89c67cf1d19e2ec38f958050ce251598480be241",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-32312",
     "osv_id": "ASB-A-373467684",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a type check in PackageParser's createIntentsList(Parcel) so that a class name read from a Parcel is only reflectively instantiated if it is a subclass of IntentInfo.",
      "confidence": "high",
      "backport_notes": [
       "Self-contained 4-line insertion right after `Class.forName(componentName)` in createIntentsList. It applied identically on 14, 15 and 16 with only line-number offsets.",
       "Android 13 is listed as affected by the bulletin, but the material includes no 13 commit. The same hunk should fit if that branch has the identical createIntentsList body."
      ],
      "meta": {
       "generated": "2026-10-03",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 3,
       "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_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-15.0.0_r9",
      "date": "2025-06-02",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "95eda53ff1d0a5c3e450720896d74a12b3111305",
       "tag": "android-security-15.0.0_r9",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    }
   ],
   "tags": [
    "android-security-15.0.0_r9"
   ],
   "unannounced": [
    {
     "bug_ids": [
      "367702727"
     ],
     "commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "48a022f29de56f50e6d73cbe845c8cb9391fe3ca",
       "subject": "Disable ASM_RESTRICTIONS flag",
       "tag": "android-security-15.0.0_r9",
       "merged": "2025-03-27",
       "markers": []
      }
     ],
     "tags": [
      "android-security-15.0.0_r9"
     ],
     "tag": "android-security-15.0.0_r9"
    },
    {
     "bug_ids": [
      "315320090"
     ],
     "commits": [
      {
       "project": "platform/packages/modules/Permission",
       "sha": "1c4928bbc6d3c7b66ed990e6f1a4b5a827e7a27e",
       "subject": "Display the system gallery storage permission as system fixed",
       "tag": "android-security-15.0.0_r9",
       "merged": "2025-04-09",
       "markers": []
      }
     ],
     "tags": [
      "android-security-15.0.0_r9"
     ],
     "tag": "android-security-15.0.0_r9"
    }
   ],
   "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-26432": {
     "cve": "CVE-2025-26432",
     "summary": "Adds a 1024-character upper bound on the tag string accepted by CompanionDeviceManagerService's setAssociationTag binder method, rejecting longer tags with IllegalArgumentException before they reach AssociationRequestsProcessor.",
     "component": "platform/frameworks/base, CompanionDeviceManager system service (services/companion)",
     "weakness": "missing input length validation (unbounded caller-supplied string)",
     "root_cause": "The overridden setAssociationTag(int associationId, String tag) method inside CompanionDeviceManagerService forwarded the caller-supplied tag string to mAssociationRequestsProcessor.setAssociationTag without any limit on its length, so an arbitrarily large tag could be passed on to the processor. The bulletin classifies the impact as DoS.",
     "fix_analysis": [
      "services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java : setAssociationTag (stub method inside CompanionDeviceManagerService): before delegating to mAssociationRequestsProcessor.setAssociationTag, the fix checks tag.length() > 1024 and throws IllegalArgumentException(\"Length of the tag must be at most1024 characters\"), so oversized tags are rejected at the service boundary.",
      "No other files or functions are changed. The processor and the association storage are untouched."
     ],
     "completeness": [
      "Only the setAssociationTag entry point in CompanionDeviceManagerService is guarded. The fix does not change AssociationRequestsProcessor.setAssociationTag itself, so any other internal path reaching it (none shown in the material) is not covered.",
      "The new check calls tag.length() without a null check. In the same file, clearAssociationTag(int associationId) calls setAssociationTag(associationId, null), so per the code shown at android-security-15.0.0_r17 that path would now hit a NullPointerException on tag.length() before reaching the processor. The material does not show whether a null can also arrive over binder.",
      "The limit is on Java String length (UTF-16 code units), not on serialized byte size."
     ],
     "behavior_changes": [
      "setAssociationTag now throws IllegalArgumentException for tags longer than 1024 characters (previously accepted).",
      "clearAssociationTag, which passes null into setAssociationTag, now dereferences null in the new check as written in the diff, so it would throw instead of reaching the processor."
     ],
     "preconditions": [
      "Caller can invoke setAssociationTag on CompanionDeviceManagerService with an association id. No permission or ownership check is visible in the stub method; whether enforcement exists further down is not shown in the material."
     ],
     "per_major": {
      "14": "not affected per the bulletin; at android-security-14.0.0_r29 the patched region is absent (0/2 lines).",
      "15": "same fix: commit a928f3273592 in android-security-15.0.0_r9 (cherry-pick of 1bea5725035b, Change-Id I7adae8cd57b26e0e9a27d68c49c2de68fd952afd); 2/2 lines present at android-security-15.0.0_r17.",
      "16": "listed as affected (16-next) but code absent: no linked commit and 0/2 lines of the patched region at android-security-16.0.0_r8. The material does not show how Google addressed it in 16.",
      "17": "not affected per the bulletin; 0/2 lines of the patched region at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single 4-line, self-contained change in the stub method. When backporting, consider guarding the null case (clearAssociationTag passes null), since the upstream check dereferences tag unconditionally."
     ],
     "confidence": "high",
     "unknowns": [
      "What concrete resource exhaustion or failure an oversized tag caused downstream (the storage/persistence code in AssociationRequestsProcessor is not shown).",
      "Why 1024 was chosen, and whether the AIDL declares the tag parameter @nullable (relevant to the clearAssociationTag null path).",
      "How Android 16 is fixed, since the bulletin lists 16-next but no commit or patched region is present in the material, and whether setAssociationTag exists in a different form or location on 16/17.",
      "Whether any permission or ownership enforcement applies to setAssociationTag."
     ],
     "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."
     }
    },
    "CVE-2025-26437": {
     "cve": "CVE-2025-26437",
     "summary": "Adds a caller identity check to the CredentialManagerService binder entry point that creates a GetCandidateRequestSession. Only the package configured as the device's credential autofill service (R.string.config_defaultCredentialManagerAutofillService) can invoke it; all other callers get a SecurityException.",
     "component": "platform/frameworks/base, services/credentials (CredentialManagerService, Credential Manager system service)",
     "weakness": "Missing caller identity check on a system service API (improper access control)",
     "root_cause": "In services/credentials/java/com/android/server/credentials/CredentialManagerService.java, the ICredentialManager method that builds a GetCandidateRequestSession read userId and callingUid but did not check who the caller was before starting the session. The commit title says this API is meant for the credential autofill service. The bulletin classifies the issue as information disclosure (ID).",
     "fix_analysis": [
      "CredentialManagerService.java, in the binder method that constructs GetCandidateRequestSession (the method name is not in the hunk): after callingUid is computed, the fix reads R.string.config_defaultCredentialManagerAutofillService and parses it with ComponentName.unflattenFromString. If the result is null, it throws SecurityException (\"Credential Autofill service does not exist on this device.\").",
      "It gets a PackageManager for the caller's user via mContext.createContextAsUser(UserHandle.getUserHandleForUid(callingUid), 0) and resolves pm.getNameForUid(callingUid). If that returns null, it throws SecurityException (\"Couldn't determine the identity of the caller.\").",
      "It compares componentName.getPackageName() with the resolved caller package using Objects.equals. On a mismatch it throws SecurityException (\"<pkg> is not the device's credential autofill package.\").",
      "A try/catch converts Resources.NotFoundException into a SecurityException, so a missing config string fails closed.",
      "Android 16 follow-up b3d70aab1515 (\"unflag cred autofill security fix\") removes the Flags.safeguardCandidateCredentialsApiCaller() gate and the android.credentials.flags.Flags import, so the check runs unconditionally. The Android 15 cherry-pick c623bbe68308 already carries the check without any flag."
     ],
     "completeness": [
      "The check is added only to the one binder method shown (the GetCandidateRequestSession path). This commit touches no other ICredentialManager methods. The material does not show whether sibling methods already had adequate checks.",
      "Every error branch fails closed: a config string that is missing or cannot be parsed, and a caller UID that cannot be resolved, all throw SecurityException.",
      "Identity is checked by matching the caller's package name (from PackageManager.getNameForUid for the caller's user) against the configured component's package. The component's class name is not compared, and no signature or privileged-app check is added.",
      "On Android 16 the check was first behind Flags.safeguardCandidateCredentialsApiCaller(). It became unconditional only with b3d70aab1515 in android-16.0.0_r2."
     ],
     "behavior_changes": [
      "Callers of this API that are not the package named in config_defaultCredentialManagerAutofillService now get a SecurityException instead of a session.",
      "If config_defaultCredentialManagerAutofillService is missing or not a valid flattened ComponentName, this API now always throws SecurityException.",
      "Every call to this method now does a PackageManager lookup (createContextAsUser + getNameForUid)."
     ],
     "preconditions": [
      "The caller can reach the ICredentialManager binder interface of CredentialManagerService and invoke the method that creates GetCandidateRequestSession.",
      "Before the fix, the patched region shows no caller identity requirement. The material does not show whether an earlier permission check exists in the same method."
     ],
     "per_major": {
      "14": "Not affected (not listed by the bulletin). The per-major facts show 8/8 lines of the patched region present at android-security-14.0.0_r29; how they got there is not shown.",
      "15": "Same fix: c623bbe68308 in android-security-15.0.0_r9 (Change-Id I35f3cf616669a6879fd353876029152e3ce327f1), unflagged. 8/8 lines present at android-security-15.0.0_r17.",
      "16": "Adapted fix: the check was present behind Flags.safeguardCandidateCredentialsApiCaller(), and b3d70aab1515 in android-16.0.0_r2 removed the flag gate so it runs unconditionally. 8/8 lines present at android-security-16.0.0_r8.",
      "17": "Not affected (not listed by the bulletin). 8/8 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single-file change. It needs the framework string resource R.string.config_defaultCredentialManagerAutofillService to exist in the target branch and to be set correctly; otherwise the API fails closed for every caller. If the target branch carries the flag-gated variant (Flags.safeguardCandidateCredentialsApiCaller()), follow the Android 16 unflag commit b3d70aab1515 rather than relying on the aconfig flag being enabled."
     ],
     "confidence": "high",
     "unknowns": [
      "The exact name of the patched binder method; the hunk shows only the class, so it is inferred from the GetCandidateRequestSession construction and the flag name.",
      "Whether any other permission check comes before the new code in the same method.",
      "Which callers could reach the method before the fix, what data the candidate session returns, and the precise disclosure impact beyond the bulletin's High/ID rating.",
      "How the patched region came to be present on Android 14 and 17 when the bulletin does not list them."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26441": {
     "cve": "CVE-2025-26441",
     "summary": "Adds a one-byte bounds check in add_attr (system/stack/sdp/sdp_discovery.cc) before reading the attribute type byte, returning NULL when no byte remains before p_end.",
     "component": "platform/packages/modules/Bluetooth, SDP discovery (system/stack/sdp/sdp_discovery.cc)",
     "weakness": "Missing bounds check (out-of-bounds read)",
     "root_cause": "add_attr in system/stack/sdp/sdp_discovery.cc ran `type = *p++;` without first checking that at least one byte remained before p_end. Per the commit message, in exceptional cases add_attr can be passed a p pointer 'one byte short of its p_end pointer', which leads to an out-of-bounds read when it reads the type of the next attribute. The existing checks (the NULL result of sdpu_get_len_from_type and the `(p + attr_len) > p_end` test) only run after that read.",
     "fix_analysis": [
      "system/stack/sdp/sdp_discovery.cc:add_attr: after SDP_ADDITIONAL_LIST_MASK is cleared from nest_level and before `type = *p++;`, the fix adds `if (p + sizeof(uint8_t) > p_end)`. When this check is true, add_attr logs a warning (\"bad arguments to add_addr\") and returns NULL, the same value its later length checks return. The check rejects p >= p_end.",
      "No other code is changed. The fix is a single 5-line insertion with the same logic on Android 14, 15 and 16."
     ],
     "completeness": [
      "Covers the read of the type byte at the start of add_attr. The length decoding that follows receives p_end, and its result is checked against p_end (lines 314 and 328 in the context). The internals of sdpu_get_len_from_type and the code after the shown context are not in the material.",
      "The fix is defensive in the callee: this commit does not change the callers that can pass such a pointer. The condition can still occur but is now rejected with NULL.",
      "Callers must handle the NULL return. The caller code is not in the material, so it cannot be confirmed that every caller treats NULL as an error."
     ],
     "behavior_changes": [
      "add_attr now returns NULL and logs a warning when called with no remaining bytes, instead of reading past p_end. This is the same return value used for a bad attribute length. How callers react is not shown.",
      "Logging differs by branch: log::warn on Android 15, SDP_TRACE_WARNING in the Android 14 and Android 16 fix commits."
     ],
     "preconditions": [
      "The local stack parses SDP discovery response data into a tSDP_DISCOVERY_DB (add_attr is a static helper in sdp_discovery.cc).",
      "Attribute data such that the parser reaches add_attr with no byte left before p_end (the 'exceptional cases' named in the commit message). The exact caller condition is not shown in the material."
     ],
     "per_major": {
      "14": "Same fix: commit d0377d694a83 in android-security-14.0.0_r20, identical check, logs via SDP_TRACE_WARNING. 3/3 lines present at android-security-14.0.0_r29.",
      "15": "Same fix: commit 5e3953251ab5 in android-security-15.0.0_r8, logs via log::warn. 3/3 lines present at android-security-15.0.0_r17.",
      "16": "Same fix: commit 3e234b3e3c0a in android-16.0.0_r2 (base), logs via SDP_TRACE_WARNING in that commit. 3/3 lines present at android-security-16.0.0_r8.",
      "17": "Not affected (not listed by the bulletin). The patched region (3/3 lines) is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained hunk with no dependencies. Only the logging call differs (SDP_TRACE_WARNING in the 14 and 16 commits, log::warn on 15), so use whichever logger the target file already uses. The 14 and 16 variants pass an extra __func__ argument to SDP_TRACE_WARNING that the format string does not use."
     ],
     "confidence": "high",
     "unknowns": [
      "Which caller and which input layout make add_attr receive p at or past p_end. The commit only says 'exceptional cases', and the caller code is not in the material.",
      "Whether all callers of add_attr check for a NULL return. Not shown in the material.",
      "Whether sdpu_get_len_from_type fully bounds its own reads against p_end. Its body is not in the material."
     ],
     "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-26443": {
     "cve": "CVE-2025-26443",
     "summary": "ManagedProvisioning's HtmlToSpannedParser now rejects HTML that contains any link whose URL is not http:// or https:// (the whole parse returns null) before building a click Intent for it. As a result, non-web URL schemes embedded in TermsActivity content are no longer turned into intents.",
     "component": "platform/packages/apps/ManagedProvisioning, TermsActivity HTML rendering (common/HtmlToSpannedParser)",
     "weakness": "Missing input validation (no URL scheme allow-list) before creating an Intent from a link target in HTML",
     "root_cause": "In HtmlToSpannedParser, the method that wraps Html.fromHtml takes every URLSpan from the result. For each span it calls mUrlIntentFactory.create(urlSpan.getURL()) and, if an Intent is returned, sets a clickable span over the link range. The URL scheme was not restricted, so any URL in the HTML was passed to the intent factory. Per the commit message, this allowed an app to be installed via a link embedded in TermsActivity.",
     "fix_analysis": [
      "src/com/android/managedprovisioning/common/HtmlToSpannedParser.java (URLSpan loop of the HTML parsing method): the URL is read into a local. If isValidURL(url) is false, a warning is logged via ProvisionLogger.logw and the method returns null at once, so no Spanned result is returned.",
      "src/com/android/managedprovisioning/common/HtmlToSpannedParser.java:isValidURL (new private helper): returns URLUtil.isHttpUrl(url) || URLUtil.isHttpsUrl(url). A new import of android.webkit.URLUtil is added.",
      "Only URLs that pass the check reach mUrlIntentFactory.create(url). The rest of the span setup is unchanged."
     ],
     "completeness": [
      "Covers every URLSpan that Html.fromHtml produces in this parser. The check runs before mUrlIntentFactory.create, so the factory never receives a non-HTTP(S) URL from this path.",
      "Fails closed for the whole document: one invalid link makes the method return null instead of skipping that span. The material does not show how callers handle a null result.",
      "The check only looks at the scheme (URLUtil.isHttpUrl / isHttpsUrl). It does not restrict host or path. The class doc says URL links are handled by WebActivity.",
      "This commit does not change how disclaimer content is obtained. A separate Android 16 commit (DisclaimersParserImpl.validateUriSchemeAndPermission) limits disclaimer content URIs to the content: and android.resource: schemes and checks the caller's read URI permission. The material does not show that change on the 14 or 15 branches.",
      "UrlIntentFactory and WebActivity are not in the material, so any extra filtering there cannot be checked."
     ],
     "behavior_changes": [
      "HTML with any link whose URL does not start with http:// or https:// is no longer rendered: the parser returns null and logs 'Invalid URL provided. Only HTTP and HTTPS URLs are allowed.'",
      "No new error codes or APIs. The only changes are stricter validation and a new warning log line."
     ],
     "preconditions": [
      "HTML containing a non-HTTP(S) link must reach HtmlToSpannedParser. Per the commit message, the link is embedded in TermsActivity. The exact source of the HTML (for example disclaimer content from EXTRA_PROVISIONING_DISCLAIMERS) is not shown linking to this parser.",
      "A provisioning flow that shows the terms screen must be started (per index search, DevicePolicyManager provisioning APIs exist, but the hits do not show the HTML path).",
      "The link is set as a clickable span, which implies the user interacts with the rendered link."
     ],
     "per_major": {
      "14": "same fix: commit 69a363847696 in android-security-14.0.0_r21, with the same diff as the 15 commit (index ca1a09cf7..25eec1833). At android-security-14.0.0_r29, 7/8 lines of the patched region are present.",
      "15": "same fix: commit a3172895010e in android-security-15.0.0_r9 (cherry-pick of 0eb898e8737f). At android-security-15.0.0_r17, 7/8 lines of the patched region are present.",
      "16": "resolved in base (android-16.0.0_r2), and 8/8 lines of the HtmlToSpannedParser region are present at android-security-16.0.0_r8. The fix commit listed for 16 is 5d67902f6a74 (android-16.0.0_r2). It adds DisclaimersParserImpl.validateUriSchemeAndPermission: a content:/android.resource: scheme allow-list plus checkUriPermission against Binder.getCallingPid/Uid for disclaimer content URIs.",
      "17": "not affected per the bulletin (not listed). android-security-17.0.0_r1 carries 7/8 lines of the patched HtmlToSpannedParser region."
     },
     "backport_notes": [
      "The HtmlToSpannedParser change is self-contained: it uses android.webkit.URLUtil and the existing ProvisionLogger. It applied with an identical diff on 14 and 15. Check for one differing line, since only 7/8 lines are present at the latest 14/15 tags.",
      "Consider also checking for the Android 16 DisclaimersParserImpl commit (5d67902f6a74). It is independent of the HtmlToSpannedParser change but concerns the same TermsActivity feature."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which of the 8 patched lines differs on 14/15/17 (7/8 present).",
      "Whether the DisclaimersParserImpl URI scheme and permission commit shown for Android 16 was also applied to the 14 and 15 branches.",
      "The name of the patched method, the implementation of UrlIntentFactory and WebActivity, and how callers handle the new null return.",
      "The source of the HTML rendered by TermsActivity, and how a non-HTTP(S) link led to app installation. The commit message only states the outcome."
     ],
     "meta": {
      "generated": "2026-10-03",
      "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-2025-26445": {
     "cve": "CVE-2025-26445",
     "summary": "Adds a permission check to ConnectivityService.offerNetwork so that only holders of NETWORK_FACTORY/MAINLINE_NETWORK_STACK (or MANAGE_TEST_NETWORKS for TRANSPORT_TEST offers) can register a network offer.",
     "component": "platform/packages/modules/Connectivity, ConnectivityService (network provider / network offer handling)",
     "weakness": "missing permission check (missing authorization on a Binder entry point)",
     "root_cause": "In service/src/com/android/server/ConnectivityService.java, IConnectivityManager.offerNetwork(providerId, score, caps, callback) did only null checks before it built a NetworkOffer and posted EVENT_REGISTER_NETWORK_OFFER. The neighbouring registerNetworkProvider and unregisterNetworkProvider call enforceNetworkFactoryOrSettingsPermission(), but offerNetwork enforced no caller permission. This went against the ConnectivityManager API annotations, which per the commit message require NETWORK_FACTORY or MAINLINE_NETWORK_STACK. The only input tying the call to a provider is the integer providerId, which comes from nextNetworkProviderId() and is not checked against the caller in the shown code. Per the commit message, an unauthorized app could register a network offer by trivially guessing an existing provider ID, intercept all NetworkRequests and so learn information about other apps (bulletin type ID, severity High).",
     "fix_analysis": [
      "service/src/com/android/server/ConnectivityService.java:offerNetwork: the fix inserts a branch on caps.hasTransport(TRANSPORT_TEST). It sits after the three Objects.requireNonNull calls and before the NetworkOffer is constructed.",
      "If the offered capabilities include TRANSPORT_TEST, the fix calls enforceAnyPermissionOf(mContext, Manifest.permission.MANAGE_TEST_NETWORKS). Per the commit message, this matches how similar APIs in the class gate test networks.",
      "Otherwise the fix calls enforceNetworkFactoryPermission(). Per the commit message, this requires NETWORK_FACTORY or MAINLINE_NETWORK_STACK, which brings the service in line with the ConnectivityManager API annotations.",
      "The checks run before EVENT_REGISTER_NETWORK_OFFER is posted. The fix does not touch the handler side (handleRegisterNetworkOffer) or NetworkOffer.",
      "It is a single-commit fix of 5 added lines in one file. The material shows no test changes."
     ],
     "completeness": [
      "Covers the offerNetwork Binder entry point for all callers. The check runs before any state change is queued.",
      "The check is purely permission-based: the fix does not check that providerId belongs to the calling process. From the shown code, a caller that holds NETWORK_FACTORY/MAINLINE_NETWORK_STACK can still pass any providerId. The material does not show whether handleRegisterNetworkOffer validates providerId.",
      "unofferNetwork, directly below in the same file, still has no permission check. The commit message says this is consistent with the ConnectivityManager annotations. unofferNetwork is keyed on the INetworkOfferCallback binder, not on an integer ID.",
      "In the shown code, TRANSPORT_TEST offers are gated only by MANAGE_TEST_NETWORKS."
     ],
     "behavior_changes": [
      "offerNetwork now rejects callers that lack NETWORK_FACTORY or MAINLINE_NETWORK_STACK (non-test offers) or MANAGE_TEST_NETWORKS (offers whose NetworkCapabilities include TRANSPORT_TEST). The exception type raised by the enforce helpers is not shown in the material.",
      "Offers with TRANSPORT_TEST are checked only against MANAGE_TEST_NETWORKS. Before the fix, no offer needed any permission.",
      "A null argument still fails at the requireNonNull calls first, because they come before the new check."
     ],
     "preconditions": [
      "The caller can reach the IConnectivityManager.offerNetwork Binder method. Per the commit message, offerNetwork is @hide and only exposed via NetworkProvider.",
      "The caller supplies a providerId that matches an existing provider. Per the commit message, such IDs are trivially guessable.",
      "Before the fix no permission was required. After the fix the caller needs NETWORK_FACTORY/MAINLINE_NETWORK_STACK, or MANAGE_TEST_NETWORKS for TRANSPORT_TEST offers."
     ],
     "per_major": {
      "14": "same fix: commit 0eccf35b6b1b in android-security-14.0.0_r21. It is the identical 5-line insertion in ConnectivityService.offerNetwork, at a different offset (around line 7487). 6/6 lines present at android-security-14.0.0_r29.",
      "15": "same fix: commit a2d3f541c78e in android-security-15.0.0_r9, a cherry-pick of ff65257bd07c / 2bde2fe348a9 (Change-Id If71ce012f927a34c647d36b5eaf3723de2c01879). 6/6 lines present at android-security-15.0.0_r17.",
      "16": "adapted fix: commit f27bca2d7d23 in android-16.0.0_r2. The logic is the same, but the test branch calls enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS) without the mContext argument. 6/6 lines present at android-security-16.0.0_r8.",
      "17": "not affected: the bulletin does not list Android 17. The patched region is present (6/6 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The only difference between branches is the enforceAnyPermissionOf call: Android 14/15 use enforceAnyPermissionOf(mContext, perm) and Android 16 uses enforceAnyPermissionOf(perm). Use whichever overload exists in the target ConnectivityService. The 14, 15 and 16 diffs call enforceNetworkFactoryPermission() without adding it, so that helper already existed on those branches.",
      "Connectivity ships as part of the Tethering/Connectivity mainline module, so devices may also get this fix through a module update, not only through the platform security tag (general platform knowledge)."
     ],
     "confidence": "high",
     "unknowns": [
      "Whether handleRegisterNetworkOffer or NetworkOffer handling checks providerId against the registered NetworkProviderInfo set or the caller UID (not shown in the material).",
      "How nextNetworkProviderId() allocates IDs (its body is not shown).",
      "The exact permissions accepted by enforceNetworkFactoryPermission() and enforceAnyPermissionOf() on each branch, and the exception they raise. Only the commit message describes them; their bodies are not shown.",
      "Whether any tests came with the fix (none appear in the diffs provided)."
     ],
     "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-26448": {
     "cve": "CVE-2025-26448",
     "summary": "Replaces malloc with calloc for the inline CursorWindow data buffer in CursorWindow::create() so the buffer is zero-initialized rather than containing stale heap content if the caller does not fully fill it before sending it to the remote end.",
     "component": "platform/frameworks/base, libs/androidfw CursorWindow (android.database native backing)",
     "weakness": "Use of uninitialized heap memory leading to information disclosure (uninitialized buffer transmitted across process boundary)",
     "root_cause": "CursorWindow::create() in libs/androidfw/CursorWindow.cpp allocated the inline window buffer mData with malloc(window->mSize) (mSize = min(kInlineSize=16384, inflatedSize)), leaving its contents uninitialized. clear() and updateSlotsData() are called afterwards, but per the commit message the caller might not fully fill the buffer before sending it to the remote end, so uninitialized heap bytes of the producing process could be transmitted to another process.",
     "fix_analysis": [
      "libs/androidfw/CursorWindow.cpp:CursorWindow::create(): the single change is `window->mData = malloc(window->mSize);` -> `window->mData = calloc(window->mSize, 1);`, so the whole inline buffer is zero-filled at allocation. The subsequent clear()/updateSlotsData() and the failure path (`if (!window->mData) goto fail;`) are unchanged.",
      "CursorWindow::createFromParcel() is intentionally left untouched; the commit message states its buffer is immediately filled from the far end so zeroing is unnecessary there."
     ],
     "completeness": [
      "Covers only the inline allocation in CursorWindow::create(). CursorWindow::maybeInflate() (shown in context, which prepares an ashmem region named \"CursorWindow: \" when the window can expand) is not modified by this commit; the material does not show how that region is initialized or filled.",
      "createFromParcel() is unchanged by design per the commit message; the material does not include its code to independently confirm the buffer is fully overwritten."
     ],
     "behavior_changes": [
      "Inline CursorWindow buffers (up to 16384 bytes) are now zero-filled on creation; slight additional cost from calloc. No API, error code, or format change."
     ],
     "preconditions": [
      "A CursorWindow is created via CursorWindow::create() (inline allocation of min(16384, inflatedSize) bytes) and sent to a remote process without the caller having fully filled the buffer (per commit message).",
      "The specific caller that leaves the buffer partially filled is not identified in the material."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 3c1515f4d194 in android-security-14.0.0_r21, identical one-line malloc->calloc change; patched region fully present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/base b7d9d1744c4f in android-security-15.0.0_r9 (cherry-pick of 9dc64621d896); patched region fully present at android-security-15.0.0_r17.",
      "16": "same fix: platform/frameworks/base 9dc64621d896 in android-16.0.0_r2; patched region fully present at android-security-16.0.0_r8.",
      "17": "not affected: not listed by the bulletin; the patched region (calloc line) is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single-commit, one-line change with no dependencies; applies cleanly wherever CursorWindow::create() uses `malloc(window->mSize)`. If a fork has customized CursorWindow.cpp, apply the same calloc replacement to the inline buffer allocation and review any custom allocation paths."
     ],
     "confidence": "high",
     "unknowns": [
      "Which caller/path leaves the window buffer partially filled before it is sent to the remote end; the material only states that a caller might.",
      "What clear() and updateSlotsData() initialize (code not provided).",
      "How the ashmem region in maybeInflate() is initialized and whether it needed equivalent treatment (code not provided).",
      "Whether a corresponding test was added; the commit lists test suites run but the diff contains no test changes."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26449": {
     "cve": "CVE-2025-26449",
     "summary": "Wraps zen rule lists crossing Binder (INotificationManager.getZenRules/getAutomaticZenRules and the automaticRules/deletedRules maps inside ZenModeConfig) in ParceledListSlice and switches zen-related string parceling to writeString8/readString8, apparently so that large sets of zen rules are no longer carried as one flat array or map in a single parcel.",
     "component": "platform/frameworks/base, NotificationManagerService / Zen mode (AutomaticZenRule, ZenModeConfig, INotificationManager)",
     "weakness": "Likely an oversized Binder transaction: all zen rules were serialized into one parcel (List/Map return types and writeTypedArray). This is inferred from the fix; the bulletin only says DoS.",
     "root_cause": "Before the fix, INotificationManager.getZenRules() returned a plain List<ZenModeConfig.ZenRule> and getAutomaticZenRules() returned a plain Map<String, AutomaticZenRule>. ZenModeConfig.writeRulesToParcel wrote every ZenRule with dest.writeTypedArray into the same parcel, with ids via writeStringArray and strings via writeString (UTF-16 encoding, general platform knowledge). So the whole rule set was serialized into a single reply parcel. The fix moves to ParceledListSlice, which exists to split large Parcelable lists across multiple transactions (general platform knowledge). This suggests the DoS came from an oversized Binder transaction, but neither the bulletin nor the commit says so explicitly.",
     "fix_analysis": [
      "core/java/android/app/INotificationManager.aidl: getAutomaticZenRules() now returns ParceledListSlice<AutomaticZenRule.AzrWithId> instead of Map<String, AutomaticZenRule>; getZenRules() now returns ParceledListSlice<ZenModeConfig.ZenRule> instead of List<ZenModeConfig.ZenRule>.",
      "core/java/android/app/AutomaticZenRule.java: adds the @hide Parcelable AutomaticZenRule.AzrWithId (mId + mRule) so the map entries can be carried as a list; it is declared in AutomaticZenRule.aidl. AutomaticZenRule(Parcel) and writeToParcel switch name, mPkg and mTriggerDescription from readString/writeString to readString8/writeString8.",
      "services/core/java/com/android/server/notification/NotificationManagerService.java: getZenRules() wraps mZenModeHelper.getZenRules() in new ParceledListSlice<>(...). getAutomaticZenRules() converts mZenModeHelper.getAutomaticZenRules().entrySet() into a List<AzrWithId> and returns new ParceledListSlice<>(ruleList). Both keep enforcePolicyAccess; getZenRules now passes the name \"getAutomaticZenRules\".",
      "core/java/android/app/NotificationManager.java getAutomaticZenRules(): in the modesApi branch it rebuilds the Map<String, AutomaticZenRule> client-side from parceledRules.getList() and returns an empty map if the slice is null. In the legacy getZenRules branch it iterates rules.getList(). The public API shape is unchanged.",
      "core/java/android/service/notification/ZenModeConfig.java writeRulesToParcel(ruleMap, dest, flags): writes ids with writeString8Array and the rules with dest.writeParcelable(new ParceledListSlice<>(rules), flags) instead of writeTypedArray. writeToParcel passes flags through for both automaticRules and deletedRules.",
      "core/java/android/service/notification/ZenModeConfig.java readRulesFromParcel: reads ids with readString8Array and reads the ParceledListSlice via readParcelable, treating a null slice as empty. If rules.size() != len it logs Slog.wtf and sets len = 0, so all rules are dropped before ruleMap is filled.",
      "core/java/android/service/notification/ZenModeConfig.java ZenRule(Parcel)/writeToParcel: name, id, enabler, pkg, iconResName and triggerDescription switched to readString8/writeString8 (UTF-8 is more compact than UTF-16 for ASCII strings, general platform knowledge).",
      "services/tests/uiservicestests/.../NotificationManagerServiceTest.java: existing tests updated to consume getAutomaticZenRules().getList() and AzrWithId."
     ],
     "completeness": [
      "Covers the bulk paths that carry the whole rule set: getZenRules(), getAutomaticZenRules(), and ZenModeConfig parceling of automaticRules and deletedRules. ZenModeConfig is returned by getZenModeConfig(), which uses enforceSystemOrSystemUI.",
      "Only the rule collections are chunked. Each individual ZenRule/AutomaticZenRule is still a single Parcelable, and nested fields (zenPolicy, zenDeviceEffects, conditionId, component) are still written with writeParcelable. ZenModeConfig.manualRule is still written with writeParcelable (a single object, not a list).",
      "getAutomaticZenRule(String id), which returns a single rule, is unchanged.",
      "The fix adds no cap on the number of zen rules (addAutomaticZenRule is untouched). Whether a count limit exists elsewhere is not shown in the material.",
      "The mismatch handling in readRulesFromParcel fails soft: on a count mismatch it logs wtf and yields an empty rule map instead of throwing."
     ],
     "behavior_changes": [
      "Hidden Binder interface change: INotificationManager.getZenRules and getAutomaticZenRules now return ParceledListSlice. Any out-of-tree caller of the raw AIDL (rather than NotificationManager) must be updated.",
      "The Parcel wire format of AutomaticZenRule, ZenModeConfig and ZenModeConfig.ZenRule changes (string8 strings, string8 id arrays, ParceledListSlice instead of a typed array). Writer and reader must be updated together.",
      "ZenModeConfig deserialization now drops all rules (with a Slog.wtf) if the embedded count differs from the number of rules in the slice.",
      "NotificationManager.getAutomaticZenRules() returns an empty map instead of passing through null if the service returns a null slice.",
      "The name that getZenRules passes to enforcePolicyAccess is now \"getAutomaticZenRules\"."
     ],
     "preconditions": [
      "The caller must pass enforcePolicyAccess to invoke getZenRules()/getAutomaticZenRules(). getZenModeConfig(), which parcels the full ZenModeConfig, requires system or SystemUI.",
      "Presumably a large enough set of zen rules must exist. How such a set is created, and whether the rule count is limited elsewhere, is not shown in the material.",
      "On Android 15 the getAutomaticZenRules path is gated by Flags.modesApi(); the legacy getZenRules path is used when the flag is off. Both are patched."
     ],
     "per_major": {
      "14": "Adapted fix (commit e3c4ba3c7963, android-security-14.0.0_r21, linked by bug_id). Only getZenRules() switched to ParceledListSlice<ZenModeConfig.ZenRule>; there is no AzrWithId and no deletedRules handling. ZenModeConfig(Parcel)/writeToParcel are patched inline (no readRulesFromParcel/writeRulesToParcel helpers), and string8 is applied to the smaller Android 14 field set. Adds ZenModeConfigTest.testWriteConfigToParcel. 7/8 patched-region lines present at android-security-14.0.0_r29.",
      "15": "Fix as analysed (commit e0a1e45a3d20, android-security-15.0.0_r9, cherry-picked from 3965123f440345017facfe9f767b22d79e55aeab). Both the flagged modesApi getAutomaticZenRules path (AzrWithId) and the legacy getZenRules path are patched, and the string8 changes follow the flag conditions. 7/8 patched-region lines present at android-security-15.0.0_r17.",
      "16": "Adapted fix: commit 3965123f4403 in android-16.0.0_r2 (base). No modesApi conditionals in the patched code, and getZenRules() is not touched or present in the shown AIDL context. The AIDL declares a raw ParceledListSlice getAutomaticZenRules(), and the service uses mZenModeHelper.getAutomaticZenRules(getCallingZenUser(), callingUid). 7/8 patched-region lines present at android-security-16.0.0_r8.",
      "17": "Not affected (the bulletin does not list Android 17). 7/8 patched-region lines present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Apply all files together: the change alters the Parcel format of AutomaticZenRule/ZenModeConfig/ZenRule and the hidden INotificationManager signatures, so framework and services code (and any test doubles implementing INotificationManager) must be updated together. For trees without the modes API (no Flags.modesApi, no getAutomaticZenRules AIDL method, no deletedRules), use the Android 14 commit e3c4ba3c7963 as the template."
     ],
     "confidence": "medium",
     "unknowns": [
      "The exact DoS trigger and symptom (which process fails and how) are not stated in the bulletin or the commit. The ParceledListSlice/string8 nature of the fix suggests oversized Binder transactions, but the material does not say so.",
      "Whether the number of zen rules a caller can register is bounded anywhere else (addAutomaticZenRule / ZenModeHelper are not shown).",
      "The Android 15 commit message references ZenModeConfigTest, but the 15 diff stat lists no ZenModeConfigTest change; the test addition is only visible in the Android 14 commit.",
      "The material does not explain why the per-major check reports 7/8 rather than 8/8 lines present in every latest tag."
     ],
     "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-26450": {
     "cve": "CVE-2025-26450",
     "summary": "IInputMethodSessionWrapper.ImeInputEventReceiver.onInputEvent now drops KeyEvents carrying Ctrl/Alt/Fn/Meta modifiers unless they are younger than 100 ms and pass InputManager.verifyInputEvent, so fabricated events written into the IME's input channel can no longer trigger modifier shortcuts in the IME.",
     "component": "platform/frameworks/base, inputmethodservice (IME input event receiver)",
     "weakness": "Missing origin/authenticity check on input events (improper input validation of events read from the IME InputChannel)",
     "root_cause": "ImeInputEventReceiver.onInputEvent in core/java/android/inputmethodservice/IInputMethodSessionWrapper.java forwarded InputEvents received from the IME's InputChannel directly to the session (KeyEvents to mInputMethodSession.dispatchKeyEvent, other events through the MotionEvent branch) without checking that the event actually originated from the system input pipeline. Per the commit message, a malicious app able to inject into the IME's FD could send fabricated InputEvents that tamper with special shortcuts such as IME switching.",
     "fix_analysis": [
      "core/java/android/inputmethodservice/IInputMethodSessionWrapper.java: constructor now stores the Context in a new field mContext so the receiver can obtain InputManager.",
      "IInputMethodSessionWrapper.java:ImeInputEventReceiver.onInputEvent: before queuing the event in mPendingEvents, if the event is a KeyEvent and hasKeyModifiers(keyEvent) is true, it fetches InputManager via mContext.getSystemService (Objects.requireNonNull), computes age = SystemClock.uptimeMillis() - keyEvent.getEventTime(), and if age >= KEY_EVENT_ALLOW_PERIOD_MS (100 ms) OR im.verifyInputEvent(keyEvent) == null it logs 'Unverified or Invalid KeyEvent injected into IME. Dropping', calls finishInputEvent(event, false) and returns without dispatching.",
      "IInputMethodSessionWrapper.java:ImeInputEventReceiver.hasKeyModifiers (new): returns false if event.hasNoModifiers(), otherwise true if isCtrlPressed() || isAltPressed() || isFunctionPressed() || isMetaPressed().",
      "The existing KeyEvent cast is rewritten to a pattern-match (event instanceof KeyEvent keyEvent); behaviour otherwise unchanged. The age check implements the commit message's 'for any events that are replayed, verify timestamp'."
     ],
     "completeness": [
      "Only KeyEvents with Ctrl/Alt/Fn/Meta modifiers are verified; KeyEvents without those modifiers (including Shift-only, since hasKeyModifiers does not test Shift) are still dispatched unverified.",
      "MotionEvents delivered through the same receiver are not verified.",
      "The Android 16 version adds a per-IME opt-in (onShouldVerifyKeyEvent) so an IME can request verification of additional keys; the 14/15 backport has no such hook, so an IME cannot extend the protected key set.",
      "The Android 16 version contains a TODO(b/331730488) noting accessibility (a11y) events are not yet handled.",
      "The 14/15 drop condition is age >= 100ms || unverified (drop if either); the 16 version uses && (drop only if both old and unverified) and is gated behind the verify_key_event aconfig flag, so the 16 drop condition is less strict than the 14/15 one as written."
     ],
     "behavior_changes": [
      "Modifier KeyEvents reaching the IME that fail InputManager.verifyInputEvent are dropped with a Log.w and finished as not handled.",
      "Modifier KeyEvents whose event time is 100 ms or more in the past relative to SystemClock.uptimeMillis() are dropped even if otherwise valid, which may affect genuine events that are delayed or replayed.",
      "Objects.requireNonNull(im) will throw if InputManager is not available from the IME's Context.",
      "Extra per-event work: a getSystemService lookup and a verifyInputEvent call for each modifier KeyEvent."
     ],
     "preconditions": [
      "Attacker must be able to inject InputEvents into the IME's InputChannel FD (per the commit message); how that FD is obtained is not shown in the material.",
      "The events are processed in ImeInputEventReceiver.onInputEvent of an IInputMethodSessionWrapper, which is created in IInputMethodWrapper.InputMethodSessionCallbackWrapper.sessionCreated for each IME session (per index search).",
      "To be blocked by the fix the injected KeyEvent must carry a Ctrl/Alt/Fn/Meta modifier; the IME must act on such shortcuts (e.g. IME switching, per commit message) for impact."
     ],
     "per_major": {
      "14": "same fix: identical DO NOT MERGE cherry-pick (f48bf9a2e7c7) in android-security-14.0.0_r21, no flag gating, || condition, modifiers Ctrl/Alt/Fn/Meta; 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "same fix: DO NOT MERGE cherry-pick 4cafc04ee7db in android-security-15.0.0_r9 (the analysed diff); 8/8 patched lines present at android-security-15.0.0_r17.",
      "16": "adapted fix: Revert^2 'Verify KeyEvents in IME' (47414432d61c) in android-16.0.0_r2; gated by the is_fixed_read_only aconfig flag android.view.inputmethod.verify_key_event, adds public @FlaggedApi onShouldVerifyKeyEvent on InputMethodService/AbstractInputMethodService and a hidden default on InputMethodSession, uses needsVerification(verifyKeyEvent() && (hasKeyModifiers || onShouldVerifyKeyEvent)), hasKeyModifiers uses hasModifiers(META_CTRL_ON)/hasModifiers(META_ALT_ON)/hasModifiers(KEYCODE_FUNCTION) (no Meta), and drop condition is age >= 100ms && unverified. 8/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (not listed); the patched region is nonetheless present (8/8 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "For 14/15 branches use the standalone DO NOT MERGE variant (single file, no aconfig flag, no new public API); the 16 variant depends on the verify_key_event flag, API txt changes and InputMethodSession.onShouldVerifyKeyEvent. The two variants differ in the drop condition (|| vs &&) and in the modifier set; the 14/15 drop condition is the stricter one."
     ],
     "confidence": "high",
     "unknowns": [
      "How an unprivileged app obtains write access to the IME's InputChannel FD is not shown in the material.",
      "Whether InputManager.verifyInputEvent can succeed for legitimately injected events (e.g. instrumentation) in the IME process is not shown.",
      "Whether the && vs || difference between the 16 and 14/15 variants is intentional is not shown.",
      "Android 13 fix commit is not included in the material.",
      "Whether hasModifiers(KeyEvent.KEYCODE_FUNCTION) in the 16 variant behaves as intended is not shown."
     ],
     "meta": {
      "generated": "2026-10-03",
      "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-2025-26452": {
     "cve": "CVE-2025-26452",
     "summary": "Restricts the \"frro:/\" drawable loading branch in ResourcesImpl.java so that the file named by the URI must canonicalize under /data/resource-cache/, end with \".frro\", be readable, and have a non-negative offset and positive size; otherwise a NotFoundException is thrown.",
     "component": "platform/frameworks/base, resources (ResourcesImpl drawable loading, fabricated runtime resource overlay drawables)",
     "weakness": "Missing validation of a file path and offset/size taken from resource-supplied URI data (unrestricted file open from resource value)",
     "root_cause": "In core/java/android/content/res/ResourcesImpl.java, the drawable loading code (the branch logging \"Loading drawable for cookie\") handled any resource file string beginning with \"frro://\" this way: it parsed the string as a Uri, built a File from '/' + uri.getHost() + uri.getPath(), opened it read-only with ParcelFileDescriptor.open, wrapped it in an AssetFileDescriptor with offset and size taken directly from the \"offset\" and \"size\" query parameters, and decoded it as an image. Nothing restricted which path could be opened and nothing checked offset/size, so the resource value fully controlled which file the loading process opened and which byte range it decoded.",
     "fix_analysis": [
      "core/java/android/app/ResourcesManager.java: adds public static final String RESOURCE_CACHE_DIR = \"/data/resource-cache/\" and makes overlayPathToIdmapPath use it instead of the inline literal (refactor only, no behavior change).",
      "core/java/android/content/res/ResourcesImpl.java, frro branch of the drawable loader: the prefix test is widened from file.startsWith(\"frro://\") to file.startsWith(\"frro:/\"). Single-slash forms now enter the validated branch instead of falling through to mAssets.openNonAsset.",
      "Same branch: offset and size are parsed first. If offset < 0 or size <= 0, a NotFoundException(\"invalid frro parameters\") is thrown before any file is opened.",
      "Same branch: after File f is built, the fix requires f.getCanonicalPath() to start with ResourcesManager.RESOURCE_CACHE_DIR and end with \".frro\", and f.canRead() to be true. Otherwise it throws NotFoundException(\"invalid frro path\"). Because the check uses the canonical path, symlinks and \"..\" segments are resolved before the prefix check. The trailing slash in the constant prevents prefix matches on sibling directories.",
      "ParcelFileDescriptor.open is called only after both checks pass, and the AssetFileDescriptor is built with the already-validated offset and size."
     ],
     "completeness": [
      "Covers the only frro file-open site shown in the material: the drawable path in ResourcesImpl.java. The check is on the canonical path, so symlink and dot-segment tricks are resolved before comparison.",
      "Any readable \".frro\" file anywhere under /data/resource-cache/ is accepted. The fix does not tie the file to the overlay or package the resource came from.",
      "offset and size are only sign-checked. Nothing checks that offset + size lies within the file. The material does not show how AssetFileDescriptor or decodeImageDrawable handle out-of-range values.",
      "If the \"offset\" or \"size\" query parameter is missing, Long.parseLong(null) throws NumberFormatException rather than the new NotFoundException. This was already true before the fix, and the surrounding try/catch handling is not shown.",
      "The material does not show whether other consumers of frro URIs exist outside this drawable path (e.g. for non-drawable resource types)."
     ],
     "behavior_changes": [
      "Drawable resources whose file string is an frro URI pointing outside /data/resource-cache/, not ending in .frro, or not readable now fail with NotFoundException(\"invalid frro path\") instead of being opened.",
      "frro URIs with a negative offset or a non-positive size now fail with NotFoundException(\"invalid frro parameters\").",
      "Strings starting with \"frro:/\" (single slash) are now handled by the frro branch rather than passed to AssetManager.openNonAsset.",
      "getCanonicalPath adds filesystem resolution to each frro drawable load. It can throw IOException, which propagates into the existing try block."
     ],
     "preconditions": [
      "A drawable resource lookup in the affected process resolves to a TypedValue whose file string begins with \"frro:/\". Per the commit title and the /data/resource-cache/ constraint, this is the form used for fabricated runtime resource overlay drawables.",
      "The attacker must be able to influence that resource file string as seen by a process that then loads the drawable. The material does not show how this is done.",
      "The target file must be readable by the process performing the load. The fix now checks this explicitly with f.canRead()."
     ],
     "per_major": {
      "14": "same fix: commit 37a272435a23 in android-security-14.0.0_r21, identical logic. The 14 diff also adds 'import android.app.ResourcesManager;' to ResourcesImpl.java. Patched region: 7/8 lines present at android-security-14.0.0_r29.",
      "15": "same fix: commit 26c58543f19d in android-security-15.0.0_r9 (cherry-pick of 12e49e7a4e56). The code shown at android-security-15.0.0_r17 has all the added checks in place. The patched-region metric reports 6/8 lines present.",
      "16": "same fix: commit 12e49e7a4e56 in android-16.0.0_r2 (the original change; the 15 commit is cherry-picked from it), identical logic. Patched region: 6/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected: the bulletin does not list Android 17. Patched region: 5/8 lines present at android-security-17.0.0_r1. The code itself is not shown."
     },
     "backport_notes": [
      "Single commit touching two files. The only branch-specific delta shown is that the Android 14 diff adds 'import android.app.ResourcesManager;' to ResourcesImpl.java; the 15 and 16 diffs do not add it. The ResourcesImpl check references the ResourcesManager.RESOURCE_CACHE_DIR constant, so add that constant too (or inline the literal).",
      "No 'Fix in fork' section was provided, so no per-file fork verdict can be reported."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not name the method that contains the frro branch in ResourcesImpl.java. It shows only the frro branch and the \"Loading drawable for cookie\" log context.",
      "The material does not describe how an untrusted party gets an frro URI into a resource value that a more privileged process loads.",
      "The material does not show whether the surrounding try/catch catches and converts the exceptions thrown in this block (NotFoundException, NumberFormatException, IOException from getCanonicalPath).",
      "The material does not explain why the latest tags report only 6/8 (15, 16) or 5/8 (17) lines of the patched region present.",
      "The material does not show the exact state of the code on Android 17."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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-26453": {
     "cve": "CVE-2025-26453",
     "summary": "Changes BluetoothOppSendFileInfo.isContentUriForOtherUser to derive the user id from the decoded Uri authority (text before the last '@') instead of Uri.getUserInfo(), so Bluetooth OPP rejects cross-user content URIs the same way ContentProvider interprets them, including URIs that use an encoded '%40' separator.",
     "component": "platform/packages/modules/Bluetooth, OPP (Object Push Profile) outbound share, BluetoothOppSendFileInfo",
     "weakness": "Inconsistent URI parsing leading to an authorization check bypass (the cross-user content URI check parsed the userId differently from the ContentProvider framework)",
     "root_cause": "isContentUriForOtherUser() in android/app/src/com/android/bluetooth/opp/BluetoothOppSendFileInfo.java used Uri.getUserInfo() to decide whether a content URI targets another user. The new javadoc in the diff explains the problem. Under RFC 2396 an encoded '@' ('%40') is data inside the authority, so getUserInfo() does not treat it as a separator. ContentProvider APIs instead use the decoded Uri.getAuthority() with ContentProvider#getUserIdFromAuthority, and there the decoded '%40' becomes the userInfo/host separator. For an authority of the form \"<otherUserId>%40<host>\", the Bluetooth check found no user info and treated the URI as belonging to the current user, while ContentProvider would read it as another user's. This let the OPP cross-user guard be bypassed (bulletin type ID).",
     "fix_analysis": [
      "BluetoothOppSendFileInfo.java:isContentUriForOtherUser: replaces uri.getUserInfo() with explicit parsing of uri.getAuthority(). It returns false if the authority is null or contains no '@'. Otherwise it takes authority.substring(0, authority.lastIndexOf('@')) as uriUserId. Because getAuthority() returns the decoded form, '%40' is now handled as '@', which matches ContentProvider's interpretation as described in the javadoc.",
      "BluetoothOppSendFileInfo.java:isContentUriForOtherUser: the decision that follows is unchanged. The method returns true (other user) when uriUserId is non-empty and differs from String.valueOf(myUserId()). Per the test names, generateFileInfo still returns the error SendFileInfo for such URIs.",
      "BluetoothOppSendFileInfo.java: adds import android.content.ContentProvider, which is referenced by the new javadoc. The javadoc states that Bluetooth, as an unbundled module, cannot access ContentProvider#getUserIdFromAuthority, so it parses the userInfo locally.",
      "BluetoothOppSendFileInfoTest.java: switches the runner to TestParameterInjector. It parameterizes generateFileInfo_withContentUriForOtherUser_returnsSendFileInfoError and generateFileInfo_withContentUriForSameUser_returnsInfoWithCorrectLength over encodedAt, building authorities \"<id>@media\" and \"<id>%40media\"."
     ],
     "completeness": [
      "Covers the cross-user check in BluetoothOppSendFileInfo.isContentUriForOtherUser for both a literal '@' and a percent-encoded '%40' separator, because getAuthority() returns the decoded authority.",
      "Uses lastIndexOf('@'), so when there are several '@' characters the userId is everything before the last one. The material does not show whether ContentProvider#getUserIdFromAuthority handles this case the same way.",
      "Any non-empty prefix that differs from the current user id string is treated as another user and rejected. A null authority, or an authority without '@', is treated as same-user.",
      "This commit touches no other OPP or Bluetooth code paths. The material does not show whether other places in the module run a similar user-id check on URIs."
     ],
     "behavior_changes": [
      "Content URIs whose decoded authority has a user prefix (before the last '@', including one written with an encoded '%40') that differs from the calling user's id are now rejected by generateFileInfo (SendFileInfo error, per the test name). Before the fix, only a literal '@' triggered the rejection.",
      "URIs that use '%40' with the caller's own user id are still accepted (covered by the parameterized same-user test).",
      "Android 14 only: the other-user unit test is annotated @Ignore (b/377774165), and TestParameterInjector is added to static_libs in android/app/tests/unit/Android.bp."
     ],
     "preconditions": [
      "A caller supplies a content:// Uri to Bluetooth OPP for outbound sharing, which reaches BluetoothOppSendFileInfo.generateFileInfo and the isContentUriForOtherUser check (per the test names in the diff).",
      "The URI authority names another user's id using '%40' as the separator.",
      "The device has multiple users, with content belonging to another user."
     ],
     "per_major": {
      "14": "adapted fix: commit 0d3683c8b1c1 (RESTRICT AUTOMERGE) in android-security-14.0.0_r21. It has the same isContentUriForOtherUser logic at a different file offset (hunk at line 262) and no ContentProvider import hunk. It also adds TestParameterInjector to android/app/tests/unit/Android.bp and marks the other-user test @Ignore. At android-security-14.0.0_r29, 7/8 patched lines are present.",
      "15": "same fix: cherry-pick 495d32429fd8 in android-security-15.0.0_r9 (Merged-In I7b6affec5dada7c9f0319fbdb35a6e977e51990f). At android-security-15.0.0_r17, 7/8 patched lines are present and the ContentProvider import is visible in the file.",
      "16": "same fix: bb8a03783901 in android-16.0.0_r2, which is the change the Android 15 commit was cherry-picked from. At android-security-16.0.0_r8, 7/8 patched lines are present.",
      "17": "not affected (not listed by the bulletin). At android-security-17.0.0_r1, 7/8 patched-region lines are present."
     },
     "backport_notes": [
      "Single self-contained commit. The production change is confined to the body of isContentUriForOtherUser, plus a ContentProvider import that the javadoc references. For test parity, older branches need TestParameterInjector in static_libs in android/app/tests/unit/Android.bp, as in the Android 14 backport. That backport @Ignore'd the other-user test with the note 'TODO: b/377774165 - Use source-built BT APEX instead of prebuilt'."
     ],
     "confidence": "high",
     "unknowns": [
      "The exact call path from a share intent to generateFileInfo is not shown. Only the test names indicate that generateFileInfo invokes the check.",
      "Whether ContentProvider#getUserIdFromAuthority uses the same lastIndexOf('@') semantics is not shown in the material.",
      "The per-major facts report 7/8 patched lines present in every branch, but the material does not show which line differs.",
      "Why the other-user test was ignored on Android 14 is not explained beyond the TODO text."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26455": {
     "cve": "CVE-2025-26455",
     "summary": "Makes the NDK AMediaCodec buffer accessors self-consistent: AMediaCodec_getInputBuffer returns the buffer base instead of the offset data pointer, AMediaCodec_getOutputBuffer reports size() instead of capacity(), and AMediaCodec_dequeueOutputBuffer reports offset 0 because the returned output pointer is already offset.",
     "component": "platform/frameworks/av, media/ndk (libmediandk AMediaCodec wrapper)",
     "weakness": "Inconsistent pointer/size/offset semantics returned to NDK clients (the material does not show the concrete memory-safety consequence)",
     "root_cause": "In media/ndk/NdkMediaCodec.cpp, AMediaCodec_getInputBuffer returned abuf->data(), which takes the internal offset into account, while reporting *out_size = abuf->capacity(). Per the commit message this 'erroneously considered the offset, which could result in a smaller input buffer being returned and client confusion'. AMediaCodec_getOutputBuffer returned data() with *out_size = capacity(), which per the commit message 'included padding after the output buffer'. AMediaCodec_dequeueOutputBuffer also copied the internal offset into info->offset, even though, per the fix comment, the address returned by AMediaCodec_getOutputBuffer is already offset.",
     "fix_analysis": [
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getInputBuffer (async path, mAsyncNotify != NULL): returns abuf->base() instead of abuf->data(). out_size stays abuf->capacity(). A comment explains that the offset is set later at queueInputBuffer.",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getInputBuffer (sync path via the getInputBuffers vector): returns abufs[idx]->base() instead of abufs[idx]->data().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getOutputBuffer (async path): *out_size = abuf->size() instead of abuf->capacity(). The pointer is still abuf->data().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_getOutputBuffer (sync path): *out_size = abufs[idx]->size() instead of capacity().",
      "media/ndk/NdkMediaCodec.cpp:AMediaCodec_dequeueOutputBuffer: on OK, sets info->offset = 0 instead of the offset returned by MediaCodec::dequeueOutputBuffer, because the pointer from AMediaCodec_getOutputBuffer is already offset. info->size, flags and presentationTimeUs are unchanged.",
      "media/ndk/include/media/NdkMediaCodec.h: updates the documentation for AMediaCodec_getOutputBuffer and AMediaCodec_dequeueOutputBuffer to describe the semantics at or before and after API level 35, and removes references to the nonexistent AMediaCodec_getInputBuffers/AMediaCodec_getOutputBuffers from the async callback doc. The header changes are comments only."
     ],
     "completeness": [
      "Both the asynchronous (mAsyncNotify) and synchronous (getInputBuffers/getOutputBuffers vector) paths of AMediaCodec_getInputBuffer and AMediaCodec_getOutputBuffer are changed.",
      "AMediaCodec_dequeueOutputBuffer is the only place in the diff where AMediaCodecBufferInfo.offset is zeroed. Any other code that fills an AMediaCodecBufferInfo (for example an asynchronous output-available callback path) is not shown in the material and is not touched by this diff.",
      "The input path keeps out_size = capacity(). The fix changes the pointer rather than the size.",
      "The fix is in the NDK wrapper only. The diff touches no MediaCodec internals.",
      "Per index search, the JNI path in frameworks/base/media/jni/android_media_MediaCodec.cpp (JMediaCodec::getBuffer, createByteBufferFromABuffer) consumes the same MediaCodecBuffer objects. It is a separate consumer and is not modified here."
     ],
     "behavior_changes": [
      "AMediaCodec_getInputBuffer now returns the buffer base address. If the MediaCodecBuffer has a nonzero internal offset, the returned pointer differs from before.",
      "AMediaCodec_getOutputBuffer now reports size() in out_size instead of capacity(), so values may be smaller than before.",
      "AMediaCodec_dequeueOutputBuffer always sets info->offset to 0.",
      "The NDK header documentation is updated with comment-only changes."
     ],
     "preconditions": [
      "A process using the NDK AMediaCodec API (libmediandk) that calls AMediaCodec_getInputBuffer, AMediaCodec_getOutputBuffer or AMediaCodec_dequeueOutputBuffer, in sync or async mode.",
      "The underlying MediaCodecBuffer has a nonzero internal offset, or padding after the valid output.",
      "Known in-tree users per index search: packages/modules/ImsMedia ImsMediaAudioSource::dequeueOutputBuffer (uses info.size with the pointer from AMediaCodec_getOutputBuffer) and the media/ndk fuzzers (NdkMediaCodecFuzzerBase.cpp, ndk_async_codec_fuzzer.cpp), which memcpy up to the reported input bufferSize into the returned pointer."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/av e28ca0c3d70c in android-security-14.0.0_r21. Its hunks and file blob ids (b230df5179..240848096a) are identical to the Android 15 commit. 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/av a5c1d4f8d6d5 in android-security-15.0.0_r9, a cherry-pick of d69fe7b73a0e. 8/8 patched lines present at android-security-15.0.0_r17, and the code context there shows the base() returns in AMediaCodec_getInputBuffer.",
      "16": "same fix (original commit): platform/frameworks/av d69fe7b73a0e in android-16.0.0_r2. Same content at different line offsets (NdkMediaCodec.cpp blob d22a5ba147..62ef6118ca). 8/8 lines present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (not listed). The patched region is present (8/8 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "A single self-contained commit that touches only media/ndk/NdkMediaCodec.cpp and media/ndk/include/media/NdkMediaCodec.h. The Android 14 and 15 patches are byte-identical, and the 16 patch differs only in line offsets. The header hunks are documentation only."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show which client or scenario produced the reported EoP, whether the old pointer/size mismatch could lead to out-of-bounds access, or how large internal offsets or padding are in practice.",
      "Whether other code in NdkMediaCodec.cpp fills AMediaCodecBufferInfo.offset (for example the asynchronous output-available callback) is not shown in the material.",
      "Why Android 13 is listed as affected in the bulletin when no Android 13 fix commit appears in the material."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 4,
      "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-26456": {
     "cve": "CVE-2025-26456",
     "summary": "Limits the secondary dex use entries per owning package (500), dex path length (4096) and class loader context length (10000) that DexUseManagerLocal.notifyDexContainersLoaded accepts, so the persisted dex use database cannot grow without limit. A file-existence pre-check added in the first commit was later changed to not follow symlinks (NOFOLLOW_LINKS), then removed because of sepolicy restrictions.",
     "component": "platform/art, libartservice (ART Service, DexUseManagerLocal in system_server)",
     "weakness": "Missing resource limit on app-supplied input (unbounded growth of an in-memory map and on-disk database)",
     "root_cause": "DexUseManagerLocal.addSecondaryDexUse used computeIfAbsent to create a new SecondaryDexUse entry for every distinct dexPath reported through notifyDexContainersLoaded. There was no cap on the number of entries per owning package and no length limit on the dexPath or classLoaderContext strings. Apps supply this data (the class javadoc says it is \"sent directly by apps, and hence the data should be trusted as little as possible\"), and secondary dex paths are not constrained by the package database. As a result, the DexUse structure and its persisted form /data/system/package-dex-usage.pb could grow without bound, as the commit message of ff0ca4365def describes.",
     "fix_analysis": [
      "Commit 1 (ff0ca4365def, 'Ensure the dex use database cannot grow unboundedly'), DexUseManagerLocal.java: adds the constants MAX_PATH_LENGTH = 4096, MAX_CLASS_LOADER_CONTEXT_LENGTH = 10000 and MAX_SECONDARY_DEX_FILES_PER_OWNER = 500, plus an Injector.getMaxSecondaryDexFilesPerOwner() accessor.",
      "Commit 1, DexUseManagerLocal.java:addSecondaryDexUse: the computeIfAbsent lambda for mSecondaryDexUseByDexFile now returns null and logs 'Not recording too many secondary dex use entries' when packageDexUse.mSecondaryDexUseByDexFile.size() >= mInjector.getMaxSecondaryDexFilesPerOwner(). The method returns early when secondaryDexUse is null. Existing entries can still gain new loader records after the limit is reached (see test testLimitSecondaryDexFiles).",
      "Commit 1, DexUseManagerLocal.java:addSecondaryDexUse: also adds the pre-check 'if (isLoaderOtherApp(loader, owningPackageName) && !mInjector.pathExists(dexPath)) return;', where pathExists is new File(path).exists(). The purpose is to stop a different loading package from using up the owner's entry budget.",
      "Commit 1, input validation loop in DexUseManagerLocal.java:notifyDexContainersLoaded: throws IllegalArgumentException when dexPath.length() > MAX_PATH_LENGTH or classLoaderContext.length() > MAX_CLASS_LOADER_CONTEXT_LENGTH, before the calls to ArtJni.validateDexPath and validateClassLoaderContext. The dex_use.proto changes only add '// key' comments.",
      "Commit 2 (9c88cbbf0028, 'Fix SELinux denial on GMS Core's symlinks'), DexUseManagerLocal.java:Injector.pathExists: switches to Files.exists(Paths.get(path), LinkOption.NOFOLLOW_LINKS), because per the code comment system_server cannot follow GMS Core's symlinks to its secondary dex files.",
      "Commit 3 (74a27958637c, 'Omit file existence check on notifyDexContainersLoaded'), DexUseManagerLocal.java: removes the isLoaderOtherApp/pathExists pre-check and Injector.pathExists 'due to sepolicy restrictions on some platforms'. The tests testNonexistingExternalSecondaryDexPath and testInternalSecondaryDexPath are deleted, and testExistingExternalSecondaryDexPath is renamed to testSecondaryDexPath. In the final state, the per-owner count limit and the two length validations remain."
     ],
     "completeness": [
      "The final code limits secondary dex entries per owning package (500), dex path length (4096) and class loader context length (10000). The commit message says owning packages, loading packages and primary dex paths are already limited by installed packages, so together this bounds the database size.",
      "After commit 3 there is no existence check. A loading package other than the owner can again have non-existent secondary dex paths recorded, and these count toward the owner's per-owner limit, which is the case commit 1 tried to prevent. Growth stays bounded by the limit.",
      "The limit applies only to new dexPath keys. The per-loader records inside an existing SecondaryDexUse (mRecordByLoader) are keyed by loading package name and isolated flag and have no separate cap. Per the commit message, they are bounded by installed packages.",
      "Entries beyond the limit are dropped with a warning log. These diffs add no pruning of an already oversized database loaded from disk."
     ],
     "behavior_changes": [
      "notifyDexContainersLoaded now throws IllegalArgumentException for a dex path longer than 4096 chars or a class loader context longer than 10000 chars.",
      "Once an owning package has 500 distinct secondary dex paths, new paths for it are not recorded (AsLog.w on 15, Log.w on 14: 'Not recording too many secondary dex use entries for <pkg>'). New loaders for already recorded paths are still accepted.",
      "Between commits 1 and 3, loads reported by a package other than the owner were dropped when system_server's existence check failed. After commit 3 this check is gone."
     ],
     "preconditions": [
      "The code is reached through DexUseManagerLocal.notifyDexContainersLoaded in system_server, which records dex-load reports. Per the class javadoc this data is 'sent directly by apps', and the commit was tested with an app-debug.apk from the bug. An installed app that reports many distinct secondary dex paths or long class loader contexts therefore reaches addSecondaryDexUse and the validation loop.",
      "The affected path is secondary dex reporting. Per the commit message, primary dex entries are bounded by installed packages."
     ],
     "per_major": {
      "14": "adapted fix: 1aedae6e1049 in android-security-14.0.0_r21 has the same limits and the same pathExists check. It uses Log.w(TAG, ...) instead of AsLog.w, and its validation loop keeps the Paths.get(dexPath).isAbsolute() check instead of the ArtJni.validateDexPath/validateClassLoaderContext calls seen on 15. 8/8 lines of the patched region are present at android-security-14.0.0_r29. The material does not show whether the two follow-ups (NOFOLLOW_LINKS, removal of the existence check) were applied to 14.",
      "15": "same fix: all three commits (ff0ca4365def, 9c88cbbf0028, 74a27958637c) are in android-security-15.0.0_r9. At android-security-15.0.0_r17 the code has the limit constants and no LinkOption import, which matches the final state. 8/8 lines are present.",
      "16": "fixed in base: android-16.0.0_r2 contains d62d66437f3b (the 'Omit file existence check' commit). Its diff context already shows the per-owner limit code and the NOFOLLOW_LINKS pathExists that it removes. 7/8 lines of the patched region are present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). 7/8 lines of the patched region are present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Apply in order ff0ca4365def, 9c88cbbf0028, 74a27958637c, or squash to the net result: the limits and length validation, without the pathExists/isLoaderOtherApp pre-check and without Injector.pathExists. The test file must also drop the pathExists mock in setUp and the two tests that commit 3 deletes. For 14-style branches, use Log.w(TAG, ...) instead of AsLog.w and keep the Paths.get(dexPath).isAbsolute() validation, as in 1aedae6e1049."
     ],
     "confidence": "high",
     "unknowns": [
      "Whether the follow-up commits 9c88cbbf0028 and 74a27958637c were also applied to the Android 14 security branch (only 1aedae6e1049 is shown for 14).",
      "The exact public entry point (framework API or binder call) through which an app's dex load report reaches notifyDexContainersLoaded is not shown.",
      "How the owning package is derived from a reported dex path is not shown.",
      "Why only 7/8 patched lines match on Android 16 and 17 is not shown.",
      "Whether this fix also reaches devices through an ART mainline module update, rather than only through the platform build, is not shown.",
      "Whether any mitigation exists for an already oversized package-dex-usage.pb loaded at boot."
     ],
     "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."
     }
    },
    "CVE-2025-26458": {
     "cve": "CVE-2025-26458",
     "summary": "Explicitly disables background activity launch on the BroadcastOptions used when LocationPendingIntentTransport sends an app-supplied PendingIntent for location updates and provider-enabled changes.",
     "component": "platform/frameworks/base, system_server location service (LocationProviderManager / LocationPendingIntentTransport)",
     "weakness": "Missing restriction on privileged PendingIntent send (background activity launch not explicitly denied by the system sender)",
     "root_cause": "In services/core/java/com/android/server/location/provider/LocationProviderManager.java, LocationPendingIntentTransport sends a client-provided PendingIntent from system_server in deliverOnLocationChanged and in the provider-enabled-changed delivery path. The BroadcastOptions built with BroadcastOptions.makeBasic() only set setDontSendToRestrictedApps(true) (and, for location delivery, a temporary allowlist for foreground service start). They did not set setPendingIntentBackgroundActivityLaunchAllowed(false), so the send relied on the default background activity launch (BAL) behavior instead of explicitly denying it. The commit message describes this as fixing the default values for the pending intent.",
     "fix_analysis": [
      "LocationProviderManager.java:LocationPendingIntentTransport.deliverOnLocationChanged: after options.setDontSendToRestrictedApps(true), adds options.setPendingIntentBackgroundActivityLaunchAllowed(false) before the temporary allowlist is set and before PendingIntentSender.send(mPendingIntent, mContext, intent, callback, options.toBundle()).",
      "LocationProviderManager.java:LocationPendingIntentTransport provider-enabled delivery (second hunk, the method that sends new Intent().putExtra(KEY_PROVIDER_ENABLED, enabled) via mPendingIntent.send(mContext, 0, ..., options.toBundle())): adds the same options.setPendingIntentBackgroundActivityLaunchAllowed(false) after setDontSendToRestrictedApps(true).",
      "Net effect: both PendingIntent sends performed by system_server on behalf of a location client now carry an explicit BAL denial in the options bundle; the foreground-service temporary allowlist for location delivery is kept unchanged."
     ],
     "completeness": [
      "Covers both PendingIntent send sites inside LocationPendingIntentTransport in LocationProviderManager.java (location changed and provider enabled changed).",
      "Only the options bundle is changed; the test mentioned is LocationProviderTest. Other PendingIntent send sites in the location service outside this class are not touched by this commit and are not shown in the material, so their state is unknown.",
      "The listener (binder callback) transport path, shown in the code context calling mListener.onProviderEnabledChanged, is not changed by this commit."
     ],
     "behavior_changes": [
      "PendingIntents registered for location updates or provider-enabled notifications are now sent with setPendingIntentBackgroundActivityLaunchAllowed(false) explicitly set in the BroadcastOptions.",
      "Foreground-service start via the temporary allowlist on location delivery is unchanged; restricted-app suppression is unchanged."
     ],
     "preconditions": [
      "An app registers a PendingIntent with the location service (LocationPendingIntentTransport is created from a Context and the client's PendingIntent, per the constructor in the code context).",
      "A location result or a provider enabled/disabled change is delivered to that registration by LocationProviderManager, causing system_server to send the PendingIntent."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 9d2acb2d3c5d in android-security-14.0.0_r21, identical two-line addition at shifted line numbers; 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/base 937c2903736f in android-security-15.0.0_r9 (cherry pick of 225602a7d0fe); 8/8 patched lines present at android-security-15.0.0_r17.",
      "16": "same fix (original commit): platform/frameworks/base 225602a7d0fe in android-16.0.0_r2; 8/8 patched lines present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (not listed); patched region (8/8 lines) present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single two-line commit with no dependencies shown; it applies identically on 14, 15 and 16. It calls BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed, which exists on those branches because the fix landed there."
     ],
     "confidence": "high",
     "unknowns": [
      "The bulletin lists Android 13 as affected but no Android 13 commit is included in the material.",
      "The exact default BAL semantics applied by PendingIntent.send when the option is absent are not shown in the material, only that the fix makes the denial explicit.",
      "Whether other location-related PendingIntent send sites exist and whether they already set this option is not shown."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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-26462": {
     "cve": "CVE-2025-26462",
     "summary": "Adds an onNullBinding override to AccessibilityServiceConnection that calls unbindLocked(). An accessibility service whose onBind() returns null is then no longer kept bound by system_server and can no longer launch activities from the background.",
     "component": "platform/frameworks/base, services/accessibility (AccessibilityServiceConnection)",
     "weakness": "Missing cleanup on a ServiceConnection callback (onNullBinding not handled). This left a stale service binding that allowed background activity launches.",
     "root_cause": "AccessibilityServiceConnection handles ServiceConnection callbacks (it overrides onServiceDisconnected) but did not override onNullBinding(). When system_server bound an accessibility service whose onBind() returned null, the connection was not unbound and the tracking resources for the bind were not released. Per the commit message, the service therefore stayed bound by system_server and could launch activities from the background (BAL). The comment in the commit cites ServiceConnection guidance that Context#unbindService must be called from onNullBinding to release these resources.",
     "fix_analysis": [
      "services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java: a new override onNullBinding(ComponentName componentName) is added right after onServiceDisconnected(). It takes mLock and calls unbindLocked(), so that, per the commit message, the service no longer stays bound by system_server.",
      "The fix is a single commit of 10 added lines. No other files or call sites change. The commit references a CTS test, android.security.cts.Bug_386950836, which is not part of the diff."
     ],
     "completeness": [
      "Covers the null-binding path for accessibility services managed by AccessibilityServiceConnection: a service that returns null from onBind() is now unbound.",
      "Only AccessibilityServiceConnection changes. The material does not show whether other ServiceConnection implementations handle onNullBinding, and it shows no similar unfixed pattern, so none is asserted.",
      "The existing onServiceDisconnected path also calls setAllowAppSwitches(..., -1, ...) on mActivityTaskManagerService. The new onNullBinding path only calls unbindLocked(). The material does not show whether unbindLocked() also clears that app-switch allowance."
     ],
     "behavior_changes": [
      "An accessibility service that returns null from onBind() is now unbound by system_server when onNullBinding fires, instead of staying bound.",
      "Per the commit message, such a service can no longer launch activities from the background."
     ],
     "preconditions": [
      "system_server binds an accessibility service through AccessibilityServiceConnection.",
      "The service's onBind() returns null, so the onNullBinding callback is delivered."
     ],
     "per_major": {
      "14": "same fix: commit 7076b2b2bd3c in android-security-14.0.0_r21 adds the identical onNullBinding override (hunk at line 252). The patched region is present at android-security-14.0.0_r29.",
      "15": "same fix: commit af2f9c246ef0 in android-security-15.0.0_r9. The patched region is present at android-security-15.0.0_r17.",
      "16": "same fix: commit eeac12b27c64 in android-16.0.0_r2 (base). The patched region is present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). The patched region is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The change is self-contained: a 10-line method added to AccessibilityServiceConnection.java that uses the existing mLock and unbindLocked(). It applied identically on 14, 15 and 16, differing only in line offset."
     ],
     "confidence": "high",
     "unknowns": [
      "The body of unbindLocked() is not shown, so the material does not show exactly which tracking resources are released or whether the app-switch allowance set elsewhere is cleared.",
      "The material does not show whether the user must enable the service for system_server to bind it.",
      "The Android 13 fix commit is not in the material, so it is not shown whether the same hunk applies on 13 (listed as affected).",
      "The CTS test android.security.cts.Bug_386950836 referenced by the commit is not in the material."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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-26463": {
     "cve": "CVE-2025-26463",
     "summary": "Adds upper bounds on the length of the packageName (223 chars) and certificate (32 bytes) accepted by BlobStoreManager.Session.allowPackageAccess, enforced both in the client wrapper and in the system_server BlobStoreSession.allowPackageAccess Binder implementation.",
     "component": "platform/frameworks/base, BlobStore (apex/blobstore framework + service)",
     "weakness": "missing bounds check on caller-supplied input length (unbounded resource consumption)",
     "root_cause": "BlobStoreSession.allowPackageAccess(String packageName, byte[] certificate) only verified that the caller owned the session and that packageName was non-null before entering the mSessionLock block; it imposed no limit on the length of packageName or certificate (and did not null-check certificate). A session owner could therefore pass arbitrarily large values to the service, which the bulletin classifies as a High severity DoS.",
     "fix_analysis": [
      "apex/blobstore/framework/java/android/app/blob/BlobStoreManager.java: defines two new @hide constants, MAX_PACKAGE_NAME_LENGTH = 223 (commented as matching android.content.pm.parsing.FrameworkParsingPackageUtils#MAX_FILE_NAME_SIZE) and MAX_CERTIFICATE_LENGTH = 32.",
      "BlobStoreManager.java:Session.allowPackageAccess: before calling mSession.allowPackageAccess, now does Objects.requireNonNull(packageName), Preconditions.checkArgument(packageName.length() <= MAX_PACKAGE_NAME_LENGTH), Objects.requireNonNull(certificate), Preconditions.checkArgument(certificate.length <= MAX_CERTIFICATE_LENGTH). This is a client-side early rejection only.",
      "apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java:allowPackageAccess: after assertCallerIsOwner() and the existing requireNonNull(packageName), adds the same two Preconditions.checkArgument length checks plus Objects.requireNonNull(certificate), all before the synchronized (mSessionLock) block. This server-side check is the actual security boundary since it runs in system_server on the Binder path regardless of which client code issued the call.",
      "The service imports the constants statically from BlobStoreManager, so the framework and service halves must carry the change together."
     ],
     "completeness": [
      "Both the client wrapper and the Binder-side implementation of allowPackageAccess are guarded, so calling IBlobStoreSession directly without the framework class is also covered.",
      "Checks are placed before the mSessionLock block and the STATE_OPENED check, so oversized input is rejected before the session's locked code runs.",
      "Only the allowPackageAccess inputs are bounded by this commit; the material does not show whether other caller-supplied strings or arrays handled by BlobStoreSession or BlobStoreManagerService (for example BlobHandle fields) have equivalent length limits.",
      "BlobStoreConfig.getMaxPermittedPackages is imported in BlobStoreSession, suggesting a separate count limit exists; this fix adds per-entry size limits and does not touch that."
     ],
     "behavior_changes": [
      "allowPackageAccess now throws IllegalArgumentException (from Preconditions.checkArgument) when packageName exceeds 223 characters or certificate exceeds 32 bytes, both in the app-side BlobStoreManager.Session and in the system_server BlobStoreSession.",
      "A null certificate is now rejected explicitly with NullPointerException on both sides (previously only packageName was null-checked in the service).",
      "Callers passing a certificate longer than 32 bytes will now be rejected; this is a stricter API contract."
     ],
     "preconditions": [
      "Caller must own an open BlobStoreSession (assertCallerIsOwner() and the STATE_OPENED check remain in place).",
      "Caller supplies an oversized packageName or certificate to allowPackageAccess, either via BlobStoreManager.Session or directly over IBlobStoreSession."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 4b630be2e2b3 in android-security-14.0.0_r21, identical hunks (service hunk offset by one line); 8/8 patched lines present at android-security-14.0.0_r29",
      "15": "same fix: platform/frameworks/base 89c67cf1d19e in android-security-15.0.0_r9, cherry-pick of aaa1cb20b89f (the Android 16 change); 8/8 patched lines present at android-security-15.0.0_r17",
      "16": "same fix: platform/frameworks/base aaa1cb20b89f in android-16.0.0_r2; 8/8 patched lines present at android-security-16.0.0_r8",
      "17": "not affected per the bulletin (not listed); the patched region is present at android-security-17.0.0_r1"
     },
     "backport_notes": [
      "Single commit: apply both files together because BlobStoreSession.java statically imports MAX_PACKAGE_NAME_LENGTH and MAX_CERTIFICATE_LENGTH from BlobStoreManager.java; the hunks are pure insertions, identical on 14, 15 and 16 apart from a one-line offset in the service hunk on 14.",
      "Test: atest CtsBlobStoreTestCases per the commit message; the TODO b/404309424 notes the constants are hardcoded in tests rather than exposed via a test API."
     ],
     "confidence": "high",
     "unknowns": [
      "The bulletin lists Android 13 as affected but no Android 13 commit is included in the material.",
      "The material does not show what the service does with the values inside the mSessionLock block (storage, persistence) or what concretely fails in system_server when oversized values are accepted, only that the bulletin rates it as DoS.",
      "Whether the 32-byte certificate limit was chosen because the service only ever compares a SHA-256 digest is not shown in the material.",
      "Which apps can create a BlobStore session is not shown in the material."
     ],
     "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-32312": {
     "cve": "CVE-2025-32312",
     "summary": "Adds a type check in PackageParser's createIntentsList(Parcel) so that a class name read from a Parcel is only reflectively instantiated if it is a subclass of IntentInfo.",
     "component": "platform/frameworks/base, package manager (core/java/android/content/pm/PackageParser.java, legacy Parcelable support for parsed components)",
     "weakness": "Externally controlled input used to select a class for reflective construction (unsafe reflection during unparceling, missing type validation)",
     "root_cause": "createIntentsList(Parcel in), in the component class inside PackageParser, reads an element count from the Parcel and then a fully qualified class name string. It resolves the name with Class.forName(componentName), looks up a (Parcel) constructor via cls.getConstructor(Parcel.class) and calls cons.newInstance(in) N times. Nothing checked that the named class was an IntentInfo subclass. Whoever controlled the Parcel contents could therefore make the unparceling process load and construct instances of any loadable class with a public Parcel constructor, and pass it the rest of the parcel. The only error handling was an AssertionError on ReflectiveOperationException.",
     "fix_analysis": [
      "core/java/android/content/pm/PackageParser.java : createIntentsList(Parcel): right after Class.forName(componentName), adds `if (!IntentInfo.class.isAssignableFrom(cls)) throw new AssertionError(\"Intent list requires subclass of IntentInfo, not: \" + componentName);`. The constructor lookup and the newInstance loop are now reached only for IntentInfo subclasses.",
      "The check sits inside the existing try block. AssertionError is not a ReflectiveOperationException, so the existing catch does not rewrap it and it propagates out of createIntentsList.",
      "Single commit, 4 inserted lines, no other files changed."
     ],
     "completeness": [
      "Covers the only reflective construction site shown in the material (createIntentsList). The sibling writeIntentsList is a serializer and needs no change.",
      "Class.forName(componentName) still runs before the new check, so the class named in the parcel is still resolved (and, with the single-argument Class.forName, initialized) before it is rejected. The fix only prevents constructor lookup and instantiation of non-IntentInfo classes.",
      "The check is against IntentInfo, not against the specific expected subtype T. Any IntentInfo subclass with a public Parcel constructor is still accepted.",
      "The material does not show whether other Parcel-driven Class.forName patterns exist elsewhere in PackageParser or related classes."
     ],
     "behavior_changes": [
      "Unparceling an intents list that names a class which is not an IntentInfo subclass now fails with AssertionError(\"Intent list requires subclass of IntentInfo, not: <name>\") instead of trying to instantiate that class.",
      "No change for well-formed parcels produced by writeIntentsList, which always writes the runtime class name of an IntentInfo element."
     ],
     "preconditions": [
      "createIntentsList must be reached with attacker-controlled Parcel contents, with N > 0 and an attacker-chosen class name string.",
      "The named class must be loadable in the unparceling process and have a public constructor taking a Parcel.",
      "The material does not show the callers, or the IPC or persistence path by which such a Parcel reaches a privileged process."
     ],
     "per_major": {
      "14": "same fix: platform/frameworks/base 577cdba1048c in android-security-14.0.0_r21. Identical 4-line insertion at the same location (offset by one line). 4/4 lines present at android-security-14.0.0_r29.",
      "15": "same fix: platform/frameworks/base 95eda53ff1d0 in android-security-15.0.0_r9, cherry-picked from 65c1a90bf4af. 4/4 lines present at android-security-15.0.0_r17.",
      "16": "same fix: commit 65c1a90bf4af in android-16.0.0_r2. 4/4 lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). The patched region (4/4 lines) is already present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Self-contained 4-line insertion right after `Class.forName(componentName)` in createIntentsList. It applied identically on 14, 15 and 16 with only line-number offsets.",
      "Android 13 is listed as affected by the bulletin, but the material includes no 13 commit. The same hunk should fit if that branch has the identical createIntentsList body."
     ],
     "confidence": "high",
     "unknowns": [
      "Which callers or IPC/persistence surfaces deliver an attacker-controlled Parcel to createIntentsList (the material does not show the call chain).",
      "Whether an Android 13 fix exists, and in which tag.",
      "Whether the class loading that still happens before the check (Class.forName runs first) was considered in scope."
     ],
     "meta": {
      "generated": "2026-10-03",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 3,
      "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": 16,
    "certain": 15,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2025-26432",
     "osv_id": "ASB-A-386802855",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "code-absent",
     "detail": "probable: none of 2 lines the fix of reference a928f3273592 modifies or sits in exists in android-security-16.0.0_r9 (e.g. 'mAssociationRequestsProcessor.setAssociationTag(associationId, tag);'): the patched code is not in this major",
     "projects": []
    },
    {
     "cve": "CVE-2025-26437",
     "osv_id": "ASB-A-370477460",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "b3d70aab1515d583aeebbcb6440f6c790502bc8f",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26441",
     "osv_id": "ASB-A-367274727",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "3e234b3e3c0a5e3789a38159854bf0b8a774b980",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26443",
     "osv_id": "ASB-A-368319929",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/packages/apps/ManagedProvisioning",
       "sha": "5d67902f6a7498d016ee588d6c00710fb2d3ab98",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/apps/ManagedProvisioning"
     ]
    },
    {
     "cve": "CVE-2025-26445",
     "osv_id": "ASB-A-388828859",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Connectivity",
       "sha": "f27bca2d7d236008f46e8c67154d7c2118a9fbf5",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Connectivity"
     ]
    },
    {
     "cve": "CVE-2025-26448",
     "osv_id": "ASB-A-309407957",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "9dc64621d896d05fcb0e6f45792a307fde130823",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26449",
     "osv_id": "ASB-A-387498139",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "3965123f440345017facfe9f767b22d79e55aeab",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26450",
     "osv_id": "ASB-A-331730488",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "47414432d61ce79083505ff013372d68eb058fc6",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26452",
     "osv_id": "ASB-A-383080440",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "12e49e7a4e56df4dce97f80051063f45e8366329",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26453",
     "osv_id": "ASB-A-395643490",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "bb8a03783901dc92738fdd9af6f3ca88feda4bcf",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2025-26455",
     "osv_id": "ASB-A-301470262",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "d69fe7b73a0ed14c2b5bc237f1a42314140c9458",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/av"
     ]
    },
    {
     "cve": "CVE-2025-26456",
     "osv_id": "ASB-A-391895923",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/art",
       "sha": "d62d66437f3b322f202c314672fbaf810fde7142",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/art"
     ]
    },
    {
     "cve": "CVE-2025-26458",
     "osv_id": "ASB-A-388828203",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "225602a7d0fecefb42c2456067d91f895c72f190",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26462",
     "osv_id": "ASB-A-386950836",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "eeac12b27c64813ebc25e890d0a179000ef4c2ef",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-26463",
     "osv_id": "ASB-A-303227969",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "aaa1cb20b89f3389f9fbc362a397770c8052e7fb",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2025-32312",
     "osv_id": "ASB-A-373467684",
     "source": "osv",
     "announced": "2025-06-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "method": [
      "base"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "last_fix": {
      "tag": "android-16.0.0_r2",
      "date": "2025-06-10",
      "provenance": "base_release"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "65c1a90bf4af54f555ded29ec2384072b1c962b8",
       "tag": "android-16.0.0_r2",
       "provenance": "base_release",
       "method": "base",
       "confidence": "certain",
       "evidence": "fix in the base release, inherited by the security line",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "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": {}
  },
  "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-06-01",
  "latest_version": "1.1",
  "latest_revision": {
   "version": "1.1",
   "date": "June 2, 2025",
   "notes": "AOSP links added"
  },
  "revisions": [
   {
    "version": "1.0",
    "date": "June 2, 2025",
    "notes": "Bulletin Published"
   },
   {
    "version": "1.1",
    "date": "June 2, 2025",
    "notes": "AOSP links added"
   }
  ],
  "tracked_since": "2026-09-30",
  "changes_since_tracking": [],
  "out_of_scope_rows": {
   "Arm components": 2,
   "Imagination Technologies": 7,
   "Qualcomm closed-source components": 6,
   "Qualcomm components": 3
  },
  "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."
 }
}