{
 "month": "2023-12",
 "generated": "2026-10-06T12:05+00:00",
 "majors": {
  "14": {
   "counts": {
    "announced": 28,
    "certain": 26,
    "probable": 2,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [
    {
     "cve": "CVE-2023-40076",
     "osv_id": "ASB-A-303835719",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "Critical",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The Credential Manager service (CredentialManagerUi) now creates the PendingIntent for its UI with PendingIntent.getActivityAsUser bound to UserHandle.of(mUserId) instead of PendingIntent.getActivity, which takes no explicit user.",
      "confidence": "high",
      "backport_notes": [
       "Single, self-contained commit. The target tree needs CredentialManagerUi.java with the mUserId field and the PendingIntent.getActivity call. PendingIntent.getActivityAsUser(Context, int, Intent, int, Bundle, UserHandle) is an existing framework-internal API (general platform knowledge)."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 8,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "9b68987df85b681f9362a3cadca6496796d23bbc",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40077",
     "osv_id": "ASB-A-298057702",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "Critical",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a std::mutex to MetaDataBase::MetaDataInternal and takes it in clear, remove, setData, findData, hasData, toString, dumpToLog and writeToParcel, so concurrent threads no longer race on the KeyedVector of items.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit. The mutex is added to the private MetaDataInternal struct in the .cpp, not to the public header. The bulletin also lists 11, 12, 12L and 13 as affected, but no commit for those branches is in the material."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 8,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "subject"
     ],
     "confidence": "probable",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "f980a9bee224396e1c895b62b6b190fc932edb6a",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "subject",
       "confidence": "probable",
       "evidence": "probable: same subject as reference 58fd993a89a3, common file media/module/foundation/MetaDataBase.cpp, score 1.00",
       "similarity": 1.0
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/av"
     ]
    },
    {
     "cve": "CVE-2023-40088",
     "osv_id": "ASB-A-291500341",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "Critical",
     "types": [
      "RCE"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds `callbackEnv = NULL;` after `vm->DetachCurrentThread()` in the DISASSOCIATE_JVM branch of callback_thread_event in the Bluetooth AdapterService JNI. After the callback thread is detached, the code no longer keeps a dangling JNIEnv pointer.",
      "confidence": "high",
      "backport_notes": [
       "A trivial one-line addition after vm->DetachCurrentThread() in callback_thread_event. It applies to any branch where callbackEnv is a file-scope JNIEnv* set by AttachCurrentThread."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "d45432ee9620bac034c88fa5edacd899cbdf9917",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-45866",
     "osv_id": "ASB-A-294854926",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "Critical",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The Bluetooth BTM security manager (system/stack/btm/btm_sec.cc) now rejects remote-initiated access to L2CAP and RFCOMM services that require incoming authentication when the peer is authenticated through a temporary bond, returning BTM_FAILED_ON_SECURITY. Related commits stop forcing the authenticate bit for SM4 peers and start authentication whenever encryption is required.",
      "confidence": "medium",
      "backport_notes": [
       "Take all four commits together. 1efe6c2e677f ([3]) and 9e02767767c2 cite regression bugs, and they change which services the rejection hits and when authentication starts. Apply [1] before [2], because [2] calls the helper that [1] adds. The helper uses the tBTM_SEC_DEV_REC accessors is_device_authenticated(), is_bond_type_temporary() and IsLocallyInitiated(), so a target branch must provide them."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "09b33986b3f13b756d2a337334ed1a96515e38d5",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "1efe6c2e677f014e8e69e1859c7506f6eb3625a5",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "9e02767767c2ee5b1e4843a3be2ba08a3c02b0de",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "d7e833a2ce6bb3b8ad4f1c8be8cb07785ee49e82",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "e7c86f86a371d9d888e2f6c4904e6fbc4f0ffb98",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 5,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40073",
     "osv_id": "ASB-A-287640400",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Notification.visitUris() now visits the MessagingStyle extras (EXTRA_MESSAGES, EXTRA_HISTORIC_MESSAGES, EXTRA_CONVERSATION_ICON) and the CallStyle extras (EXTRA_CALL_PERSON, call verification icon) whenever extras is non-null. Before the fix this happened only when isStyle(MessagingStyle.class) or isStyle(CallStyle.class) was true. The already-unconditional EXTRA_MESSAGING_PERSON visit is moved next to the other MessagingStyle extras.",
      "confidence": "high",
      "backport_notes": [
       "Single-commit fix limited to Notification.visitUris plus a test. On branches without the typed Bundle.getParcelable(String, Class) and getParcelableArray(String, Class) overloads (added in API 33), use the untyped overloads and keep the same unconditional structure (general platform knowledge)."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "8f326fdea66691d4711cd074bf20a53211c9a7aa",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40075",
     "osv_id": "ASB-A-281061287",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "DoS"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Moves the ensureShortcutCountBeforePush() call in ShortcutPackage from the push path (the method whose disabled-shortcut message references pushDynamicShortcuts()) into forceReplaceShortcutInner, right before saveShortcut(), to bound shortcuts published through addDynamicShortcuts.",
      "confidence": "medium",
      "backport_notes": [
       "Single-file, two-line change: add ensureShortcutCountBeforePush() immediately before saveShortcut() in forceReplaceShortcutInner, and remove the call after the isEnabled() precondition in the push path. Check on the target branch that the push path still reaches the check."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "052789e6a57dce7ecd10c9dd98b90ddd917566a3",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40078",
     "osv_id": "ASB-A-275626001",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a check after the opus_decode() retry in a2dp_vendor_opus_decoder_decode_packet. If the retry fails, the packet is dropped. Before, the negative error code was turned into a huge unsigned frame length that was passed to the decode callback.",
      "confidence": "medium",
      "backport_notes": [
       "Self-contained 6-line insertion with no dependencies shown. Adapt the log call to the tree's logging macro if needed. Keep the 'if (ret_val < OPUS_OK) return false;' guard between the retry opus_decode() call and the frame_len computation."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "6cdf985a664476659b84d8c74698cb3dfa28f82b",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40079",
     "osv_id": "ASB-A-278722815",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "ShortcutService now sends the client-supplied callback IntentSender with ActivityOptions that set MODE_BACKGROUND_ACTIVITY_START_DENIED, so the PendingIntent no longer benefits from system_server's background-activity-launch privilege.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit touching one file; it requires ActivityOptions.setPendingIntentBackgroundActivityStartMode, MODE_BACKGROUND_ACTIVITY_START_DENIED and the IntentSender.sendIntent overload taking an options Bundle to be available in the target tree."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "96e0524c48c6e58af7d15a2caf35082186fc8de2",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40080",
     "osv_id": "ASB-A-275057843",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds MAX_SYNC_TRANSACTION checks on the index returned by the periodic-sync table lookups in system/stack/btm/btm_ble_gap.cc before it is used to address btm_ble_pa_sync_cb.p_sync[] and btm_ble_pa_sync_cb.sync_transfer[], across five functions.",
      "confidence": "high",
      "backport_notes": [
       "Single commit touching only system/stack/btm/btm_ble_gap.cc. Place each check immediately after the index lookup and before the array pointer is formed or used."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "397c1e928552db0b5ae642885e8475de27e47822",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40082",
     "osv_id": "ASB-A-290909089",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "pvmfw now generates a random 64-bit value and writes it into the guest device tree's /chosen/kaslr-seed property, so the template's constant placeholder (-1) is no longer passed to the guest.",
      "confidence": "high",
      "backport_notes": [
       "A backport needs (a) a pvmfw rand module that provides rand::random_array() and (b) a template DT whose /chosen node already has an 8-byte kaslr-seed property, because setprop_inplace replaces an existing property and does not create or resize one (general platform knowledge of libfdt in-place setters). Verify both exist on the target branch.",
       "On branches where the patched region does not fully match or the files are absent, find the equivalent of modify_for_next_stage before applying the fix."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Virtualization",
       "sha": "0cf463e9949db2d30755fc63a79225a6158928d3",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Virtualization"
     ]
    },
    {
     "cve": "CVE-2023-40083",
     "osv_id": "ASB-A-277590580",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a bounds check in parse_gap_data (system/main/shim/utils.cc). When a GAP data element's declared length is larger than the bytes left in the buffer, parsing now stops instead of copying past the end of raw_data.",
      "confidence": "high",
      "backport_notes": [
       "Self-contained 4-line addition inside parse_gap_data. It applies to any branch that has system/main/shim/utils.cc with the same loop. The bulletin lists Android 13 as affected, but no Android 13 commit is 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."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "423c0285e5ee4375e7a71fdb865047513b68b627",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40084",
     "osv_id": "ASB-A-272382770",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Replaces the netdutils::threadLaunch-started monitor thread in netd's MDnsSdListener::Monitor with a stored std::thread. A new Monitor destructor interrupts this thread by closing one end of the control socketpair and then joins it, so Monitor::run can no longer run on a destroyed Monitor instance.",
      "confidence": "high",
      "backport_notes": [
       "Two-file change in system/netd with no new dependency beyond <thread>. For Android 11-13 (listed as affected), apply the same pattern: store the thread, add a destructor that closes mCtrlSocketPair[1] and joins the thread, and add the POLLHUP exit path in run(). Check the revents dispatch on the target branch, which the material does not show."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 8,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/system/netd",
       "sha": "7dae058172acd0c2cd96724cd2feb5e211fe50c2",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/system/netd"
     ]
    },
    {
     "cve": "CVE-2023-40087",
     "osv_id": "ASB-A-275895309",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Bounds the sample loops in transcodeQ15ToFloat, transcodeQ23ToFloat and transcodeQ31ToFloat (system/btif/src/btif_avrcp_audio_track.cc) by the destination buffer length (trackHolder->bufferLength) and replaces the off-by-one `<=` loop condition, which ran one iteration past length/sampleSize.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit. It needs BtifAvrcpAudioTrack to have a `bufferLength` member and std::min to be available. The same file already uses std::clamp.",
       "The commit subject is marked [conflict]. In a customized tree, check the three loop conditions directly instead of relying on the merge result."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "subject"
     ],
     "confidence": "probable",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "ead0b0ab43ef3b00522c77896428996e6bd7aca2",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "subject",
       "confidence": "probable",
       "evidence": "probable: same subject as reference 243fdf1c0d53, common file system/btif/src/btif_avrcp_audio_track.cc, score 0.67",
       "similarity": 0.67
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40089",
     "osv_id": "ASB-A-294228721",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Makes DevicePolicyManager.getCredentialManagerPolicy() user-handle aware. The IDevicePolicyManager call now carries an explicit userId, the service looks up the profile/device owner for that user instead of the Binder caller's user, and cross-user queries require INTERACT_ACROSS_USERS.",
      "confidence": "medium",
      "backport_notes": [
       "All three files must move together: the AIDL signature change requires the DevicePolicyManager client and DevicePolicyManagerService to change in the same build. The referenced test is android.credentials.cts.CtsDevicePolicyTest."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 8,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "e2e05f488da6abc765a62e7faf10cb74e729732e",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40090",
     "osv_id": "ASB-A-274478807",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Replaces the plain memcmp used to compare the computed AES-CMAC with the received signature in BTM_BleVerifySignature with BoringSSL's CRYPTO_memcmp, which is hardened against timing side channels.",
      "confidence": "high",
      "backport_notes": [
       "Single self-contained commit: swap memcmp for CRYPTO_memcmp in BTM_BleVerifySignature and add #include \"openssl/mem.h\". The Bluetooth stack already links against BoringSSL (libcrypto), so no build-rule change should be needed, but check the target's dependencies if the include does not resolve (general platform knowledge).",
       "The bulletin also lists Android 13 as affected, but the Android 13 commit is not in this 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."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "fb76b30e021090d71d7c0e6a57c1ca3acdb9e2d4",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-40091",
     "osv_id": "ASB-A-283699145",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The SHELL_COMMAND_TRANSACTION handler in incidentd's IncidentService::onTransact now reads the in/out/err file descriptors with Parcel::readUniqueFileDescriptor (which dups them) and hands owned fds to fdopen via release(), instead of fdopen'ing fds still owned by the Parcel.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit in cmds/incidentd/src/IncidentService.cpp. It needs Parcel::readUniqueFileDescriptor and android::base::unique_fd (general platform knowledge). The bulletin lists 11 to 13 as affected; when taking the hunk there, check that the local `err` (now unique_fd) and the new `result` variable fit the branch's code."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "29e8df07d8c447c5c4eb94d81b85be6c44295eff",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40092",
     "osv_id": "ASB-A-288110451",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a check in ShortcutService.verifyShortcutInfoPackage that the user ID embedded in a caller-supplied ShortcutInfo equals the user ID of the Binder calling UID, throwing SecurityException otherwise.",
      "confidence": "high",
      "backport_notes": [
       "Single-commit, 4-line addition; it relies on injectBinderCallingUid() and ShortcutInfo.getUserId(), both used in the surrounding code. The bulletin lists 11, 12, 12L, 13 as affected, so the same hunk should apply where verifyShortcutInfoPackage exists in the same form; verify no system-initiated path on the target branch passes shortcuts for other users, since the check has no system exemption."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "af8827252ba25d0287e638862c22b6dfefd2b8d2",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40094",
     "osv_id": "ASB-A-288896339",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a CONTROL_KEYGUARD permission check to the IActivityTaskManager.keyguardGoingAway binder entry point in ActivityTaskManagerService so that callers without that permission can no longer signal that the keyguard is going away.",
      "confidence": "high",
      "backport_notes": [
       "The functional change is one line in ActivityTaskManagerService.keyguardGoingAway, using mAmInternal.enforceCallingPermission. On branches without that helper, mContext.enforceCallingPermission with the same permission and message is the equivalent (general platform knowledge). The AIDL @JavaPassthrough annotation is separate from the runtime check."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "fa30b150bba0d1d6157d037eb3138721bf164ade",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40095",
     "osv_id": "ASB-A-273729172",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "The fix makes PendingIntentUtils.createDontSendToRestrictedAppsBundle explicitly call setPendingIntentBackgroundActivityLaunchAllowed(false) on the BroadcastOptions it builds. PendingIntents that system_server sends with these options (the commit title names requestGeofence) can no longer be used to bypass background activity launch restrictions.",
      "confidence": "medium",
      "backport_notes": [
       "A single one-line change with no other commits listed. It depends on BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed being available in the target branch."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "d1421cacf6bb94fa81d77e907d51a9268d045162",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40096",
     "osv_id": "ASB-A-268724205",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "AudioPolicyService::OpRecordAudioMonitor now registers its AppOps watcher with AppOpsManager::WATCH_FOREGROUND_CHANGES only for apps that target SDK U or later, after an interim revert that removed the flag for all apps. For those apps, foreground and background transitions are watched, so background recording can be silenced.",
      "confidence": "medium",
      "backport_notes": [
       "Apply in order. The revert 3f5420f7eb60 assumes 7370c8442e66 (unconditional WATCH_FOREGROUND_CHANGES) is present, and dc0af854d4dd is based on the post-revert file (index df0c59f6fa). Alternatively, apply only the end state: pass flags computed from doesPackageTargetAtLeastU() to startWatchingMode().",
       "dc0af854d4dd requires content::pm::IPackageManagerNative::getTargetSdkVersionForPackage and the __ANDROID_API_U__ constant. Branches older than 14 may not have the constant (general platform knowledge)."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r2",
      "date": "2023-11-06",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "3f5420f7eb607a74914fde61fb628f43fbdf8e62",
       "tag": "android-security-14.0.0_r2",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/frameworks/av",
       "sha": "dc0af854d4dd6c5bda691f9199198f1928e5b679",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 2,
     "first_commit_before_announcement_days": 25,
     "multi_tag_fix": true,
     "projects": [
      "platform/frameworks/av"
     ]
    },
    {
     "cve": "CVE-2023-40098",
     "osv_id": "ASB-A-288896269",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "SystemUI's conversation notification guts now only requests pinning a People Space (priority conversation) widget when the notification's user is in the same profile group as the system user, so marking a conversation as priority on a secondary user no longer triggers the widget pin request.",
      "confidence": "high",
      "backport_notes": [
       "The fix changes two signatures (NotificationConversationInfo.bindNotification and the NotificationGutsManager constructor, a @SysUISingleton class per its imports); all callers and tests must be updated and a UserManager must be supplied to NotificationGutsManager.",
       "The bulletin lists 12, 12L and 13 as affected but no commits for those branches are in the material; a backport needs both the UserManager plumbing and the isSameProfileGroup guard around requestPinAppWidget in NotificationConversationInfo."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "0c5db0349ae6ba53e38ab89adedaf0299b0893db",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-40103",
     "osv_id": "ASB-A-197260547",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Two frameworks/base commits make AssetManager2 hold promoted (strong) ApkAssets references for the whole duration of a scoped \"operation\" instead of re-promoting weak pointers per access, and make the Java StringBlock/XmlBlock/AssetManager wrappers null out native pointers after destruction and reject calls on a gone native object.",
      "confidence": "medium",
      "backport_notes": [
       "58fa254a5d1a changes the AssetManager2 header API (GetApkAssets() vector getter removed, apk_assets_ type changed), so every caller of GetApkAssets()/apk_assets_ (aapt2 SymbolTable.cpp, Idmap_test.cpp, AssetManager2_test.cpp, any custom code) must be converted to StartOperation() + GetApkAssets(cookie)/GetApkAssetsCount(). The Java commit c3bc12c484ef touches separate files and shows no dependency on it."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 9,
       "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "58fa254a5d1aee2206de90d5396c01e177483e3a",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      },
      {
       "project": "platform/frameworks/base",
       "sha": "c3bc12c484ef3bbca4cec19234437c45af5e584d",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 2,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-45773",
     "osv_id": "ASB-A-275057847",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds MAX_SYNC_TRANSACTION sentinel checks before indexing the periodic-sync tables (p_sync[] and sync_transfer[]) in five functions of system/stack/btm/btm_ble_gap.cc, so a failed index lookup no longer leads to an out-of-bounds access.",
      "confidence": "high",
      "backport_notes": [
       "Single commit touching only system/stack/btm/btm_ble_gap.cc. It uses the existing MAX_SYNC_TRANSACTION constant, the index helpers and the BTM_ILLEGAL_VALUE status. Android 13 is listed as affected by the bulletin, but no 13 commit is shown in the material, so whether it applies cleanly there is not established."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 6,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "change_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "397c1e928552db0b5ae642885e8475de27e47822",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "change_id",
       "confidence": "certain",
       "evidence": "ref 7b30443dac7b",
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-45774",
     "osv_id": "ASB-A-288113797",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "ShortcutService now checks, while validating an incoming shortcut, that the calling UID can grant read access to the content URI behind a URI-based shortcut icon (Icon.TYPE_URI / TYPE_URI_ADAPTIVE_BITMAP), using UriGrantsManagerInternal.checkGrantUriPermission.",
      "confidence": "medium",
      "backport_notes": [
       "Single self-contained commit. It depends on an existing mUriGrantsManagerInternal field and on injectBinderCallingUid() in ShortcutService. On the older branches listed as affected (11, 12, 12L, 13), check that these exist, and that ContentProvider.getUriWithoutUserId / getUserIdFromUri and Icon.TYPE_URI_ADAPTIVE_BITMAP are available."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 11,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "1332ecd5e322a80706cf4f5ff7eb8f58f19586fd",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-45775",
     "osv_id": "ASB-A-275340684",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds length checks (size >= 2) on the StreamingAudioContext LTV value in LeAudioBroadcasterImpl::CreateAudioBroadcast before it is written with UINT16_TO_STREAM and read with STREAM_TO_UINT16, returning early on short values.",
      "confidence": "high",
      "backport_notes": [
       "Single commit: add the two size checks right after each successful ltv.Find(kLeAudioMetadataTypeStreamingAudioContext) in CreateAudioBroadcast, before the UINT16_TO_STREAM / STREAM_TO_UINT16 macros. If the target tree also has a broadcast_id-keyed path with the same Find/STREAM pattern (as in the r29 excerpt), add the same check there. Bluetooth is a mainline module, so the fix may also arrive through a module update rather than the platform tag (general platform knowledge)."
      ],
      "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "8e3b3fc918b3ea77754c6d82ab0f09cce81e145b",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-45776",
     "osv_id": "ASB-A-282234870",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds length checks in LeAudioBroadcasterImpl (system/bta/le_audio/broadcaster/broadcaster.cc) so that the 2-byte StreamingAudioContext LTV value from caller-supplied broadcast subgroup metadata is only read or written when the value vector holds at least 2 bytes.",
      "confidence": "high",
      "backport_notes": [
       "Single commit: add a size() < 2 check right before each UINT16_TO_STREAM / STREAM_TO_UINT16 on the StreamingAudioContext value. If the target tree has been refactored, find every site that calls ltv.Find(kLeAudioMetadataTypeStreamingAudioContext) and dereferences .data() with a 2-byte macro.",
       "In the r29 context, pp is assigned before the check and the log string is different. Either order is safe because pp is only dereferenced after the check."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 5,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "8e3b3fc918b3ea77754c6d82ab0f09cce81e145b",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    },
    {
     "cve": "CVE-2023-45777",
     "osv_id": "ASB-A-299930871",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "EoP"
     ],
     "status": "resolved",
     "brief": {
      "summary": "In AccountManagerService.checkKeyIntentParceledCorrectly, replaces the deprecated untyped Bundle.getParcelable(KEY_INTENT) read of the authenticator-supplied bundle with the typed getParcelable(KEY_INTENT, Intent.class).",
      "confidence": "medium",
      "backport_notes": [
       "The commit is a one-line change. Bundle.getParcelable(String, Class) exists from API 33 / Android 13 (general platform knowledge). The later r29 form of the method also changes the simulateBundle read and adds a null branch; compare against that form when backporting."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 11,
       "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
      }
     },
     "method": [
      "bug_id"
     ],
     "confidence": "certain",
     "first_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "e6a018a836966f00c416e68034df1c930fabdf90",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/frameworks/base"
     ]
    },
    {
     "cve": "CVE-2023-45781",
     "osv_id": "ASB-A-275553827",
     "source": "osv",
     "announced": "2023-12-01",
     "severity": "High",
     "types": [
      "ID"
     ],
     "status": "resolved",
     "brief": {
      "summary": "Adds a bounds check in parse_gap_data (system/main/shim/utils.cc). If a GAP data element's length byte points past the end of raw_data, parsing now stops instead of copying out of bounds.",
      "confidence": "high",
      "backport_notes": [
       "A single self-contained 4-line hunk with no dependencies. It applies anywhere parse_gap_data exists with the same loop structure. The bulletin lists Android 13 as affected, but no Android 13 commit is in the material."
      ],
      "meta": {
       "generated": "2026-10-04",
       "author_model": "claude-fable-5-1",
       "review_model": "claude-opus-5-5",
       "review_corrections": 1,
       "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_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "last_fix": {
      "tag": "android-security-14.0.0_r3",
      "date": "2023-12-04",
      "provenance": "security_tag"
     },
     "public_commits": [
      {
       "project": "platform/packages/modules/Bluetooth",
       "sha": "423c0285e5ee4375e7a71fdb865047513b68b627",
       "tag": "android-security-14.0.0_r3",
       "provenance": "security_tag",
       "method": "bug_id",
       "confidence": "certain",
       "evidence": null,
       "similarity": null
      }
     ],
     "n_public_commits": 1,
     "projects": [
      "platform/packages/modules/Bluetooth"
     ]
    }
   ],
   "tags": [
    "android-security-14.0.0_r3"
   ],
   "unannounced": [
    {
     "bug_ids": [
      "300861053"
     ],
     "commits": [
      {
       "project": "platform/frameworks/av",
       "sha": "7784a011a7e49509f03051272210d8896b1be1e1",
       "subject": "NdkMedia: fix android.mediav2.cts.CodecEncoderSurfaceTest failed.",
       "tag": "android-security-14.0.0_r3",
       "merged": "2023-10-11",
       "markers": []
      }
     ],
     "tags": [
      "android-security-14.0.0_r3"
     ],
     "tag": "android-security-14.0.0_r3"
    },
    {
     "bug_ids": [
      "261709193"
     ],
     "commits": [
      {
       "project": "platform/frameworks/base",
       "sha": "4d71fa0cd4459f7bfed4808c53d3c62a96e32aa6",
       "subject": "Adding in verification of calling UID in onShellCommand",
       "tag": "android-security-14.0.0_r3",
       "merged": "2023-10-11",
       "markers": []
      }
     ],
     "tags": [
      "android-security-14.0.0_r3"
     ],
     "tag": "android-security-14.0.0_r3"
    }
   ],
   "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-2023-40076": {
     "cve": "CVE-2023-40076",
     "summary": "The Credential Manager service (CredentialManagerUi) now creates the PendingIntent for its UI with PendingIntent.getActivityAsUser bound to UserHandle.of(mUserId) instead of PendingIntent.getActivity, which takes no explicit user.",
     "component": "platform/frameworks/base, services/credentials (CredentialManagerUi, Credential Manager service)",
     "weakness": "Missing explicit user binding when creating a PendingIntent in a system service (cross-user effect inferred, not shown)",
     "root_cause": "In services/credentials/java/com/android/server/credentials/CredentialManagerUi.java, the method that builds the Credential Manager UI intent (random UUID action, requestCode 0, FLAG_IMMUTABLE) returned PendingIntent.getActivity(mContext, 0, intent, FLAG_IMMUTABLE). That call does not tie the PendingIntent to the requesting user stored in the class field mUserId. The material does not show which user mContext resolves to. The bulletin rates the issue Critical, type ID (information disclosure); the material does not describe the disclosure path.",
     "fix_analysis": [
      "Commit 9b68987df85b (one file, 5 insertions, 2 deletions) in CredentialManagerUi.java adds import android.os.UserHandle. It replaces PendingIntent.getActivity(mContext, /*requestCode=*/0, intent, PendingIntent.FLAG_IMMUTABLE) with PendingIntent.getActivityAsUser(mContext, /*requestCode=*/0, intent, PendingIntent.FLAG_IMMUTABLE, /*options=*/null, UserHandle.of(mUserId)).",
      "The explicit UserHandle makes the PendingIntent target the user stored in mUserId for this CredentialManagerUi instance. The request code, the random-UUID action and FLAG_IMMUTABLE are unchanged."
     ],
     "completeness": [
      "Covers the single PendingIntent creation site in CredentialManagerUi.java shown in the diff. The fix is one changed call plus an import.",
      "The existing TODO about creating a unique pending intent with a request code and cancelling pre-existing pending intents is left in place. requestCode stays 0, and uniqueness still relies only on the random UUID action.",
      "The material shows no other PendingIntent creation sites in the credentials service, so it cannot show whether sibling paths exist."
     ],
     "behavior_changes": [
      "The Credential Manager UI PendingIntent is now created for UserHandle.of(mUserId). The fix adds no new error codes or validation failures."
     ],
     "preconditions": [
      "A Credential Manager request handled by CredentialManagerUi for which the UI PendingIntent is created (the code path with the random-UUID action intent).",
      "Inferred from the diff: the change likely only matters when mUserId differs from the user mContext resolves to, for example in a multi-user or profile configuration. The exact trigger is not shown in the material."
     ],
     "per_major": {
      "14": "same fix: resolved via commit 9b68987df85b in android-security-14.0.0_r3 (cherry-picked, Change-Id If03e146a069b9162d41eee26b7070ea52827fddf); 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "not affected (not listed by the bulletin); 8/8 patched lines present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); 8/8 patched lines present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); 8/8 patched lines present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single, self-contained commit. The target tree needs CredentialManagerUi.java with the mUserId field and the PendingIntent.getActivity call. PendingIntent.getActivityAsUser(Context, int, Intent, int, Bundle, UserHandle) is an existing framework-internal API (general platform knowledge)."
     ],
     "confidence": "high",
     "unknowns": [
      "The diff hunk header does not show the name of the method that contains the changed PendingIntent call.",
      "Which user mContext resolves to, and so which user the PendingIntent targeted before the fix, is not shown.",
      "The material does not describe the information disclosure path that led to the Critical rating.",
      "The material does not show whether other PendingIntent creation sites exist in the credentials service.",
      "Whether releases older than 14 contain this code is not covered by the material."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 8,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40077": {
     "cve": "CVE-2023-40077",
     "summary": "Adds a std::mutex to MetaDataBase::MetaDataInternal and takes it in clear, remove, setData, findData, hasData, toString, dumpToLog and writeToParcel, so concurrent threads no longer race on the KeyedVector of items.",
     "component": "platform/frameworks/av, media foundation (MetaDataBase, media/module/foundation/MetaDataBase.cpp), reached via httplive (HTTP Live Streaming) per the commit subject",
     "weakness": "Race condition leading to use-after-free (unsynchronized access to a KeyedVector shared across threads)",
     "root_cause": "MetaDataBase stores its items in a KeyedVector<uint32_t, typed_data> inside MetaDataInternal with no synchronization. When one thread mutates the vector (setData, remove, clear) while another thread looks it up or iterates it (findData, hasData, toString, dumpToLog, writeToParcel), the vector can change underneath the reader, which then accesses the wrong memory. The commit message attributes the use-after-free to the httplive path.",
     "fix_analysis": [
      "media/module/foundation/MetaDataBase.cpp: adds #include <mutex> and a std::mutex mLock member to struct MetaDataBase::MetaDataInternal. That struct is accessed through the mInternalData pointer, so const methods can also lock it.",
      "MetaDataBase::clear and MetaDataBase::remove: take std::lock_guard<std::mutex> on mInternalData->mLock before touching mItems.",
      "MetaDataBase::setData: the lock is taken before indexOfKey and the add or replace of the item that follows.",
      "MetaDataBase::findData and MetaDataBase::hasData (both const): the lock is taken before indexOfKey.",
      "MetaDataBase::toString and MetaDataBase::dumpToLog: the lock is taken before iterating mItems by index (size()/keyAt). MetaDataBase::writeToParcel: the lock is taken before reading mItems.size().",
      "Single commit with 11 insertions and no logic or data-structure change. The fix only adds mutual exclusion around the existing KeyedVector operations."
     ],
     "completeness": [
      "The eight functions touched by the diff are now serialized by a per-object mutex.",
      "The diff does not touch the MetaDataBase copy constructor, operator=, constructor or destructor. The material does not show whether these access mItems without the lock.",
      "The lock is per MetaDataBase instance and does not address the lifetime of the MetaDataBase object itself."
     ],
     "behavior_changes": [
      "The patched MetaDataBase functions now acquire a non-recursive std::mutex, so calls on the same object from different threads serialize. There are no new error codes or API changes.",
      "Re-entrant use (calling another locked method on the same object while the lock is held) would deadlock. The diff shows no such nesting inside the patched functions."
     ],
     "preconditions": [
      "A MetaDataBase (or MetaData) object shared between at least two threads, with one thread mutating it (setData, remove or clear) while another reads or iterates it.",
      "Per the commit message, the triggering path is HTTP Live Streaming (httplive) in frameworks/av. The exact call sites are not shown in the material."
     ],
     "per_major": {
      "14": "same fix: commit f980a9bee224 landed in android-security-14.0.0_r3. At android-security-14.0.0_r29, 8/8 lines of the patched region are present in media/module/foundation/MetaDataBase.cpp.",
      "15": "not affected (not listed by the bulletin). The patched region (8/8 lines) is present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin). The patched region (8/8 lines) is present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin). The patched region (8/8 lines) is present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained commit. The mutex is added to the private MetaDataInternal struct in the .cpp, not to the public header. The bulletin also lists 11, 12, 12L and 13 as affected, but no commit for those branches is in the material."
     ],
     "confidence": "high",
     "unknowns": [
      "The specific httplive call sites and threads that raced on the MetaDataBase object (the commit message only names the component).",
      "Whether the MetaDataBase copy constructor or operator= access mItems without the new lock.",
      "Whether the data pointer returned by findData points into vector-owned storage and is used by callers after the lock is released.",
      "The fix commits for Android 11, 12, 12L and 13, and the path of MetaDataBase.cpp on those branches."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 8,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40088": {
     "cve": "CVE-2023-40088",
     "summary": "Adds `callbackEnv = NULL;` after `vm->DetachCurrentThread()` in the DISASSOCIATE_JVM branch of callback_thread_event in the Bluetooth AdapterService JNI. After the callback thread is detached, the code no longer keeps a dangling JNIEnv pointer.",
     "component": "platform/packages/modules/Bluetooth, android/app/jni (AdapterService JNI callback thread / CallbackEnv)",
     "weakness": "Use-after-free (dangling pointer to a freed JNI environment)",
     "root_cause": "In android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp, callback_thread_event(ASSOCIATE_JVM) attaches the callback thread with vm->AttachCurrentThread(&callbackEnv, &args). This stores the thread's JNIEnv* in the file-scope variable callbackEnv. On DISASSOCIATE_JVM, the code called vm->DetachCurrentThread() and cleared sHaveCallbackThread, but it left callbackEnv pointing at the environment. Per the commit message, detaching frees that environment context. The commit message says the stale variable allows a UAF 'under certain conditions', and its title ('Fix UAF in ~CallbackEnv') names the CallbackEnv destructor as the place where the UAF happens.",
     "fix_analysis": [
      "android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp:callback_thread_event, DISASSOCIATE_JVM branch: after vm->DetachCurrentThread() and sHaveCallbackThread = false, the fix adds callbackEnv = NULL;. Code that reads callbackEnv later sees a null pointer instead of a dangling pointer to the freed JNIEnv.",
      "Single one-line commit (d45432ee9620). The commit message says a custom JNI unit test was written but deliberately left out of the merged change."
     ],
     "completeness": [
      "The fix only clears the global callbackEnv in the detach path. It does not change CallbackEnv itself or the attach path. Whether it is effective depends on CallbackEnv (constructor, valid(), destructor) treating a NULL callbackEnv as invalid. The CallbackEnv implementation is not in the provided material, so the code shown cannot confirm this.",
      "Nulling callbackEnv after DetachCurrentThread() is not atomic, and the diff adds no locking. The diff does not address whether another thread can observe callbackEnv between the two statements. The isCallbackThread() check does limit the detach to the callback thread itself.",
      "Only this JNI file is changed. Other JNI files in the Bluetooth app that may keep their own JNIEnv globals are not part of this fix and are not shown in the material."
     ],
     "behavior_changes": [
      "After the callback thread is disassociated from the JVM, callbackEnv is NULL instead of stale. The diff adds no new error codes, log messages or API changes. How CallbackEnv reacts to the NULL value is not shown."
     ],
     "preconditions": [
      "The Bluetooth stack's callback thread must be torn down (a DISASSOCIATE_JVM event delivered to callback_thread_event on the callback thread), and afterwards a CallbackEnv that relies on the global callbackEnv must be used or destroyed. The material does not describe the exact triggering sequence beyond 'certain conditions' in the commit message.",
      "The code is in the Bluetooth AdapterService JNI inside the Bluetooth process. The bulletin rates the issue Critical RCE but gives no further trigger detail."
     ],
     "per_major": {
      "14": "same fix: commit d45432ee9620 in android-security-14.0.0_r3. At android-security-14.0.0_r29 the patched region is fully present (2/2 lines), with callbackEnv = NULL at line 765.",
      "15": "not affected (not listed by the bulletin). The patched region is present at android-security-15.0.0_r17 (2/2 lines).",
      "16": "not affected (not listed by the bulletin). The patched region is present at android-security-16.0.0_r8 (2/2 lines).",
      "17": "not affected (not listed by the bulletin). The patched region is present at android-security-17.0.0_r1 (2/2 lines)."
     },
     "backport_notes": [
      "A trivial one-line addition after vm->DetachCurrentThread() in callback_thread_event. It applies to any branch where callbackEnv is a file-scope JNIEnv* set by AttachCurrentThread."
     ],
     "confidence": "high",
     "unknowns": [
      "The CallbackEnv class implementation (constructor, valid(), ~CallbackEnv) is not in the provided material, so the exact place where the stale callbackEnv is dereferenced is not shown, nor is how a NULL value is handled.",
      "The commit message only says 'under certain conditions'; it does not describe when DISASSOCIATE_JVM races with or comes before a CallbackEnv use.",
      "The per-major facts do not show which security-13 tag carries the fix for Android 13."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-45866": {
     "cve": "CVE-2023-45866",
     "summary": "The Bluetooth BTM security manager (system/stack/btm/btm_sec.cc) now rejects remote-initiated access to L2CAP and RFCOMM services that require incoming authentication when the peer is authenticated through a temporary bond, returning BTM_FAILED_ON_SECURITY. Related commits stop forcing the authenticate bit for SM4 peers and start authentication whenever encryption is required.",
     "component": "platform/packages/modules/Bluetooth, BR/EDR security manager (system/stack/btm/btm_sec.cc)",
     "weakness": "Missing authorization check: authentication obtained via a temporary bond was accepted as sufficient for services requiring incoming authentication",
     "root_cause": "In btm_sec.cc the grant paths of btm_sec_l2cap_access_req_by_requirement (rc == BTM_SUCCESS branch, which called p_callback with a hardcoded BTM_SUCCESS), btm_sec_mx_access_request (rc == BTM_SUCCESS branch) and btm_sec_execute_procedure (the 'All required security procedures already established' step, which clears the AUTHENTICATE/ENCRYPT bits) did not consider whether the authenticated peer's bond was temporary (is_bond_type_temporary()). So a remote-initiated request for a service whose security_required includes BTM_SEC_IN_AUTHENTICATE could be granted for a temp-bonded, authenticated peer.",
     "fix_analysis": [
      "Commit 09b33986b3f1 ([1]) btm_sec.cc: adds static helper access_secure_service_from_temp_bond(p_dev_rec, locally_initiated, security_req). It returns true when the request is not locally initiated, security_req has BTM_SEC_IN_AUTHENTICATE, p_dev_rec->is_device_authenticated() is true and p_dev_rec->is_bond_type_temporary() is true.",
      "Commit 09b33986b3f1 btm_sec.cc:btm_sec_l2cap_access_req_by_requirement: in the rc == BTM_SUCCESS path, the helper is evaluated with is_originator and security_required. On a match rc becomes BTM_FAILED_ON_SECURITY, which is now passed to p_callback and returned instead of the hardcoded BTM_SUCCESS.",
      "Commit 09b33986b3f1 btm_sec.cc:btm_sec_execute_procedure: before the 'All required security procedures already established' step that clears the AUTHENTICATE/ENCRYPT bits from p_dev_rec->security_required, the helper is evaluated with p_dev_rec->IsLocallyInitiated() and p_dev_rec->security_required. On a match the function returns BTM_FAILED_ON_SECURITY.",
      "Commit d7e833a2ce6b ([2]) btm_sec.cc:btm_sec_mx_access_request (RFCOMM multiplexer path): in the rc == BTM_SUCCESS branch the same helper is applied, and rc is set to BTM_FAILED_ON_SECURITY before p_callback is invoked.",
      "Commit 1efe6c2e677f ([3], citing Nearby regression bug 298539299) btm_sec.cc:btm_sec_l2cap_access_req_by_requirement: for SM4-to-SM4 links in BTM_SEC_MODE_SP/BTM_SEC_MODE_SC, BTM_SEC_OUT_AUTHENTICATE / BTM_SEC_IN_AUTHENTICATE are no longer forced into security_required. Only BTM_SEC_OUT_ENCRYPT / BTM_SEC_IN_ENCRYPT are added. Because the new rejection keys on BTM_SEC_IN_AUTHENTICATE, this narrows the rejection to services that require authentication (commit body: 'Allow access to rfcomm PSM by default').",
      "Commit 9e02767767c2 (unnumbered, citing regression bugs 299570702/299561281) btm_sec.cc:btm_sec_execute_procedure: when the BR/EDR link is not BTM_SEC_AUTHENTICATED, start_auth is now set if security_required has either the AUTHENTICATE bit or the ENCRYPT bit for the relevant direction, so encryption-only requirements also trigger authentication."
     ],
     "completeness": [
      "The temp-bond rejection is applied on three grant paths: the rc == BTM_SUCCESS path of btm_sec_l2cap_access_req_by_requirement, the 'already established' path of btm_sec_execute_procedure, and the rc == BTM_SUCCESS branch of btm_sec_mx_access_request (RFCOMM).",
      "Only remote-initiated (acceptor) requests are rejected. Locally initiated requests make access_secure_service_from_temp_bond return false.",
      "The check keys on BTM_SEC_IN_AUTHENTICATE only. With 1efe6c2e677f applied, encryption-only incoming requirements are not caught by the temp-bond check. 9e02767767c2 makes such requirements start authentication in btm_sec_execute_procedure when the link is not yet authenticated.",
      "The material does not show whether btm_sec_l2cap_access_req_by_requirement or btm_sec_mx_access_request have other early-success returns outside the diffed hunks, and it shows no change to LE (SMP) paths."
     ],
     "behavior_changes": [
      "Service access callbacks can now receive BTM_FAILED_ON_SECURITY instead of BTM_SUCCESS for remote-initiated access from a temp-bonded, authenticated peer to a service requiring BTM_SEC_IN_AUTHENTICATE. btm_sec_execute_procedure returns BTM_FAILED_ON_SECURITY in the same case.",
      "New LOG_ERROR lines: 'Trying to access a secure service from a temp bonding, rejecting' and 'Trying to access a secure rfcomm service from a temp bonding, reject'.",
      "SM4-to-SM4 links in SP/SC mode no longer get BTM_SEC_OUT_AUTHENTICATE / BTM_SEC_IN_AUTHENTICATE forced into security_required in btm_sec_l2cap_access_req_by_requirement. Only the ENCRYPT bits are added.",
      "btm_sec_execute_procedure now starts authentication on an unauthenticated BR/EDR link when encryption is required, not only when authentication is required."
     ],
     "preconditions": [
      "A device record whose bond type is temporary and which is authenticated (is_device_authenticated()).",
      "Remote-initiated (not locally initiated) L2CAP or RFCOMM service access whose security_required includes BTM_SEC_IN_AUTHENTICATE, reaching btm_sec_l2cap_access_req_by_requirement, btm_sec_mx_access_request or btm_sec_execute_procedure.",
      "Per index search, btm_sec_l2cap_access_req_by_requirement is mocked in system/test/mock/mock_stack_btm_sec.h. The search surfaced no other callers, so the material does not show the full set of entry points."
     ],
     "per_major": {
      "14": "Same fix: four commits (09b33986b3f1, d7e833a2ce6b, 1efe6c2e677f, 9e02767767c2) in android-security-14.0.0_r3, all in system/stack/btm/btm_sec.cc. At android-security-14.0.0_r29, 5/5 lines of the patched region are present.",
      "15": "Not affected per the bulletin. At android-security-15.0.0_r17, 6/8 lines of the patched region are present. The material does not show whether an equivalent check exists.",
      "16": "Not affected per the bulletin. At android-security-16.0.0_r8, 3/8 lines of the patched region are present. The material does not show whether an equivalent check exists.",
      "17": "Not affected per the bulletin. At android-security-17.0.0_r1, 2/8 lines of the patched region are present. The material does not show whether an equivalent check exists."
     },
     "backport_notes": [
      "Take all four commits together. 1efe6c2e677f ([3]) and 9e02767767c2 cite regression bugs, and they change which services the rejection hits and when authentication starts. Apply [1] before [2], because [2] calls the helper that [1] adds. The helper uses the tBTM_SEC_DEV_REC accessors is_device_authenticated(), is_bond_type_temporary() and IsLocallyInitiated(), so a target branch must provide them."
     ],
     "confidence": "medium",
     "unknowns": [
      "The material does not describe the concrete trigger or which profile/service the EoP targets. It shows only the code-level condition (temp bond plus an incoming authentication requirement).",
      "The relative order of 9e02767767c2 among the numbered commits is not stated.",
      "Whether an equivalent check exists in Android 15/16/17, where the patched region only partially matches.",
      "Whether btm_sec_l2cap_access_req_by_requirement or btm_sec_mx_access_request have other early-success returns outside the diffed hunks."
     ],
     "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-2023-40073": {
     "cve": "CVE-2023-40073",
     "summary": "Notification.visitUris() now visits the MessagingStyle extras (EXTRA_MESSAGES, EXTRA_HISTORIC_MESSAGES, EXTRA_CONVERSATION_ICON) and the CallStyle extras (EXTRA_CALL_PERSON, call verification icon) whenever extras is non-null. Before the fix this happened only when isStyle(MessagingStyle.class) or isStyle(CallStyle.class) was true. The already-unconditional EXTRA_MESSAGING_PERSON visit is moved next to the other MessagingStyle extras.",
     "component": "platform/frameworks/base, core/java/android/app/Notification.java (Notification.visitUris)",
     "weakness": "Incomplete URI enumeration in Notification.visitUris: style-specific extras were skipped when the style was not applied",
     "root_cause": "In Notification.visitUris(), several URIs were visited only inside `if (isStyle(MessagingStyle.class) && extras != null)` and `if (isStyle(CallStyle.class) & extras != null)` blocks. For MessagingStyle these were the sender icons in EXTRA_MESSAGES and EXTRA_HISTORIC_MESSAGES and EXTRA_CONVERSATION_ICON. For CallStyle they were the EXTRA_CALL_PERSON icon and the verification icon. An app can put these extras into notification.extras without applying the style to the Builder; the test does this with messagingStyle.addExtras(notification.extras) and callStyle.addExtras(notification.extras). In that case isStyle() is false and the visitor never sees those URIs. Per the comment added by the fix, Notification Listeners may still use these extras directly without an isStyle check.",
     "fix_analysis": [
      "core/java/android/app/Notification.java:visitUris: the `isStyle(MessagingStyle.class) && extras != null` guard is removed. The EXTRA_MESSAGES, EXTRA_HISTORIC_MESSAGES and EXTRA_CONVERSATION_ICON visits move into the generic `if (extras != null)` block. The EXTRA_MESSAGING_PERSON visit was already in that generic block; it is only moved next to the other MessagingStyle extras, so its behavior is unchanged.",
      "core/java/android/app/Notification.java:visitUris: the `isStyle(CallStyle.class) & extras != null` guard is removed in the same way. EXTRA_CALL_PERSON (the Person icon URI) and the call verification icon are now visited inside the same `if (extras != null)` block. This also removes the non-short-circuit `&`.",
      "services/tests/uiservicestests/.../NotificationManagerServiceTest.java: the new test testVisitUris_styleExtrasWithoutStyle builds a notification without a style and injects MessagingStyle and CallStyle extras via addExtras(). It checks that the visitor receives content://user, content://historicalMessenger, content://messenger, content://conversationShortcut, content://caller and content://callVerification."
     ],
     "completeness": [
      "Covers the MessagingStyle and CallStyle extras that visitUris already handled: they are now visited whether or not a style is applied.",
      "Other extras in the generic block (EXTRA_LARGE_ICON_BIG, EXTRA_PICTURE_ICON, EXTRA_AUDIO_CONTENTS_URI, EXTRA_BACKGROUND_IMAGE_URI, EXTRA_PEOPLE_LIST, EXTRA_REMOTE_INPUT_HISTORY_ITEMS, EXTRA_MESSAGING_PERSON) were already unconditional and are not changed.",
      "The fix only widens what visitUris enumerates. It does not change where visitUris is called or how the visited URIs are checked.",
      "At android-security-14.0.0_r29 the code shows later changes on top of the fix: person.visitUris(visitor), getParcelableArrayFromBundle for EXTRA_MESSAGES, and message.visitUris. These likely account for the 6/8 line match. The unconditional structure and the explanatory comment are present."
     ],
     "behavior_changes": [
      "Content URIs inside MessagingStyle and CallStyle extras are now passed to the visitUris visitor even for notifications that do not declare those styles. Whatever the caller does with visited URIs now also applies to them.",
      "No new API, error code or configuration. The change is internal to Notification.visitUris."
     ],
     "preconditions": [
      "An app posts a Notification whose extras Bundle contains MessagingStyle and/or CallStyle extras without applying the matching style via Notification.Builder.setStyle, so isStyle() returns false.",
      "The extras carry content:// URIs (Person icons, the conversation or shortcut icon, the verification icon).",
      "A consumer reads those extras directly without an isStyle check. The fix comment names Notification Listeners as such consumers."
     ],
     "per_major": {
      "14": "same fix: commit 8f326fdea666 in android-security-14.0.0_r3 (linked by bug_id). At android-security-14.0.0_r29, 6/8 lines of the patched region are present, with later refactoring of the visit calls on top.",
      "15": "not affected per the bulletin. At android-security-15.0.0_r17, 6/8 lines of the patched region are present; the code is not otherwise shown.",
      "16": "not affected per the bulletin. At android-security-16.0.0_r8, 6/8 lines of the patched region are present; the code is not otherwise shown.",
      "17": "not affected per the bulletin. At android-security-17.0.0_r1, 6/8 lines of the patched region are present; the code is not otherwise shown."
     },
     "backport_notes": [
      "Single-commit fix limited to Notification.visitUris plus a test. On branches without the typed Bundle.getParcelable(String, Class) and getParcelableArray(String, Class) overloads (added in API 33), use the untyped overloads and keep the same unconditional structure (general platform knowledge)."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show the commits for Android 11, 12, 12L and 13, which the bulletin lists as affected.",
      "The material does not show the NotificationManagerService call site that uses visitUris, or what it does with the visited URIs. The impact of the missed URIs is inferred from the fix comment and the test.",
      "The code at the 15, 16 and 17 tags is not shown beyond the 6/8 line match.",
      "The material does not show whether visitUris handles any other style-specific extras beyond those in the diff and context."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40075": {
     "cve": "CVE-2023-40075",
     "summary": "Moves the ensureShortcutCountBeforePush() call in ShortcutPackage from the push path (the method whose disabled-shortcut message references pushDynamicShortcuts()) into forceReplaceShortcutInner, right before saveShortcut(), to bound shortcuts published through addDynamicShortcuts.",
     "component": "platform/frameworks/base, ShortcutService (services/core/java/com/android/server/pm/ShortcutPackage.java)",
     "weakness": "Missing resource limit enforcement on a code path (unbounded growth of shortcuts per package)",
     "root_cause": "Before the fix, ShortcutPackage.java called ensureShortcutCountBeforePush() only in the push path (right after the Preconditions check whose message references pushDynamicShortcuts()). forceReplaceShortcutInner saved shortcuts without it. Per the commit message, when an app has multiple main activities, the total number of shortcuts published through addDynamicShortcuts could grow indefinitely. The bulletin classifies this as a DoS.",
     "fix_analysis": [
      "ShortcutPackage.java:forceReplaceShortcutInner: after forceDeleteShortcutInner(newShortcut.getId()), saveIconAndFixUpShortcutLocked and fixUpShortcutResourceNamesAndValues, a call to ensureShortcutCountBeforePush() is inserted immediately before saveShortcut(newShortcut).",
      "ShortcutPackage.java: the ensureShortcutCountBeforePush() call that followed Preconditions.checkArgument(newShortcut.isEnabled(), \"pushDynamicShortcuts() cannot publish disabled shortcuts\") is removed. Net diff: 1 insertion, 1 deletion, one file."
     ],
     "completeness": [
      "Any code that saves a shortcut through forceReplaceShortcutInner now runs ensureShortcutCountBeforePush() first. Which methods call forceReplaceShortcutInner is not shown.",
      "The material does not show whether the push path still reaches ensureShortcutCountBeforePush() after its own call was removed.",
      "Paths that call saveShortcut() directly, without forceReplaceShortcutInner, are not covered by this change. The material does not show whether such paths exist.",
      "The implementation of ensureShortcutCountBeforePush() (the limit it applies, and whether it rejects or evicts) is not in the material."
     ],
     "behavior_changes": [
      "Shortcuts saved through forceReplaceShortcutInner are now subject to ensureShortcutCountBeforePush() before saveShortcut(). The commit message names addDynamicShortcuts as the affected API.",
      "The count check no longer runs at the start of the push path. Its effect on that path depends on call structure not shown in the material."
     ],
     "preconditions": [
      "An installed app that publishes dynamic shortcuts through addDynamicShortcuts (per the commit message).",
      "Per the commit message, the app has multiple main activities."
     ],
     "per_major": {
      "14": "same fix: resolved via commit 052789e6a57d in android-security-14.0.0_r3 (linked by bug_id); at android-security-14.0.0_r29 all 8/8 lines of the patched region are present.",
      "15": "not affected (not listed by the bulletin); at android-security-15.0.0_r17 the patched region is present (8/8 lines).",
      "16": "not affected (not listed by the bulletin); at android-security-16.0.0_r8 the patched region is present (8/8 lines).",
      "17": "not affected (not listed by the bulletin); at android-security-17.0.0_r1 the patched region is present (8/8 lines)."
     },
     "backport_notes": [
      "Single-file, two-line change: add ensureShortcutCountBeforePush() immediately before saveShortcut() in forceReplaceShortcutInner, and remove the call after the isEnabled() precondition in the push path. Check on the target branch that the push path still reaches the check."
     ],
     "confidence": "medium",
     "unknowns": [
      "The body of ensureShortcutCountBeforePush() and the limit it enforces are not shown.",
      "Whether addOrReplaceDynamicShortcut and the push path call forceReplaceShortcutInner. The full list of callers of forceReplaceShortcutInner/saveShortcut is not shown.",
      "The name of the method the check was removed from is not shown in the diff.",
      "The bulletin lists Android 11, 12, 12L, 13 as affected, but only the Android 14 commit is in the material."
     ],
     "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-2023-40078": {
     "cve": "CVE-2023-40078",
     "summary": "Adds a check after the opus_decode() retry in a2dp_vendor_opus_decoder_decode_packet. If the retry fails, the packet is dropped. Before, the negative error code was turned into a huge unsigned frame length that was passed to the decode callback.",
     "component": "platform/packages/modules/Bluetooth, system/stack/a2dp (A2DP Opus vendor codec decoder)",
     "weakness": "Missing return-value check leading to signed-to-unsigned conversion and out-of-bounds buffer access",
     "root_cause": "In system/stack/a2dp/a2dp_vendor_opus_decoder.cc, a2dp_vendor_opus_decoder_decode_packet calls opus_decode(). If the first call fails, it retries with a different set of parameters (the retry call shown in the diff passes A2DP_OPUS_DECODE_BUFFER_LENGTH and flags 0). The return value of the retry was not checked. It was used directly in 'size_t frame_len = ret_val * numChannels * sizeof(a2dp_opus_decoder_cb.decode_buf[0])', and the result was handed to a2dp_opus_decoder_cb.decode_callback. If the retry also fails, ret_val is negative. Converted to unsigned, it gives an enormous size that overflows the frame buffer (per the commit message).",
     "fix_analysis": [
      "system/stack/a2dp/a2dp_vendor_opus_decoder.cc:a2dp_vendor_opus_decoder_decode_packet: right after the retry opus_decode() call and before frame_len is computed, the fix adds 'if (ret_val < OPUS_OK) { LOG_ERROR(\"Opus DecodeFrame retry failed with %d, dropping packet\", ret_val); return false; }'. A failed retry now returns false before the size computation and before decode_callback is called.",
      "Single-commit fix: 6 added lines, no other files touched."
     ],
     "completeness": [
      "Covers the unchecked path shown in the diff, which is the result of the retry opus_decode() call. Per the commit message, a failed first decode leads to the retry, so the retry result is the value that reaches the frame_len computation.",
      "The fix adds no explicit upper-bound check that frame_len fits in decode_buf. It relies on opus_decode() respecting the frame_size argument it is given. The material does not show the decode_buf declaration, so this cannot be verified.",
      "Only the Opus vendor decoder is changed. The material shows nothing about other A2DP decoders."
     ],
     "behavior_changes": [
      "A2DP Opus packets for which both the first and the retry opus_decode() fail are now dropped. The function logs 'Opus DecodeFrame retry failed with %d, dropping packet' at error level and returns false instead of calling decode_callback.",
      "No change for packets that decode successfully on the first or second attempt."
     ],
     "preconditions": [
      "The A2DP Opus vendor decoder must be in use and decoding a packet in a2dp_vendor_opus_decoder_decode_packet.",
      "The packet must be one for which opus_decode() fails on both the first call and the retry.",
      "The callers of a2dp_vendor_opus_decoder_decode_packet, and how a remote peer could cause the decode failures, are not shown in the material."
     ],
     "per_major": {
      "14": "same fix: commit 6cdf985a6644 in android-security-14.0.0_r3 (cherry-pick of internal c7b6e560eda0, Merged-In Ie8ec891bf5e2537eeee9272f550ae23f8797a878). At android-security-14.0.0_r29, only 2/4 lines of the patched region are present. The material does not show the current text or explain the difference.",
      "15": "not affected per the bulletin (not listed). At android-security-15.0.0_r17, 2/4 lines of the patched region are present. Whether the guard exists in another form is not shown.",
      "16": "not affected per the bulletin (not listed). At android-security-16.0.0_r8, 2/4 lines of the patched region are present. Whether the guard exists in another form is not shown.",
      "17": "not affected per the bulletin (not listed). At android-security-17.0.0_r1, 2/4 lines of the patched region are present. Whether the guard exists in another form is not shown."
     },
     "backport_notes": [
      "Self-contained 6-line insertion with no dependencies shown. Adapt the log call to the tree's logging macro if needed. Keep the 'if (ret_val < OPUS_OK) return false;' guard between the retry opus_decode() call and the frame_len computation."
     ],
     "confidence": "medium",
     "unknowns": [
      "The surrounding code is not in the material: the first opus_decode() call, its failure branch, the decode_buf declaration and size, and how decode_callback consumes frame_len.",
      "The actual text of the patched region at android-security-14.0.0_r29 and in the 15/16/17 tags is not shown. It is unclear why only 2/4 lines match and whether the guard is present in an equivalent form.",
      "Which code calls a2dp_vendor_opus_decoder_decode_packet, and whether it can be triggered remotely, is not shown."
     ],
     "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-2023-40079": {
     "cve": "CVE-2023-40079",
     "summary": "ShortcutService now sends the client-supplied callback IntentSender with ActivityOptions that set MODE_BACKGROUND_ACTIVITY_START_DENIED, so the PendingIntent no longer benefits from system_server's background-activity-launch privilege.",
     "component": "platform/frameworks/base, services/core ShortcutService (requestPinAppWidget callback path)",
     "weakness": "Confused deputy / improper privilege handling: a caller-provided PendingIntent is sent by system_server without rescinding background activity launch (BAL) privileges",
     "root_cause": "In services/core/java/com/android/server/pm/ShortcutService.java (hunk at ~line 4407), the service calls intentSender.sendIntent(mContext, 0, extras, null, null) on an IntentSender supplied by a client (per the commit message, the callback PendingIntent passed into AppWidgetManager.requestPinAppWidget). Because the send originates from system_server, the PendingIntent could bypass background activity launch (BAL) checks (per the commit message). No ActivityOptions were passed with the send.",
     "fix_analysis": [
      "services/core/java/com/android/server/pm/ShortcutService.java: before calling intentSender.sendIntent, build ActivityOptions.makeBasic().setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_DENIED).",
      "The call is switched to the 7-argument overload intentSender.sendIntent(mContext, 0, extras, null, null, null, options.toBundle()) so the denial option is passed with the send; the existing SendIntentException handling (Slog.w) is unchanged.",
      "Imports added: static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED and android.app.ActivityOptions."
     ],
     "completeness": [
      "Only the single sendIntent call in ShortcutService.java shown in the hunk is changed; the fix is a one-file, one-call change.",
      "The material does not show other places in ShortcutService or in the AppWidget pin flow where a caller-supplied IntentSender/PendingIntent is sent from system_server; whether those exist and are covered is not determinable from the material.",
      "The commit message lists a manual test, BackgroundActivityLaunchTest, and regression tests (RequestPinAppWidgetTest, PeopleSpaceWidgetManagerTest); no new test is included in the diff."
     ],
     "behavior_changes": [
      "The callback PendingIntent sent by ShortcutService is now sent with a background activity start mode of DENIED, so it can no longer rely on system_server being the sender to start an activity from the background.",
      "sendIntent now passes a non-null options Bundle (ActivityOptions with background start mode denied) instead of no options."
     ],
     "preconditions": [
      "A client supplies a callback IntentSender/PendingIntent that reaches the ShortcutService send path (per the commit message, via AppWidgetManager.requestPinAppWidget).",
      "The code path at ~line 4407 is reached, i.e. the early-return above the try block is not taken (the condition is not shown in the material)."
     ],
     "per_major": {
      "14": "same fix: commit 96e0524c48c6 in android-security-14.0.0_r3 (cherry-pick of eb90469587d9, Change-Id I2df9de272192c9a149a9ff519c96e6e0e8304040); at android-security-14.0.0_r29 8/8 lines of the patched region are present.",
      "15": "not affected per the bulletin; the patched code (8/8 lines) is present at android-security-15.0.0_r17.",
      "16": "not affected per the bulletin; patched code present (8/8 lines) at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin; patched code present (8/8 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single self-contained commit touching one file; it requires ActivityOptions.setPendingIntentBackgroundActivityStartMode, MODE_BACKGROUND_ACTIVITY_START_DENIED and the IntentSender.sendIntent overload taking an options Bundle to be available in the target tree."
     ],
     "confidence": "high",
     "unknowns": [
      "The name of the enclosing method and the early-return condition preceding the try block are not shown in the hunk.",
      "Whether other system_server send sites for caller-supplied PendingIntents in the shortcut/appwidget pin flow exist and were addressed separately.",
      "Effect of the added options on non-activity PendingIntents (broadcast/service) is not shown.",
      "Which API level introduced the ActivityOptions BAL-mode APIs used by the fix (relevant for trees older than 14) is not shown.",
      "Why Android 15+ are listed as not affected (the bulletin lists only 14 and 14-next); the material only shows that the patched code is present there."
     ],
     "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-2023-40080": {
     "cve": "CVE-2023-40080",
     "summary": "Adds MAX_SYNC_TRANSACTION checks on the index returned by the periodic-sync table lookups in system/stack/btm/btm_ble_gap.cc before it is used to address btm_ble_pa_sync_cb.p_sync[] and btm_ble_pa_sync_cb.sync_transfer[], across five functions.",
     "component": "platform/packages/modules/Bluetooth, BT stack BLE GAP periodic advertising sync (system/stack/btm/btm_ble_gap.cc)",
     "weakness": "Missing bounds check (out-of-bounds array index when a lookup returns the sentinel MAX_SYNC_TRANSACTION)",
     "root_cause": "The added checks show that btm_ble_get_psync_index(sid, addr) and btm_ble_get_free_sync_transfer_index() can return MAX_SYNC_TRANSACTION as a 'not found / no free slot' value. In btm_ble_start_sync_request and btm_ble_start_sync_timeout, the result of btm_ble_get_psync_index was used directly to form &btm_ble_pa_sync_cb.p_sync[index] without checking for that value; btm_ble_start_sync_request then wrote p->sync_state. In BTM_BlePeriodicSyncTransfer and BTM_BlePeriodicSyncSetInfo, the result of btm_ble_get_free_sync_transfer_index was used directly as &btm_ble_pa_sync_cb.sync_transfer[index] and written (p_sync_transfer->in_use = true) without a check. In BTM_BleStartPeriodicSync the sentinel was already checked, but the pointer &p_sync[index] was computed before the check. The commit title describes these as OOB bugs.",
     "fix_analysis": [
      "system/stack/btm/btm_ble_gap.cc:btm_ble_start_sync_request: after int index = btm_ble_get_psync_index(sid, addr), if index == MAX_SYNC_TRANSACTION, LOG_ERROR and return before computing p = &btm_ble_pa_sync_cb.p_sync[index] and setting p->sync_state.",
      "system/stack/btm/btm_ble_gap.cc:btm_ble_start_sync_timeout: the same check after btm_ble_get_psync_index(adv_sid, address); LOG_ERROR and return before p is taken from p_sync[index].",
      "system/stack/btm/btm_ble_gap.cc:BTM_BleStartPeriodicSync: the existing index == MAX_SYNC_TRANSACTION check (syncCb with BTM_NO_RESOURCES, then return) is kept, and the computation of p = &btm_ble_pa_sync_cb.p_sync[index] is moved after it.",
      "system/stack/btm/btm_ble_gap.cc:BTM_BlePeriodicSyncTransfer: after int index = btm_ble_get_free_sync_transfer_index(), if index == MAX_SYNC_TRANSACTION, BTM_TRACE_ERROR, cb.Run(BTM_ILLEGAL_VALUE, addr) and return before writing sync_transfer[index].",
      "system/stack/btm/btm_ble_gap.cc:BTM_BlePeriodicSyncSetInfo: the same check, with an early return through cb.Run(BTM_ILLEGAL_VALUE, addr), before writing sync_transfer[index]."
     ],
     "completeness": [
      "The fix guards all five index uses in the diff: two users of btm_ble_get_psync_index (btm_ble_start_sync_request, btm_ble_start_sync_timeout), a reordering in BTM_BleStartPeriodicSync, and two users of btm_ble_get_free_sync_transfer_index (BTM_BlePeriodicSyncTransfer, BTM_BlePeriodicSyncSetInfo).",
      "The check compares only against the exact value MAX_SYNC_TRANSACTION, so it relies on the helpers never returning any other out-of-range value.",
      "Other users of these index helpers elsewhere in btm_ble_gap.cc are not in the material, so it is not shown whether they already check the sentinel.",
      "The fix is a single commit to one file, with no helper or header changes."
     ],
     "behavior_changes": [
      "BTM_BlePeriodicSyncTransfer and BTM_BlePeriodicSyncSetInfo now call the caller's callback with BTM_ILLEGAL_VALUE and return when no free sync_transfer slot index is returned.",
      "btm_ble_start_sync_request now returns early with a LOG_ERROR when the lookup returns MAX_SYNC_TRANSACTION; in that case PeriodicScanStart is not issued and the SYNC_TIMEOUT alarm is not armed.",
      "btm_ble_start_sync_timeout now returns early with a LOG_ERROR when the lookup returns MAX_SYNC_TRANSACTION, skipping the rest of the timeout handling.",
      "BTM_BleStartPeriodicSync behaviour is unchanged (same BTM_NO_RESOURCES callback); only the pointer computation moved."
     ],
     "preconditions": [
      "Bluetooth enabled and the LE periodic advertising sync path reached: BTM_BleStartPeriodicSync, BTM_BlePeriodicSyncTransfer or BTM_BlePeriodicSyncSetInfo called, or the sync timeout alarm (set in btm_ble_start_sync_request) firing. The callers are not shown in the material.",
      "For the psync paths: btm_ble_get_psync_index returns MAX_SYNC_TRANSACTION for the (sid, address) pair.",
      "For the transfer and set-info paths: btm_ble_get_free_sync_transfer_index returns MAX_SYNC_TRANSACTION (no free slot).",
      "The material shows no remote-only trigger; the bulletin classifies the issue as EoP."
     ],
     "per_major": {
      "14": "same fix: commit 397c1e928552 in android-security-14.0.0_r3 (cherry-pick of internal 3bb913ee8c7d); all 8 patched lines present at android-security-14.0.0_r29.",
      "15": "not affected per the bulletin (not listed); the patched region (8/8 lines) is present at android-security-15.0.0_r17.",
      "16": "not affected per the bulletin (not listed); the patched region (8/8 lines) is present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin (not listed); 0/8 patched lines present at android-security-17.0.0_r1. The material does not show why."
     },
     "backport_notes": [
      "Single commit touching only system/stack/btm/btm_ble_gap.cc. Place each check immediately after the index lookup and before the array pointer is formed or used."
     ],
     "confidence": "high",
     "unknowns": [
      "The definitions of btm_ble_get_psync_index, btm_ble_get_free_sync_transfer_index, MAX_SYNC_TRANSACTION and the btm_ble_pa_sync_cb arrays (including their sizes) are not in the material; the sentinel meaning is inferred from the added checks.",
      "Whether other users of these index helpers in btm_ble_gap.cc already check the sentinel.",
      "Who calls these functions and how far up the trigger reaches.",
      "Which of the two bugs (275057843, 275057678) maps to which function, and the exact trigger used in testing.",
      "Why the patched lines are absent at android-security-17.0.0_r1."
     ],
     "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-2023-40082": {
     "cve": "CVE-2023-40082",
     "summary": "pvmfw now generates a random 64-bit value and writes it into the guest device tree's /chosen/kaslr-seed property, so the template's constant placeholder (-1) is no longer passed to the guest.",
     "component": "platform/packages/modules/Virtualization, pvmfw (protected VM firmware), device tree preparation for the guest payload",
     "weakness": "Use of a constant/predictable value where a random value is required (guest KASLR seed never randomized)",
     "root_cause": "The pvmfw template device tree has a placeholder /chosen/kaslr-seed value (the commit message says the constant -1). modify_for_next_stage in pvmfw/src/fdt.rs patched the DICE node, set the strict-boot and new-instance chosen flags and filtered bootargs, but never wrote kaslr-seed. As a result the constant placeholder was passed to the guest.",
     "fix_analysis": [
      "pvmfw/src/main.rs:main: before it configures the device tree, main calls rand::random_array() and converts the result with u64::from_ne_bytes into kaslr_seed. If the RNG fails, the error is logged ('Failed to generated guest KASLR seed') and mapped to RebootReason::InternalError, so the payload is not started.",
      "pvmfw/src/main.rs:main: passes kaslr_seed to modify_for_next_stage as a new trailing argument.",
      "pvmfw/src/fdt.rs:modify_for_next_stage: adds a new parameter kaslr_seed: u64. After setting the avf,strict-boot and avf,new-instance chosen flags, it writes the seed with fdt.chosen_mut()?.unwrap().setprop_inplace(cstr!(\"kaslr-seed\"), &kaslr_seed.to_be_bytes()), i.e. it replaces the existing property in place with a big-endian value. libfdt errors propagate and main maps them to RebootReason::InternalError."
     ],
     "completeness": [
      "Covers the one place in the material where pvmfw builds the next-stage device tree: modify_for_next_stage, called once from main in pvmfw/src/main.rs. No other caller appears in the material.",
      "The write uses setprop_inplace, which replaces an existing property rather than creating one, so the fix relies on the template DT already containing a kaslr-seed placeholder. The template DT is not part of the diff.",
      "The write is unconditional (it does not depend on debuggable, strict_boot or debug_policy) and happens after debug-policy application, so that step cannot leave the placeholder in place.",
      "The quality of the seed depends on rand::random_array(), whose implementation is not shown in the material."
     ],
     "behavior_changes": [
      "Guest kernels now receive a randomly generated /chosen/kaslr-seed value from pvmfw instead of the constant placeholder.",
      "New failure path: if rand::random_array() fails, pvmfw logs an error and returns RebootReason::InternalError instead of starting the payload.",
      "New failure path: a libfdt error when writing kaslr-seed is mapped to RebootReason::InternalError ('Failed to configure device tree'). A missing /chosen node would hit the .unwrap() and panic."
     ],
     "preconditions": [
      "A protected VM is booted through pvmfw. pvmfw/src/main.rs:main runs on this path after DICE derivation and before 'Starting payload...'.",
      "The affected party is the guest kernel, which receives /chosen/kaslr-seed in the device tree that pvmfw hands over."
     ],
     "per_major": {
      "14": "same fix: commit 0cf463e9949d in android-security-14.0.0_r3. All 8 lines of the patched region are still present at android-security-14.0.0_r29.",
      "15": "not affected per the bulletin. At android-security-15.0.0_r17, 5/8 lines of the patched region are present.",
      "16": "not affected per the bulletin. pvmfw/src/fdt.rs and pvmfw/src/main.rs are absent at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin. The patched files are absent at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "A backport needs (a) a pvmfw rand module that provides rand::random_array() and (b) a template DT whose /chosen node already has an 8-byte kaslr-seed property, because setprop_inplace replaces an existing property and does not create or resize one (general platform knowledge of libfdt in-place setters). Verify both exist on the target branch.",
      "On branches where the patched region does not fully match or the files are absent, find the equivalent of modify_for_next_stage before applying the fix."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show the implementation or entropy source of rand::random_array().",
      "The template DT change (if any) that defines the kaslr-seed placeholder is not shown. The commit only patches fdt.rs and main.rs.",
      "Whether Android 15's partially matching region writes kaslr-seed in an equivalent way is not shown. The material only shows that the bulletin does not list 15.",
      "How severely the constant seed weakened guest KASLR is not described beyond the commit message."
     ],
     "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-2023-40083": {
     "cve": "CVE-2023-40083",
     "summary": "Adds a bounds check in parse_gap_data (system/main/shim/utils.cc). When a GAP data element's declared length is larger than the bytes left in the buffer, parsing now stops instead of copying past the end of raw_data.",
     "component": "platform/packages/modules/Bluetooth, system/main/shim (GD shim utilities, GAP/advertising data parsing)",
     "weakness": "Missing bounds check leading to out-of-bounds read (CWE-125 class)",
     "root_cause": "parse_gap_data walks raw_data as a sequence of length-prefixed GAP elements. It read the length byte at raw_data[offset], then built a copy from raw_data.begin() + offset to begin + len + 1. It never checked that offset + len + 1 fits within raw_data.size(). A malformed length value therefore made the vector copy (std::make_shared<std::vector<uint8_t>>(begin, end)) read past the end of the input buffer. The bulletin classifies this as information disclosure.",
     "fix_analysis": [
      "system/main/shim/utils.cc:parse_gap_data: right after uint8_t len = raw_data[offset] is read, the fix inserts `if (offset + len + 1 > raw_data.size()) break;`. The loop now ends before the iterator range is built and copied whenever the element would run past the end of the buffer.",
      "The check comes before the `auto begin`/`auto end` computation and before hci::GapData::Parse, so neither the copy nor the parse sees an over-long range. Elements already parsed stay in output. The truncated or malformed trailing element is dropped without notice.",
      "Single-commit fix: 4 lines added, no other files touched."
     ],
     "completeness": [
      "Within this function, the fix covers the copy range. The while condition keeps offset < raw_data.size(), so raw_data[offset] is safe, and the new check keeps the [begin, end) range in bounds. offset is size_t and len is uint8_t, so the addition cannot overflow.",
      "The fix only addresses parse_gap_data in system/main/shim/utils.cc. The material does not show whether other GAP/advertising-data parsers in the stack handle lengths the same way.",
      "A zero-length element (len == 0) still copies a 1-byte range (the length byte), passes it to hci::GapData::Parse and advances offset by 1. The fix does not change this."
     ],
     "behavior_changes": [
      "Parsing now stops at the first GAP element whose declared length exceeds the remaining input. That element and everything after it are left out of output. Before the fix, such input caused an out-of-bounds read.",
      "No error is reported to the caller. The function returns the elements parsed so far."
     ],
     "preconditions": [
      "parse_gap_data must be called with raw_data containing a length byte larger than the bytes left in the buffer. The material does not show which callers supply raw_data (per index search, no caller was found), so the entry point and whether the input is remote or local are unknown."
     ],
     "per_major": {
      "14": "same fix: commit 423c0285e5ee, applied in android-security-14.0.0_r3 (cherry-pick of 0d7e3d8fd963, Change-Id I7fcb7c46f668). All 5 lines of the patched region are present at android-security-14.0.0_r29.",
      "15": "not affected per the bulletin; the patched code is present (5/5 lines) at android-security-15.0.0_r17.",
      "16": "not affected per the bulletin; the patched code is present (5/5 lines) at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin; the patched code is present (5/5 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Self-contained 4-line addition inside parse_gap_data. It applies to any branch that has system/main/shim/utils.cc with the same loop. The bulletin lists Android 13 as affected, but no Android 13 commit is in the material."
     ],
     "confidence": "high",
     "unknowns": [
      "Which callers feed parse_gap_data, and whether the input comes from a remote peer (no caller found in the provided index results).",
      "The Android 13 fix commit and its state are not in the material.",
      "The commit references the test command atest net_test_main_shim, but the test content is not shown.",
      "How the patched code reached the 15, 16 and 17 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."
     }
    },
    "CVE-2023-40084": {
     "cve": "CVE-2023-40084",
     "summary": "Replaces the netdutils::threadLaunch-started monitor thread in netd's MDnsSdListener::Monitor with a stored std::thread. A new Monitor destructor interrupts this thread by closing one end of the control socketpair and then joins it, so Monitor::run can no longer run on a destroyed Monitor instance.",
     "component": "platform/system/netd, server/MDnsSdListener (mDNS service monitor thread)",
     "weakness": "Heap use-after-free caused by a thread lifetime bug: the worker thread running Monitor::run outlived the Monitor object",
     "root_cause": "MDnsSdListener::Monitor::Monitor() started the monitor thread with ::android::netdutils::threadLaunch(this) and kept no thread handle. The destructor was an empty `virtual ~Monitor() {}`. When a Monitor (embedded as MDnsSdListener::mMonitor) was destroyed, nothing stopped or waited for the thread running Monitor::run(), which uses members such as mPollFds, mPollRefs and mCtrlSocketPair. In the shown old code, the control socket revents were handled by a switch with only a POLLIN case, so there was no exit path on hangup. The commit message describes this as a heap-use-after-free in MDnsSdListener::Monitor::run, found with mdns_service_fuzzer after about 500 rounds.",
     "fix_analysis": [
      "server/MDnsSdListener.h: class Monitor gains a `std::thread* mRescanThread` member and `#include <thread>`. The empty `virtual ~Monitor() {}` is replaced by a declared, non-virtual `~Monitor()`.",
      "server/MDnsSdListener.cpp:MDnsSdListener::Monitor::Monitor(): the netdutils::threadLaunch(this) call is replaced by `mRescanThread = new std::thread(&Monitor::run, this)`. An ALOGE is logged if the thread is not joinable.",
      "server/MDnsSdListener.cpp:MDnsSdListener::Monitor::~Monitor() (new): closes mCtrlSocketPair[1]. Per the code comment, this interrupts poll in run() with revents 17 (POLLIN|POLLHUP). The destructor then calls mRescanThread->join() and deletes the thread object, so members stay valid until the thread has exited.",
      "server/MDnsSdListener.cpp:MDnsSdListener::Monitor::run(): the switch on mPollFds[0].revents is replaced by two ifs. If `revents & POLLHUP`, the thread frees mPollFds and mPollRefs, logs and returns. This is the new termination path. If `revents == POLLIN`, it reads one byte from mCtrlSocketPair[0] and calls rescan() for the RESCAN command, like the old `case POLLIN`."
     ],
     "completeness": [
      "The fix covers the Monitor object lifetime: destruction now waits for run() to return, which addresses the reported UAF in Monitor::run.",
      "Thread termination depends on the POLLHUP on mPollFds[0] that the destructor produces by closing mCtrlSocketPair[1].",
      "The new destructor does not close mCtrlSocketPair[0]. mPollFds/mPollRefs are freed by the exiting thread on the POLLHUP path.",
      "The joinable() check in the constructor only logs. std::thread construction either succeeds or throws (general platform knowledge).",
      "This commit does not change the lifetime of other objects used by run() (Context objects, DNSServiceRef entries, callbacks)."
     ],
     "behavior_changes": [
      "Monitor::~Monitor() now blocks until the monitor thread exits.",
      "The monitor thread now terminates when the control socket reports POLLHUP, and frees mPollFds/mPollRefs on exit.",
      "Monitor's destructor is no longer virtual.",
      "New log lines: ALOGE 'Unable to launch thread.' and VDBG logs 'Monitor recycling', 'Monitor thread leaving.' and 'Monitor recycled'."
     ],
     "preconditions": [
      "A MDnsSdListener::Monitor instance must be destroyed while its monitor thread is running. The commit message shows this was reached with mdns_service_fuzzer. When production netd destroys MDnsSdListener is not shown in the material.",
      "The mDNS native service in netd must be present. Per index search, packages/modules/Connectivity NsdService.java uses the netd MDnsManager only below SDK level V (comment: 'mdns native service provided by netd is removed' on V+)."
     ],
     "per_major": {
      "14": "same fix: commit 7dae058172ac in android-security-14.0.0_r3 (cherry-pick of 9c0c15f80cffb98b36284dd169a2e62e059dbbe3, Ignore-AOSP-First), recorded as resolved. At android-security-14.0.0_r29, 5/8 lines of the patched region are present.",
      "15": "not affected: not listed by the bulletin. The patched files server/MDnsSdListener.cpp and .h are absent at android-security-15.0.0_r17.",
      "16": "not affected: not listed by the bulletin. The patched files are absent at android-security-16.0.0_r8.",
      "17": "not affected: not listed by the bulletin. The patched files are absent at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Two-file change in system/netd with no new dependency beyond <thread>. For Android 11-13 (listed as affected), apply the same pattern: store the thread, add a destructor that closes mCtrlSocketPair[1] and joins the thread, and add the POLLHUP exit path in run(). Check the revents dispatch on the target branch, which the material does not show."
     ],
     "confidence": "high",
     "unknowns": [
      "Which production netd code path (outside the fuzzer) destroys MDnsSdListener/Monitor is not shown.",
      "How the unchanged parts of run() handle other control socket revents values (e.g. POLLERR/POLLNVAL) is not shown.",
      "The fix commits for Android 11, 12, 12L and 13 are not in the material.",
      "Why only 5/8 lines of the patched region are present at android-security-14.0.0_r29 is not shown."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 8,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40087": {
     "cve": "CVE-2023-40087",
     "summary": "Bounds the sample loops in transcodeQ15ToFloat, transcodeQ23ToFloat and transcodeQ31ToFloat (system/btif/src/btif_avrcp_audio_track.cc) by the destination buffer length (trackHolder->bufferLength) and replaces the off-by-one `<=` loop condition, which ran one iteration past length/sampleSize.",
     "component": "platform/packages/modules/Bluetooth, system/btif AVRCP audio track (btif_avrcp_audio_track.cc)",
     "weakness": "Missing bounds check / off-by-one heap out-of-bounds write (CWE-787 style)",
     "root_cause": "The three transcode helpers in system/btif/src/btif_avrcp_audio_track.cc looped with `for (; i <= length / sampleSize; i++)` and wrote `trackHolder->buffer[i]`. This had two problems. First, the `<=` condition ran one extra iteration: it wrote index length/sampleSize and read one sample beyond the length-derived range of the input `buffer`. Second, the loop bound depended only on the input `length` and never on `trackHolder->bufferLength`. A `length` larger than the destination float buffer could therefore cause an out-of-bounds write into `trackHolder->buffer`. Per index search, transcodeToPcmFloat selects these helpers by switching on trackHolder->bitsPerSample (16, 24 or 32). The unit test reaches them through BtifAvrcpAudioTrackWriteData.",
     "fix_analysis": [
      "system/btif/src/btif_avrcp_audio_track.cc:transcodeQ15ToFloat: the loop condition changed from `i <= length / sampleSize` to `i < std::min(trackHolder->bufferLength, length / sampleSize)`. This removes the extra iteration and caps the samples written at the destination buffer length.",
      "system/btif/src/btif_avrcp_audio_track.cc:transcodeQ23ToFloat: same loop bound change. The per-sample 24-bit extraction in the loop body is unchanged.",
      "system/btif/src/btif_avrcp_audio_track.cc:transcodeQ31ToFloat: same loop bound change.",
      "The return value `i * sampleSize` now reflects the clamped number of samples that were transcoded.",
      "system/btif/test/btif_avrcp_audio_track_test.cc:setMaxAudioTrackGain_minGain_bufferStreamDucked: the test now writes `bufferLength` bytes instead of `bufferLength - 1`, to match the new `<` semantics."
     ],
     "completeness": [
      "All three bit-depth paths (16, 24, 32) that transcodeToPcmFloat selects get the same bound. None keeps the old condition.",
      "The destination write `trackHolder->buffer[i]` is now bounded by both the input length and `trackHolder->bufferLength`.",
      "transcodeQ23ToFloat still reads `*((int32_t*)(buffer + offset - 1))`. When i == 0, this read starts one byte before `buffer`. The fix does not touch this expression (see potential_variants).",
      "The fix relies on `trackHolder->bufferLength` matching the actual allocation of `trackHolder->buffer`. The material does not show the allocation site.",
      "If `length` is not a multiple of sampleSize, the trailing partial sample is now skipped instead of producing an extra iteration."
     ],
     "behavior_changes": [
      "Writes larger than the audio track buffer are now truncated to `bufferLength` samples, and the return value reports the reduced byte count.",
      "Each call transcodes one fewer sample than the old `<=` loop did. The unit test was adjusted to match."
     ],
     "preconditions": [
      "An audio track created by BtifAvrcpAudioTrackCreate receives data through BtifAvrcpAudioTrackWriteData. Per index search, transcodeToPcmFloat dispatches to the helpers. The material does not show the call from BtifAvrcpAudioTrackWriteData directly; the unit test only suggests it.",
      "trackHolder->bitsPerSample is 16, 24 or 32, so one of the transcode helpers is selected.",
      "The `length` passed to the helper exceeds what trackHolder->buffer can hold, or reaches the off-by-one boundary. The material does not show where `length` comes from or who controls it."
     ],
     "per_major": {
      "14": "Same fix, in android-security-14.0.0_r3. It came through the automerger chain from a tm-dev change (Change-Id I0389f56ae210b4976821e0ceeb21a7a0c2965a62, cherry-picked from 3d7c7f4c2c51), and the commit is linked by subject only. At android-security-14.0.0_r29 the `std::min(trackHolder->bufferLength, length / sampleSize)` loops are present in all three helpers. The facts report 6/8 patched-region lines present.",
      "15": "Not affected per the bulletin. The fixed loop bounds are present at android-security-15.0.0_r17 (6/8 patched-region lines present).",
      "16": "Not affected per the bulletin. The fixed code is present at android-security-16.0.0_r8 (6/8 patched-region lines present).",
      "17": "Not affected per the bulletin. The fixed code is present at android-security-17.0.0_r1 (6/8 patched-region lines present)."
     },
     "backport_notes": [
      "Single self-contained commit. It needs BtifAvrcpAudioTrack to have a `bufferLength` member and std::min to be available. The same file already uses std::clamp.",
      "The commit subject is marked [conflict]. In a customized tree, check the three loop conditions directly instead of relying on the merge result."
     ],
     "confidence": "medium",
     "unknowns": [
      "Where `length` originates, i.e. which decoder or transport path feeds BtifAvrcpAudioTrackWriteData, and whether a remote peer can influence it.",
      "How BtifAvrcpAudioTrackCreate allocates `trackHolder->buffer` and sets `bufferLength`.",
      "Why the bulletin lists 14-next as affected while 15 is not listed.",
      "Which 2 of the 8 patched-region lines the per-major facts count as absent."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40089": {
     "cve": "CVE-2023-40089",
     "summary": "Makes DevicePolicyManager.getCredentialManagerPolicy() user-handle aware. The IDevicePolicyManager call now carries an explicit userId, the service looks up the profile/device owner for that user instead of the Binder caller's user, and cross-user queries require INTERACT_ACROSS_USERS.",
     "component": "platform/frameworks/base, DevicePolicyManager / DevicePolicyManagerService (credential manager policy)",
     "weakness": "Incorrect user-id resolution: the policy was looked up for the Binder caller's user rather than the user of the client Context.",
     "root_cause": "In DevicePolicyManagerService.java, getCredentialManagerPolicy() took no user argument and resolved the admin with getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), so it always used the user derived from the Binder calling identity. The client DevicePolicyManager.getCredentialManagerPolicy() did not pass the user of its Context (myUserId()). The policy returned therefore came from the calling user's profile/device owner, not from the user the DevicePolicyManager instance was bound to.",
     "fix_analysis": [
      "core/java/android/app/admin/IDevicePolicyManager.aidl: signature changed from `PackagePolicy getCredentialManagerPolicy()` to `PackagePolicy getCredentialManagerPolicy(int userId)`.",
      "core/java/android/app/admin/DevicePolicyManager.java:getCredentialManagerPolicy(): now calls mService.getCredentialManagerPolicy(myUserId()). It is annotated @UserHandleAware(enabledSinceTargetSdkVersion = UPSIDE_DOWN_CAKE, requiresPermissionIfNotCaller = INTERACT_ACROSS_USERS). throwIfParentInstance() is unchanged.",
      "services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java:getCredentialManagerPolicy(int userId): keeps the mHasFeature early return and the existing Preconditions.checkCallAuthorization(canWriteCredentialManagerPolicy(caller) || canQueryAdminPolicy(caller)). It adds `if (userId != caller.getUserId()) Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS))` and resolves the admin with getProfileOwnerOrDeviceOwnerLocked(userId) instead of caller.getUserId()."
     ],
     "completeness": [
      "Covers the single getter getCredentialManagerPolicy end to end (AIDL, client, service).",
      "setCredentialManagerPolicy(in PackagePolicy policy) is untouched and still has no userId parameter.",
      "The diff adds no check that userId refers to an existing user. getProfileOwnerOrDeviceOwnerLocked(userId) is consulted, and null is returned when no admin is found.",
      "The client code shown passes myUserId() with no target-SDK branch. How the @UserHandleAware enabledSinceTargetSdkVersion attribute is enforced is not shown."
     ],
     "behavior_changes": [
      "The IDevicePolicyManager.getCredentialManagerPolicy binder signature changed (it now takes int userId). Direct callers of the old transaction must be updated.",
      "When the requested userId differs from the Binder caller's user, the call now fails the authorization check unless the caller holds INTERACT_ACROSS_USERS.",
      "The returned PackagePolicy is now the one set by the profile/device owner of the Context's user rather than the Binder caller's user."
     ],
     "preconditions": [
      "mHasFeature is true; otherwise the method returns null.",
      "The caller passes canWriteCredentialManagerPolicy(caller) || canQueryAdminPolicy(caller).",
      "The behavior differs only when the DevicePolicyManager instance's user (myUserId()) differs from the Binder caller's user."
     ],
     "per_major": {
      "14": "Same fix: commit e2e05f488da6 in android-security-14.0.0_r3 (cherry-pick of 0951b28bd94a). At android-security-14.0.0_r29, 7/8 lines of the patched region are present, and the code context shows the userId-aware client, the @UserHandleAware annotation and the AIDL signature getCredentialManagerPolicy(int userId).",
      "15": "Not affected per the bulletin. 7/8 lines of the patched region are present at android-security-15.0.0_r17.",
      "16": "Not affected per the bulletin. 7/8 lines of the patched region are present at android-security-16.0.0_r8.",
      "17": "Not affected per the bulletin. 7/8 lines of the patched region are present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "All three files must move together: the AIDL signature change requires the DevicePolicyManager client and DevicePolicyManagerService to change in the same build. The referenced test is android.credentials.cts.CtsDevicePolicyTest."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which caller invoked getCredentialManagerPolicy on behalf of another user, and how the pre-fix behavior led to the EoP classification, is not shown in the material.",
      "Why the 8th line of the patched region is reported as not present at the latest tags is not shown.",
      "How the @UserHandleAware annotation attributes are enforced is not shown."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 8,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40090": {
     "cve": "CVE-2023-40090",
     "summary": "Replaces the plain memcmp used to compare the computed AES-CMAC with the received signature in BTM_BleVerifySignature with BoringSSL's CRYPTO_memcmp, which is hardened against timing side channels.",
     "component": "platform/packages/modules/Bluetooth, system/stack/btm (BLE security, LE data signature verification)",
     "weakness": "Non-constant-time comparison of a cryptographic MAC (observable timing discrepancy)",
     "root_cause": "In system/stack/btm/btm_ble.cc, BTM_BleVerifySignature computes an AES-CMAC over the signed data with the peer's CSRK (p_rec->ble.keys.pcsrk) via crypto_toolbox::aes_cmac into p_mac. It then compared p_mac with the received signature p_comp using the stock memcmp over BTM_CMAC_TLEN_SIZE bytes. The commit message says this stock memcmp allows signature contents to be deduced through a side-channel (timing) attack. The bulletin rates the issue High / EoP.",
     "fix_analysis": [
      "system/stack/btm/btm_ble.cc:BTM_BleVerifySignature: the comparison `memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0` becomes `CRYPTO_memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0`. Per the commit message, CRYPTO_memcmp is hardened against this timing attack.",
      "system/stack/btm/btm_ble.cc: adds `#include \"openssl/mem.h\"` to declare CRYPTO_memcmp.",
      "On success the existing logic is unchanged: btm_ble_increment_sign_ctr(bd_addr, false) is called and verified is set to true."
     ],
     "completeness": [
      "The fix covers exactly one MAC comparison, in BTM_BleVerifySignature. The MAC computation and the sign-counter handling around it are not changed.",
      "This commit changes no other comparison sites. The material does not show whether other secret comparisons in the Bluetooth stack use memcmp, so nothing can be concluded about them.",
      "The fix is a one-line semantic change plus an include. The diff adds no new validation, error path or test. The commit message names atest bluetooth_test_gd_unit as the test run."
     ],
     "behavior_changes": [
      "None functionally: CRYPTO_memcmp returns 0 on equality, so the existing `== 0` check keeps the same verification outcome. Only the timing of the comparison changes.",
      "btm_ble.cc now includes BoringSSL's openssl/mem.h."
     ],
     "preconditions": [
      "BTM_BleVerifySignature must be reached for a device whose security record holds a peer CSRK (p_rec->ble.keys.pcsrk), as used in the diff.",
      "The specific callers and the transport path are not shown in the material."
     ],
     "per_major": {
      "14": "same fix: commit fb76b30e0210 in android-security-14.0.0_r3 (cherry-pick of 7a960ac1c0cbc6d3949b6eaa7a86302a0b20c04f). At android-security-14.0.0_r29, 8/8 lines of the patched region are present.",
      "15": "not affected per the bulletin. At android-security-15.0.0_r17, 6/8 lines of the patched region are present. The material does not identify the two differing lines.",
      "16": "not affected per the bulletin. At android-security-16.0.0_r8, 6/8 lines of the patched region are present. The material does not identify the two differing lines.",
      "17": "not affected per the bulletin. At android-security-17.0.0_r1, 6/8 lines of the patched region are present. The material does not identify the two differing lines."
     },
     "backport_notes": [
      "Single self-contained commit: swap memcmp for CRYPTO_memcmp in BTM_BleVerifySignature and add #include \"openssl/mem.h\". The Bluetooth stack already links against BoringSSL (libcrypto), so no build-rule change should be needed, but check the target's dependencies if the include does not resolve (general platform knowledge).",
      "The bulletin also lists Android 13 as affected, but the Android 13 commit is not in this material."
     ],
     "confidence": "high",
     "unknowns": [
      "The callers of BTM_BleVerifySignature and the transport path to it (for example, which ATT/GATT operations) are not shown in the material.",
      "The material does not show which 2 of the 8 patched-region lines differ at the Android 15/16/17 tags, or whether CRYPTO_memcmp is present there. It shows only that the bulletin lists those versions as not affected.",
      "The Android 13 fix commit is not 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-2023-40091": {
     "cve": "CVE-2023-40091",
     "summary": "The SHELL_COMMAND_TRANSACTION handler in incidentd's IncidentService::onTransact now reads the in/out/err file descriptors with Parcel::readUniqueFileDescriptor (which dups them) and hands owned fds to fdopen via release(), instead of fdopen'ing fds still owned by the Parcel.",
     "component": "platform/frameworks/base, cmds/incidentd (IncidentService binder shell-command handling)",
     "weakness": "File descriptor ownership confusion (fdopen on a Parcel-owned fd that was not duplicated)",
     "root_cause": "In cmds/incidentd/src/IncidentService.cpp, IncidentService::onTransact handled SHELL_COMMAND_TRANSACTION by calling data.readFileDescriptor() three times and passing the returned fds directly to fdopen(). Per the commit message, readFileDescriptor does not provide ownership of the fds while fdopen needs ownership, so the fds should have been duped. The old code did not check whether the fd reads succeeded. It also declared a local `int err` fd that shadowed the outer `status_t err`, and later overwrote it with the result of command().",
     "fix_analysis": [
      "cmds/incidentd/src/IncidentService.cpp:IncidentService::onTransact (SHELL_COMMAND_TRANSACTION): replace the three data.readFileDescriptor() calls with unique_fd in, out, err and data.readUniqueFileDescriptor(&in/&out/&err). Per the commit message, readUniqueFileDescriptor dups the fds internally, so the handler owns its own descriptors.",
      "Each readUniqueFileDescriptor return status is checked. On any status != OK, the transaction returns that status immediately, before reading argc/args, the IShellCallback and the IResultReceiver.",
      "fdopen is now called with in.release(), out.release() and err.release(), which transfers ownership of the duped fds into the FILE* streams instead of using Parcel-owned fds.",
      "The result of command(fin, fout, ferr, args) is stored in a new status_t result and sent via resultReceiver->send(result). The `err` variable is no longer reused as both an fd and a status."
     ],
     "completeness": [
      "Covers all three fds (in, out, err) read in the SHELL_COMMAND_TRANSACTION case of IncidentService::onTransact; this is the only place the diff touches.",
      "The cleanup code after the diff (`if (fin != NULL) {` ...) is unchanged and only partially visible, so how the streams are closed is not shown.",
      "All three unique_fds are released before the fdopen NULL check. If an fdopen call fails, its released fd is no longer owned by a unique_fd, and the material does not show whether it is closed.",
      "Other incidentd entry points that may carry fds (for example AIDL-generated methods on IncidentService) are not shown and are not modified by this commit."
     ],
     "behavior_changes": [
      "When a file descriptor cannot be read from the parcel, onTransact now returns the Parcel status immediately, without reading the remaining arguments or calling the result receiver.",
      "incidentd now works on duplicated fds (one dup per stream) rather than on the Parcel's own fds.",
      "No change to the shell command logic or the argument parsing is visible in the diff."
     ],
     "preconditions": [
      "A binder client must be able to deliver a SHELL_COMMAND_TRANSACTION to the incidentd service binder (IncidentService::onTransact implements its own handling for this code, per the comment in the context). The material does not show whether any permission or caller-identity check gates this path.",
      "The transaction carries file descriptors. The index search returned only Java Binder.transact/onTransact and unrelated services, not a native caller of IncidentService::onTransact."
     ],
     "per_major": {
      "14": "same fix: commit 29e8df07d8c4 in android-security-14.0.0_r3 (cherry-pick of ba78ef276951, Change-Id Ibe03a17dee91ac5bf25d123d4fd9c0bdd3c7d80e). The code shown at android-security-14.0.0_r29 is in the fixed form (readUniqueFileDescriptor + release()); the per-major facts report a 5/8 patched-region match there.",
      "15": "not affected per the bulletin; at android-security-15.0.0_r17, 5/8 lines of the patched region are present (same ratio as the fixed Android 14 tag); code not shown.",
      "16": "not affected per the bulletin; at android-security-16.0.0_r8, 5/8 lines of the patched region are present (same ratio as the fixed Android 14 tag); code not shown.",
      "17": "not affected per the bulletin; at android-security-17.0.0_r1, 5/8 lines of the patched region are present (same ratio as the fixed Android 14 tag); code not shown."
     },
     "backport_notes": [
      "Single self-contained commit in cmds/incidentd/src/IncidentService.cpp. It needs Parcel::readUniqueFileDescriptor and android::base::unique_fd (general platform knowledge). The bulletin lists 11 to 13 as affected; when taking the hunk there, check that the local `err` (now unique_fd) and the new `result` variable fit the branch's code."
     ],
     "confidence": "medium",
     "unknowns": [
      "Whether any permission or UID check gates SHELL_COMMAND_TRANSACTION in IncidentService::onTransact (not shown).",
      "The full cleanup code after the diff (closing of fin/fout/ferr) is only partially visible, including handling of a released fd whose fdopen failed.",
      "The concrete consequence of the ownership bug in the old code.",
      "Which commits, if any, applied this fix to Android 11, 12, 12L and 13 (listed as affected).",
      "Why only 5/8 patched-region lines match in the 14 to 17 tags.",
      "The contents of bug reports 286931110 and 283699145 (the commit's Test lines reference incidentd_service_fuzzer)."
     ],
     "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-2023-40092": {
     "cve": "CVE-2023-40092",
     "summary": "Adds a check in ShortcutService.verifyShortcutInfoPackage that the user ID embedded in a caller-supplied ShortcutInfo equals the user ID of the Binder calling UID, throwing SecurityException otherwise.",
     "component": "platform/frameworks/base, services/core ShortcutService (ShortcutManager system service)",
     "weakness": "Missing validation / authorization check on a caller-controlled user ID (cross-user data boundary not enforced)",
     "root_cause": "verifyShortcutInfoPackage(String callerPackage, ShortcutInfo si) only verified that si.getPackage() equals the caller's package name. The caller-supplied ShortcutInfo also carries a user ID (si.getUserId()), which was never compared against the calling UID's user. verifyCaller() checks the userId argument of the API call against the caller, but the per-shortcut user ID inside each ShortcutInfo was unchecked, so shortcut objects tagged with another user's ID were not rejected by this function.",
     "fix_analysis": [
      "services/core/java/com/android/server/pm/ShortcutService.java:verifyShortcutInfoPackage: after the existing package-name mismatch check, obtains callingUid via injectBinderCallingUid() and throws SecurityException(\"User-ID in shortcut doesn't match the caller\") if UserHandle.getUserId(callingUid) != si.getUserId().",
      "Because verifyShortcutInfoPackages(String, List<ShortcutInfo>) loops over every element and calls verifyShortcutInfoPackage, the new check applies to every shortcut in a list passed through it."
     ],
     "completeness": [
      "Covers every path that goes through verifyShortcutInfoPackage / verifyShortcutInfoPackages; null ShortcutInfo entries still return early without checks (sanitizeShortcutSizes removes null entries, but its call order relative to the verification is not shown).",
      "verifyShortcutInfoPackage has no isCallerSystem() early return (unlike verifyCaller()), so the new user-ID check runs for any caller that reaches it; the material does not show whether system paths reach it or pass shortcuts for a different user.",
      "Only the user ID is validated; no other ShortcutInfo fields gain validation in this change. Paths that handle ShortcutInfo without calling verifyShortcutInfoPackage(s), if any, are not visible in the material."
     ],
     "behavior_changes": [
      "Calls whose ShortcutInfo passes through verifyShortcutInfoPackage(s) with a user ID different from the caller's user now fail with SecurityException(\"User-ID in shortcut doesn't match the caller\") instead of being accepted.",
      "verifyShortcutInfoPackage has no system-caller bypass, so if a system caller reaches it, the check applies to that caller as well."
     ],
     "preconditions": [
      "Caller reaches a ShortcutService API that passes caller-supplied ShortcutInfo objects through verifyShortcutInfoPackage or verifyShortcutInfoPackages (the specific IShortcutService entry points are not shown in the material).",
      "The ShortcutInfo package name must already equal the caller's package (pre-existing check); the shortcut's user ID is set to a user other than the caller's.",
      "A user ID other than the caller's is needed for the mismatch to matter (presumably a multi-user setup)."
     ],
     "per_major": {
      "14": "same fix: commit af8827252ba2 in android-security-14.0.0_r3 (cherry-pick, Change-Id Idbde676f871db83825155730e3714f3727e25762); 3/3 patched lines present at android-security-14.0.0_r29.",
      "15": "not affected per bulletin; the 3 patched lines are present at android-security-15.0.0_r17.",
      "16": "not affected per bulletin; the 3 patched lines are present at android-security-16.0.0_r8.",
      "17": "not affected per bulletin; the 3 patched lines are present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Single-commit, 4-line addition; it relies on injectBinderCallingUid() and ShortcutInfo.getUserId(), both used in the surrounding code. The bulletin lists 11, 12, 12L, 13 as affected, so the same hunk should apply where verifyShortcutInfoPackage exists in the same form; verify no system-initiated path on the target branch passes shortcuts for other users, since the check has no system exemption."
     ],
     "confidence": "high",
     "unknowns": [
      "Which IShortcutService entry points call verifyShortcutInfoPackage(s) and whether every ShortcutInfo-accepting path goes through them.",
      "Whether sanitizeShortcutSizes runs after verifyShortcutInfoPackages on the publish paths.",
      "What concrete information was disclosed by a cross-user shortcut (the bulletin only rates it High / ID).",
      "Whether any legitimate system caller relied on publishing shortcuts with a different user ID and is affected by the lack of a system exemption."
     ],
     "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-2023-40094": {
     "cve": "CVE-2023-40094",
     "summary": "Adds a CONTROL_KEYGUARD permission check to the IActivityTaskManager.keyguardGoingAway binder entry point in ActivityTaskManagerService so that callers without that permission can no longer signal that the keyguard is going away.",
     "component": "platform/frameworks/base, WindowManager / ActivityTaskManagerService (keyguard control)",
     "weakness": "Missing permission check on a system binder API",
     "root_cause": "ActivityTaskManagerService.keyguardGoingAway(int flags), the implementation of the binder method IActivityTaskManager.keyguardGoingAway, only called enforceNotIsolatedCaller(\"keyguardGoingAway\") before clearing the calling identity and continuing. No permission was required, so any non-isolated process with access to the ActivityTaskManager binder could call this keyguard-going-away notification, which per index search is normally sent by SystemUI's KeyguardViewMediator. The rest of the method body is not shown; per index search, KeyguardController.keyguardGoingAway (which marks the keyguard as going away and prepares the TRANSIT_KEYGUARD_GOING_AWAY transition) is the likely downstream path.",
     "fix_analysis": [
      "services/core/java/com/android/server/wm/ActivityTaskManagerService.java:keyguardGoingAway: adds mAmInternal.enforceCallingPermission(CONTROL_KEYGUARD, \"unlock keyguard\") as the first statement, before enforceNotIsolatedCaller and before Binder.clearCallingIdentity, so the check runs against the real caller's identity. A static import of android.Manifest.permission.CONTROL_KEYGUARD is added.",
      "core/java/android/app/IActivityTaskManager.aidl:keyguardGoingAway: adds @JavaPassthrough(annotation=\"@android.annotation.RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD)\"), which marks the permission requirement on the generated Java interface."
     ],
     "completeness": [
      "Covers the single binder entry point IActivityTaskManager.keyguardGoingAway, which is the only unguarded path shown in the material.",
      "The internal KeyguardController.keyguardGoingAway(displayId, flags) is not changed. Per index search it is package-private and called from DisplayContentTests; that ATMS calls it is not shown in the material.",
      "The neighbouring keyguard-related AIDL method setLockScreenShown in the same interface is not touched by this commit; its enforcement is not shown in the material."
     ],
     "behavior_changes": [
      "Callers of IActivityTaskManager.keyguardGoingAway without android.permission.CONTROL_KEYGUARD now receive a SecurityException instead of having the request processed (enforceCallingPermission throws SecurityException on denial) (general platform knowledge).",
      "The permission check now runs before the isolated-caller check, so an isolated process without the permission fails on the permission check first.",
      "Legitimate callers such as SystemUI KeyguardViewMediator (per index search) are unaffected provided they hold CONTROL_KEYGUARD."
     ],
     "preconditions": [
      "Caller is a non-isolated process able to obtain the IActivityTaskManager binder and invoke keyguardGoingAway(int flags); before the fix no permission was required.",
      "If the call reaches KeyguardController.keyguardGoingAway, that method only acts when the keyguard is showing and not already going away (per index search of that method)."
     ],
     "per_major": {
      "14": "same fix: commit fa30b150bba0 in android-security-14.0.0_r3 (Change-Id I7ba7e56f954c8e6f1f734311f735215918975bc6); 8/8 patched lines present at android-security-14.0.0_r29.",
      "15": "not affected per the bulletin; the patched region is present at android-security-15.0.0_r17 (8/8 lines).",
      "16": "not affected per the bulletin; patched region present at android-security-16.0.0_r8 (8/8 lines).",
      "17": "not affected per the bulletin; patched region present at android-security-17.0.0_r1 (8/8 lines)."
     },
     "backport_notes": [
      "The functional change is one line in ActivityTaskManagerService.keyguardGoingAway, using mAmInternal.enforceCallingPermission. On branches without that helper, mContext.enforceCallingPermission with the same permission and message is the equivalent (general platform knowledge). The AIDL @JavaPassthrough annotation is separate from the runtime check."
     ],
     "confidence": "high",
     "unknowns": [
      "The material does not show the concrete impact of an unprivileged keyguardGoingAway call beyond the bulletin's EoP/High rating.",
      "The body of ActivityTaskManagerService.keyguardGoingAway after clearCallingIdentity is not shown, so neither the exact downstream call nor any validation of flags is shown.",
      "Whether the backports to Android 11, 12, 12L and 13 (listed as affected) were applied identically is not shown; only the Android 14 commit is provided.",
      "Enforcement on the sibling AIDL method setLockScreenShown is not 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-2023-40095": {
     "cve": "CVE-2023-40095",
     "summary": "The fix makes PendingIntentUtils.createDontSendToRestrictedAppsBundle explicitly call setPendingIntentBackgroundActivityLaunchAllowed(false) on the BroadcastOptions it builds. PendingIntents that system_server sends with these options (the commit title names requestGeofence) can no longer be used to bypass background activity launch restrictions.",
     "component": "platform/frameworks/base, system_server PendingIntent sending options (services/core PendingIntentUtils; the commit title names the requestGeofence path)",
     "weakness": "Missing restriction: background activity launch (BAL) was not denied in the options system_server uses when it sends app-supplied PendingIntents (BAL restriction bypass)",
     "root_cause": "createDontSendToRestrictedAppsBundle in services/core/java/com/android/server/PendingIntentUtils.java built BroadcastOptions that only called setDontSendToRestrictedApps(true). It did not call setPendingIntentBackgroundActivityLaunchAllowed(false). According to the commit title, this allowed a bypass of background activity launch restrictions via requestGeofence.",
     "fix_analysis": [
      "services/core/java/com/android/server/PendingIntentUtils.java:createDontSendToRestrictedAppsBundle: one line is added, options.setPendingIntentBackgroundActivityLaunchAllowed(false), before the options are converted to a Bundle. The option therefore applies both in the bundle == null branch and in the branch that merges into an existing bundle via bundle.putAll(options.toBundle()).",
      "Every caller of this helper gets the option, so every send that uses this bundle now explicitly denies background activity launch."
     ],
     "completeness": [
      "Covers every send path that gets its options from createDontSendToRestrictedAppsBundle, including the case where an existing Bundle is merged.",
      "Does not cover system_server code that sends app-supplied PendingIntents without this helper; the material does not show such sites. Per index search, ConnectivityService.sendIntent (packages/modules/Connectivity) sets setPendingIntentBackgroundActivityLaunchAllowed(false) on its own when isAtLeastT() is true, without using this helper.",
      "The existing setDontSendToRestrictedApps(true) behavior is unchanged."
     ],
     "behavior_changes": [
      "PendingIntents sent with this bundle no longer get background activity launch allowed through the sender options.",
      "No API change; the change is limited to the options Bundle this helper builds."
     ],
     "preconditions": [
      "An app supplies a PendingIntent to a system service whose send path uses PendingIntentUtils.createDontSendToRestrictedAppsBundle; the commit title names requestGeofence."
     ],
     "per_major": {
      "14": "same fix: commit d1421cacf6bb in android-security-14.0.0_r3 (cherry-picked from 7f9be7c3c859, Change-Id Ia8094244f908b20d42711b6ea8f58f9b3345b563); at android-security-14.0.0_r29 all 5/5 lines of the patched region are present.",
      "15": "not affected per the bulletin; the patched region is present at android-security-15.0.0_r17 (5/5 lines).",
      "16": "not affected per the bulletin; the patched region is present at android-security-16.0.0_r8 (5/5 lines).",
      "17": "not affected per the bulletin; the patched region is present at android-security-17.0.0_r1 (5/5 lines)."
     },
     "backport_notes": [
      "A single one-line change with no other commits listed. It depends on BroadcastOptions.setPendingIntentBackgroundActivityLaunchAllowed being available in the target branch."
     ],
     "confidence": "medium",
     "unknowns": [
      "The material shows no call sites of createDontSendToRestrictedAppsBundle beyond the commit title's reference to requestGeofence, so the full set of affected system services is not visible.",
      "The exact trigger conditions (app state, how the launch is obtained) are not shown.",
      "How the fix was applied to Android 11, 12, 12L and 13 (listed as affected) is not in the material, nor whether setPendingIntentBackgroundActivityLaunchAllowed exists on those branches.",
      "The commit only records 'Test: manually'; it includes no regression test."
     ],
     "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-2023-40096": {
     "cve": "CVE-2023-40096",
     "summary": "AudioPolicyService::OpRecordAudioMonitor now registers its AppOps watcher with AppOpsManager::WATCH_FOREGROUND_CHANGES only for apps that target SDK U or later, after an interim revert that removed the flag for all apps. For those apps, foreground and background transitions are watched, so background recording can be silenced.",
     "component": "platform/frameworks/av, services/audiopolicy (AudioPolicyService, OpRecordAudioMonitor / AppOps record-audio monitoring)",
     "weakness": "Missing re-evaluation of a foreground-conditioned AppOp (improper access control): the op mode watcher was not registered for foreground-state changes.",
     "root_cause": "In services/audiopolicy/service/AudioPolicyService.cpp, OpRecordAudioMonitor::onFirstRef() calls checkOp() and then mAppOpsManager.startWatchingMode(mAppOp, packageName, mOpCallback). Without the AppOpsManager::WATCH_FOREGROUND_CHANGES flag, the watcher is not registered for foreground-state changes. A foreground-only record op is therefore not re-evaluated when the app goes to the background. An earlier commit, 7370c8442e66 (\"Listen for foreground AppOps changes\"), had passed the flag unconditionally. The two commits in the material first revert it, because it broke VOIP apps that record in the background, and then re-apply it based on the app's targetSdk.",
     "fix_analysis": [
      "Commit 3f5420f7eb60 (android-security-14.0.0_r2), AudioPolicyService.cpp:OpRecordAudioMonitor::onFirstRef: reverts 7370c8442e66 by removing the AppOpsManager::WATCH_FOREGROUND_CHANGES argument from mAppOpsManager.startWatchingMode(). Stated reason: top VOIP apps rely on recording in the background without capabilities.",
      "Commit dc0af854d4dd (android-security-14.0.0_r3), AudioPolicyService.cpp: adds two helpers in an anonymous namespace. getTargetSdkForPackageName() looks up 'package_native' via defaultServiceManager()->checkService, casts it to content::pm::IPackageManagerNative and calls getTargetSdkVersionForPackage(); it returns -1 on any failure. doesPackageTargetAtLeastU() returns targetSdk >= __ANDROID_API_U__. The commit also adds #include <android/content/pm/IPackageManagerNative.h>.",
      "Same commit, OpRecordAudioMonitor::onFirstRef: computes int flags = doesPackageTargetAtLeastU(mAttributionSource.packageName.value_or(\"\")) ? AppOpsManager::WATCH_FOREGROUND_CHANGES : 0 and passes flags to startWatchingMode(). Apps targeting U or later get the foreground-change watcher. Apps targeting older SDKs keep the prior behavior, per the commit message.",
      "At android-security-14.0.0_r29, the IPackageManagerNative.h include is at line 28 of AudioPolicyService.cpp. This is consistent with the second commit being on the release branch."
     ],
     "completeness": [
      "The change touches only the flags passed to startWatchingMode() in OpRecordAudioMonitor::onFirstRef(). Neither diff touches checkOp() or RecordAudioOpCallback.",
      "The restriction applies only to packages whose targetSdk is U or later. Packages targeting an older SDK are not watched for foreground changes and keep the pre-fix behavior by design.",
      "getTargetSdkForPackageName() fails open. If 'package_native' is unavailable, the interface cast fails, or getTargetSdkVersionForPackage() returns an error, targetSdk is -1 and the WATCH_FOREGROUND_CHANGES flag is not set.",
      "These commits do not address the existing TODO in onFirstRef ('We need to always watch AppOpsManager::OP_RECORD_AUDIO too since it controls the mic permission for legacy apps').",
      "The material does not include the original commit 7370c8442e66 or any fix applied to Android 11, 12, 12L and 13, which the bulletin lists as affected."
     ],
     "behavior_changes": [
      "For apps with targetSdk U or later, the record-audio AppOp watcher is registered with WATCH_FOREGROUND_CHANGES, so per the commit message their recording can be silenced in the background. Apps targeting older SDKs keep the previous behavior.",
      "onFirstRef() of OpRecordAudioMonitor now makes a binder call to the package_native service (getTargetSdkVersionForPackage) each time a monitor is created.",
      "Between the two commits (android-security-14.0.0_r2 only), the foreground watcher was removed for all apps."
     ],
     "preconditions": [
      "An app starts an audio capture through AudioPolicyService, which creates an OpRecordAudioMonitor. onFirstRef() runs when the first strong reference is taken (RefBase::incStrong / forceIncStrong call onFirstRef, per index search).",
      "The app then changes foreground state while capturing. With the final fix, the watcher only applies if the package's targetSdk is U or later and the package_native lookup succeeds."
     ],
     "per_major": {
      "14": "Fixed by two commits in frameworks/av: the revert 3f5420f7eb60 in android-security-14.0.0_r2 (removes WATCH_FOREGROUND_CHANGES), then dc0af854d4dd in android-security-14.0.0_r3 (re-adds it when targetSdk is U or later). At android-security-14.0.0_r29, the IPackageManagerNative.h include from the second commit is present. The resolver reports 1/4 lines of the patched region present, which may reflect the later rewrite of that call (inference).",
      "15": "Not affected (not listed by the bulletin). The resolver reports 1/4 lines of the patched region present at android-security-15.0.0_r17.",
      "16": "Not affected (not listed by the bulletin). The resolver reports 1/4 lines of the patched region present at android-security-16.0.0_r8.",
      "17": "Not affected (not listed by the bulletin). The resolver reports 1/4 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "Apply in order. The revert 3f5420f7eb60 assumes 7370c8442e66 (unconditional WATCH_FOREGROUND_CHANGES) is present, and dc0af854d4dd is based on the post-revert file (index df0c59f6fa). Alternatively, apply only the end state: pass flags computed from doesPackageTargetAtLeastU() to startWatchingMode().",
      "dc0af854d4dd requires content::pm::IPackageManagerNative::getTargetSdkVersionForPackage and the __ANDROID_API_U__ constant. Branches older than 14 may not have the constant (general platform knowledge)."
     ],
     "confidence": "medium",
     "unknowns": [
      "The material does not include the original commit 7370c8442e66 ('Listen for foreground AppOps changes') or show what else it changed.",
      "The material does not show how RecordAudioOpCallback and checkOp() react to the callback, which is where the silencing happens.",
      "The material does not show the fixes applied to Android 11, 12, 12L and 13, which the bulletin lists as affected.",
      "The material does not show what getTargetSdkVersionForPackage returns for an empty package name (the value_or(\"\") case).",
      "The material shows the state of OpRecordAudioMonitor::onFirstRef on the 15/16/17 security tags only as resolver line counts."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-40098": {
     "cve": "CVE-2023-40098",
     "summary": "SystemUI's conversation notification guts now only requests pinning a People Space (priority conversation) widget when the notification's user is in the same profile group as the system user, so marking a conversation as priority on a secondary user no longer triggers the widget pin request.",
     "component": "platform/frameworks/base, SystemUI notification guts (NotificationConversationInfo / NotificationGutsManager), People Space widget",
     "weakness": "Missing user/profile check before a cross-user UI action (bulletin type: ID)",
     "root_cause": "In NotificationConversationInfo.java the \"done\" click handler, when the selected action is ACTION_FAVORITE and the priority changed, unconditionally called mPeopleSpaceWidgetManager.requestPinAppWidget(mShortcutInfo, new Bundle()). It did not consider which user the StatusBarNotification belonged to, so a conversation from a secondary user could cause a People Space widget pin request for that conversation's shortcut. The bulletin classifies the result as information disclosure; the material does not detail what is exposed.",
     "fix_analysis": [
      "NotificationConversationInfo.java: adds a UserManager field (mUm) and a new 'UserManager um' parameter to bindNotification, stored as mUm.",
      "NotificationConversationInfo.java (done click listener): wraps the requestPinAppWidget call in 'if (mUm.isSameProfileGroup(UserHandle.USER_SYSTEM, mSbn.getNormalizedUserId()))'. The pin request now happens only when the notification's normalized user is in the system user's profile group; mShadeController.animateCollapseShade() and mGutsContainer.closeControls(v, true) still run unconditionally.",
      "NotificationGutsManager.java: injects UserManager via the constructor (new 'UserManager userManager' parameter, stored in mUserManager) and passes it to notificationInfoView.bindNotification(...) in the conversation-guts binding path.",
      "Tests: NotificationConversationInfoTest adds a UserManager mock to every bindNotification call, stubs isSameProfileGroup to true in testSelectPriorityRequestsPinPeopleTile, and adds testSelectPriorityRequestsPinPeopleTile_noMultiuser verifying requestPinAppWidget is never called when isSameProfileGroup returns false. NotificationGutsManagerTest passes a UserManager mock to the constructor."
     ],
     "completeness": [
      "Only the single requestPinAppWidget call site in NotificationConversationInfo's done handler is gated; the fix does not change PeopleSpaceWidgetManager.requestPinAppWidget itself or any other caller of it (none shown in the material).",
      "The check is relative to UserHandle.USER_SYSTEM, not the current foreground user: profiles of the system user still get the widget prompt, while all other users (and their profiles) are excluded.",
      "The rest of the done handler is unchanged (shade collapse and closeControls(v, save=true) still run); only the widget pin request is gated."
     ],
     "behavior_changes": [
      "Marking a conversation as priority from a notification belonging to a user outside the system user's profile group no longer shows the People Space widget pin prompt; the shade still collapses and the guts still close.",
      "Signatures changed: NotificationConversationInfo.bindNotification gains a UserManager parameter and NotificationGutsManager's constructor gains a UserManager parameter."
     ],
     "preconditions": [
      "Device with more than one user; a conversation notification posted for a user that is not the system user or one of its profiles is visible in the shade.",
      "The notification guts (NotificationConversationInfo) are opened for that conversation via NotificationGutsManager, the priority (ACTION_FAVORITE) option is selected and confirmed, and the conversation was not already priority (getPriority() != mSelectedAction).",
      "NotificationConversationInfo.bindNotification is invoked from NotificationGutsManager's conversation guts binding path (per diff); NotificationInfo.bindNotification found by index search is a different class and is not involved."
     ],
     "per_major": {
      "14": "same fix: commit 0c5db0349ae6 in android-security-14.0.0_r3 (cherry-pick of adf620316dcf); all 8 lines of the patched region present at android-security-14.0.0_r29.",
      "15": "not affected (not listed by the bulletin); patched region (8/8 lines) present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); patched region (8/8 lines) present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); patched region (8/8 lines) present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The fix changes two signatures (NotificationConversationInfo.bindNotification and the NotificationGutsManager constructor, a @SysUISingleton class per its imports); all callers and tests must be updated and a UserManager must be supplied to NotificationGutsManager.",
      "The bulletin lists 12, 12L and 13 as affected but no commits for those branches are in the material; a backport needs both the UserManager plumbing and the isSameProfileGroup guard around requestPinAppWidget in NotificationConversationInfo."
     ],
     "confidence": "high",
     "unknowns": [
      "What information the pinned widget exposed and to which user; the material only gives the bulletin type ID and the fix.",
      "Fix commits for Android 12, 12L and 13 (listed as affected) are not in the material.",
      "Whether other code paths request pinning People Space widgets for non-system users.",
      "How the USER_SYSTEM-relative check behaves on headless system user mode devices.",
      "Where the priority (ACTION_FAVORITE) channel change is persisted; the diff does not show it.",
      "Where UserManager is provided for Dagger injection into NotificationGutsManager on older branches."
     ],
     "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-2023-40103": {
     "cve": "CVE-2023-40103",
     "summary": "Two frameworks/base commits make AssetManager2 hold promoted (strong) ApkAssets references for the whole duration of a scoped \"operation\" instead of re-promoting weak pointers per access, and make the Java StringBlock/XmlBlock/AssetManager wrappers null out native pointers after destruction and reject calls on a gone native object.",
     "component": "platform/frameworks/base, libs/androidfw AssetManager2 and core/jni/android_util_AssetManager.cpp plus android.content.res Java wrappers (AssetManager, StringBlock, XmlBlock)",
     "weakness": "use-after-free / object lifetime race (Java commit: race calling into an already freed native object; native commit: weakly referenced ApkAssets promoted per access)",
     "root_cause": "On the Java side, StringBlock.mNative and XmlBlock.mNative were final and kept the freed native address after nativeDestroy(), XmlBlock did not close its StringBlock when its open count reached zero, and AssetManager.getAttributeResolutionStack() did not call ensureValidLocked(); per the commit message, a racing call could reach an already freed native object instead of getting a null. On the native side, AssetManager2 stored its ApkAssets only as weak pointers (std::vector<ApkAssetsWPtr> apk_assets_) and each method (FindEntry, GetStringPoolForCookie, OpenDir, OpenNonAsset, GetNonSystemOverlays, GetLastResourceResolution, Theme::SetTo, JNI NativeGetResourceStringArray, ...) promoted the weak pointer locally for each access, so no strong reference was held across a whole JNI call. The native commit itself is described as a performance change; its exact security contribution is not stated in the material.",
     "fix_analysis": [
      "Commit 58fa254a5d1a, libs/androidfw/include/androidfw/AssetManager2.h: apk_assets_ becomes mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> (weak pointer plus cached promoted strong pointer); adds struct ScopedOperation, [[nodiscard]] StartOperation() const, FinishOperation() const, counter number_of_running_scoped_operations_, and replaces the GetApkAssets() vector getter with GetApkAssets(ApkAssetsCookie) const returning const ApkAssetsPtr& plus GetApkAssetsCount().",
      "Commit 58fa254a5d1a, libs/androidfw/AssetManager2.cpp: StartOperation() increments the counter and returns a ScopedOperation whose destructor calls FinishOperation(); FinishOperation() clears all cached strong pointers only when the last nested operation ends. GetApkAssets(cookie) DCHECKs that an operation is running, returns a static empty pointer for cookie < 0 or >= size, and otherwise promotes once and caches the result in pair.second for the rest of the operation.",
      "Commit 58fa254a5d1a, libs/androidfw/AssetManager2.cpp: the internal users of apk_assets_[..].promote() shown in the diff are converted to StartOperation() + GetApkAssets(i): BuildDynamicRefTable (also pre-populates the strong pointer from the caller's list), DumpToLog, GetStringPoolForCookie, GetOverlayablesToString, ContainsAllocatedTable, GetNonSystemOverlays, GetResourceConfigurations, GetResourceLocales, OpenDir, both OpenNonAsset overloads, FindEntry, GetLastResourceResolution, and Theme::SetTo (which now starts operations on both source and destination managers and iterates with GetApkAssetsCount()/GetApkAssets()). ResetResourceResolution() is simplified to last_resolution_ = Resolution{}.",
      "Commit 58fa254a5d1a, core/jni/android_util_AssetManager.cpp: adds ScopedLockedAssetsOperation (holds the ScopedLock<AssetManager2> and an AssetManager2::ScopedOperation) and LockAndStartAssetManager(jlong); the Native* JNI entry points in the diff that previously took ScopedLock<AssetManager2> now use it, so the ApkAssets stay promoted for the whole JNI call, including entry points that run AttributeResolution (ApplyStyle, ResolveAttrs, RetrieveAttributes) and Theme operations under that lock. NativeGetResourceStringArray replaces GetApkAssets()[cookie].promote() with GetApkAssets(cookie).",
      "Commit 58fa254a5d1a, tools/aapt2/process/SymbolTable.cpp LookupAttributeInTable, libs/androidfw/tests/AssetManager2_test.cpp, libs/androidfw/tests/Idmap_test.cpp: adapted to the new API (GetApkAssetsCount(), StartOperation(), GetApkAssets(cookie)); a new GetApkAssets test verifies strong counts rise during an operation and drop back after it.",
      "Commit c3bc12c484ef, core/java/android/content/res/StringBlock.java: mNative is no longer final and is set to 0 after nativeDestroy() in close().",
      "Commit c3bc12c484ef, core/java/android/content/res/XmlBlock.java: decOpenCountLocked() now closes mStrings before nativeDestroy(mNative) and sets mNative = 0; mNative is no longer final. newParser() returns null when mNative == 0 (shown in code context).",
      "Commit c3bc12c484ef, core/java/android/content/res/AssetManager.java: ensureValidLocked() additionally throws RuntimeException when mObject == 0 even if mOpen is true; getAttributeResolutionStack() now calls ensureValidLocked() before nativeAttributeResolutionStack()."
     ],
     "completeness": [
      "The JNI entry points shown in the diff are converted to LockAndStartAssetManager, so those Java-initiated AssetManager2 operations hold strong references for their full duration; whether any lock site remains unconverted is not fully visible in the material.",
      "The listed internal AssetManager2 methods start their own operation; GetBag is not shown doing so, and aapt2 LookupAttributeInTable adds its own StartOperation() before calling it.",
      "GetApkAssets(cookie) includes a range check returning an empty pointer for out-of-range cookies.",
      "Strong references are released only when the outermost operation finishes; nothing in the diff changes how ApkAssets are released from Java (ApkAssets/ResourcesManager).",
      "Java side: only StringBlock and XmlBlock clear mNative; only getAttributeResolutionStack() gains an ensureValidLocked() call in AssetManager.java. Whether every other AssetManager native-call path already called ensureValidLocked() is not shown in the material.",
      "Theme native pointers (theme_ptr reinterpret_cast in the JNI functions) are validated only via the pre-existing CHECK(theme->GetAssetManager() == ...) and are not otherwise touched by these commits."
     ],
     "behavior_changes": [
      "AssetManager2 API change: GetApkAssets() returning the weak-pointer vector is removed; callers must use StartOperation() plus GetApkAssets(cookie) and GetApkAssetsCount(). GetApkAssets() DCHECKs an operation is running.",
      "ApkAssets strong references are held by the AssetManager2 for the duration of any operation and released at FinishOperation(); destruction of an ApkAssets may therefore be deferred until the current operation ends.",
      "Out-of-range cookies passed to GetApkAssets() yield an empty pointer.",
      "FinishOperation() logs a warning (ALOGW) if called with no running operation.",
      "AssetManager.ensureValidLocked() throws RuntimeException(\"AssetManager is open but the native object is gone\") when mObject == 0; getAttributeResolutionStack() can now throw this.",
      "XmlBlock now closes its StringBlock when its open count reaches zero; StringBlock and XmlBlock have mNative == 0 after close, so newParser() returns null on a closed XmlBlock.",
      "ResetResourceResolution() now resets the whole Resolution struct rather than a listed subset of fields."
     ],
     "preconditions": [
      "Code path: resource or asset access through android.content.res.AssetManager / Resources that reaches the Native* JNI functions in core/jni/android_util_AssetManager.cpp and AssetManager2 methods such as FindEntry, GetBag, OpenNonAsset, GetStringPoolForCookie, or Theme::SetTo.",
      "For the Java-side commit: a StringBlock, XmlBlock or AssetManager being closed/destroyed while another caller still invokes methods on it (race described in the commit message).",
      "The exact triggering sequence is not described in the material.",
      "Per index search, no callers outside frameworks/base were found for the patched JNI functions."
     ],
     "per_major": {
      "14": "same fix: both commits (58fa254a5d1a and c3bc12c484ef) are in android-security-14.0.0_r3 (Merged-In I26ef88df4f6267b5e8b89f1588f2382db74030c0 and I817dc2f5ef24e1fafeba3ce4c1c440abe70ad3ed); 8/8 lines of the patched region present at android-security-14.0.0_r29.",
      "15": "not affected per the bulletin; 8/8 lines of the patched region present at android-security-15.0.0_r17.",
      "16": "not affected per the bulletin; 8/8 lines of the patched region present at android-security-16.0.0_r8.",
      "17": "not affected per the bulletin; 8/8 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "58fa254a5d1a changes the AssetManager2 header API (GetApkAssets() vector getter removed, apk_assets_ type changed), so every caller of GetApkAssets()/apk_assets_ (aapt2 SymbolTable.cpp, Idmap_test.cpp, AssetManager2_test.cpp, any custom code) must be converted to StartOperation() + GetApkAssets(cookie)/GetApkAssetsCount(). The Java commit c3bc12c484ef touches separate files and shows no dependency on it."
     ],
     "confidence": "medium",
     "unknowns": [
      "The exact sequence that releases an ApkAssets or native object during an in-flight call is not shown in the material.",
      "How the native commit (described as a performance change) contributes to the security fix is not stated in the material.",
      "Whether the former direct apk_assets_[cookie] indexing sites lacked bounds checks is not visible from the diff hunks.",
      "Whether all ScopedLock<AssetManager2> sites in android_util_AssetManager.cpp were converted (e.g. NativeThemeRebase's second manager) is not fully visible.",
      "Whether other AssetManager.java native-call methods already called ensureValidLocked() is not visible in the material.",
      "The bulletin lists only Android 14 as affected; the material does not show why other versions are not listed."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 9,
      "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-2023-45773": {
     "cve": "CVE-2023-45773",
     "summary": "Adds MAX_SYNC_TRANSACTION sentinel checks before indexing the periodic-sync tables (p_sync[] and sync_transfer[]) in five functions of system/stack/btm/btm_ble_gap.cc, so a failed index lookup no longer leads to an out-of-bounds access.",
     "component": "platform/packages/modules/Bluetooth, BT stack BLE GAP periodic advertising sync (system/stack/btm/btm_ble_gap.cc)",
     "weakness": "Missing bounds check on an array index (a sentinel return value used directly as the index), leading to out-of-bounds access including writes",
     "root_cause": "The helpers btm_ble_get_psync_index(), btm_ble_get_free_psync_index() and btm_ble_get_free_sync_transfer_index() can return MAX_SYNC_TRANSACTION when no matching or free slot is found (the fix treats that value as the failure case). Several callers used the return value directly to index btm_ble_pa_sync_cb.p_sync[] or btm_ble_pa_sync_cb.sync_transfer[]. btm_ble_start_sync_request then wrote p->sync_state, and the sync_transfer paths wrote in_use, through the resulting pointer. btm_ble_start_sync_request and btm_ble_start_sync_timeout had no check at all. BTM_BlePeriodicSyncTransfer and BTM_BlePeriodicSyncSetInfo had no check after getting a free sync_transfer index. BTM_BleStartPeriodicSync already had the check, but formed the element pointer before it.",
     "fix_analysis": [
      "btm_ble_gap.cc:btm_ble_start_sync_request: after btm_ble_get_psync_index(sid, addr), if index == MAX_SYNC_TRANSACTION, log an error and return before computing &btm_ble_pa_sync_cb.p_sync[index] and setting p->sync_state. This also skips PeriodicScanStart and the sync timeout alarm.",
      "btm_ble_gap.cc:btm_ble_start_sync_timeout: same check after btm_ble_get_psync_index(adv_sid, address). On MAX_SYNC_TRANSACTION it logs and returns before p_sync[index] is used.",
      "btm_ble_gap.cc:BTM_BleStartPeriodicSync: moves the computation of p = &btm_ble_pa_sync_cb.p_sync[index] to after the existing index == MAX_SYNC_TRANSACTION check (which already ran syncCb with BTM_NO_RESOURCES and returned). Behavior is unchanged; the pointer is just no longer formed from the sentinel.",
      "btm_ble_gap.cc:BTM_BlePeriodicSyncTransfer: after btm_ble_get_free_sync_transfer_index(), if index == MAX_SYNC_TRANSACTION, log via BTM_TRACE_ERROR, run cb with BTM_ILLEGAL_VALUE and addr, and return before touching sync_transfer[index].",
      "btm_ble_gap.cc:BTM_BlePeriodicSyncSetInfo: the same check and BTM_ILLEGAL_VALUE callback before indexing sync_transfer[index]."
     ],
     "completeness": [
      "All five sites in the diff that index p_sync[] or sync_transfer[] with a value from the three lookup helpers now reject the MAX_SYNC_TRANSACTION sentinel before any dereference.",
      "The fix is defensive at the call sites only; the helpers still return MAX_SYNC_TRANSACTION as the not-found value. Any other caller of those helpers would need the same check. The material does not show other callers, so their status is not established.",
      "In btm_ble_start_sync_request, the early return skips PeriodicScanStart and the timeout alarm, and the diff adds no callback or cleanup for that case."
     ],
     "behavior_changes": [
      "BTM_BlePeriodicSyncTransfer and BTM_BlePeriodicSyncSetInfo now invoke the caller's callback with BTM_ILLEGAL_VALUE when no free sync_transfer slot is available, instead of proceeding.",
      "btm_ble_start_sync_request returns early with LOG_ERROR when no p_sync entry matches sid/addr. In that case the periodic scan is not started and the SYNC_TIMEOUT alarm is not armed.",
      "btm_ble_start_sync_timeout returns early with LOG_ERROR when the entry cannot be found, skipping the rest of the timeout handling.",
      "BTM_BleStartPeriodicSync: no observable change (the existing BTM_NO_RESOURCES path is kept; only the pointer computation is reordered)."
     ],
     "preconditions": [
      "Bluetooth enabled, with BLE periodic advertising sync in use (BTM_BleStartPeriodicSync, BTM_BlePeriodicSyncTransfer, BTM_BlePeriodicSyncSetInfo in btm_ble_gap.cc).",
      "The table lookup fails: no free p_sync or sync_transfer slot, or no p_sync entry matches the requested sid/address when btm_ble_start_sync_request or btm_ble_start_sync_timeout runs.",
      "The bulletin rates this as EoP, High. The material does not show the exact trigger path (local app or remote peer)."
     ],
     "per_major": {
      "14": "same fix: commit 397c1e928552 (Change-Id I4c8ec50c15e2727839a49da0e582164557bcd38a) in android-security-14.0.0_r3; all 8 patched lines present at android-security-14.0.0_r29.",
      "15": "not affected (not listed by the bulletin); the patched region is present (8/8 lines) at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); the patched region is present (8/8 lines) at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); 0/8 patched lines found at android-security-17.0.0_r1, so the code region appears to have been removed or restructured. The material does not show the replacement code."
     },
     "backport_notes": [
      "Single commit touching only system/stack/btm/btm_ble_gap.cc. It uses the existing MAX_SYNC_TRANSACTION constant, the index helpers and the BTM_ILLEGAL_VALUE status. Android 13 is listed as affected by the bulletin, but no 13 commit is shown in the material, so whether it applies cleanly there is not established."
     ],
     "confidence": "high",
     "unknowns": [
      "Whether other callers of btm_ble_get_psync_index / btm_ble_get_free_psync_index / btm_ble_get_free_sync_transfer_index exist that this diff does not cover.",
      "Who calls btm_ble_start_sync_request and btm_ble_start_sync_timeout (the index search returned no callers).",
      "The concrete trigger, and why the bulletin classifies it as EoP.",
      "How the Android 13 branch was patched (no 13 commit in the material).",
      "What replaced this code in Android 17, where the patched region is absent."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 6,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-45774": {
     "cve": "CVE-2023-45774",
     "summary": "ShortcutService now checks, while validating an incoming shortcut, that the calling UID can grant read access to the content URI behind a URI-based shortcut icon (Icon.TYPE_URI / TYPE_URI_ADAPTIVE_BITMAP), using UriGrantsManagerInternal.checkGrantUriPermission.",
     "component": "platform/frameworks/base, ShortcutService (services/core/java/com/android/server/pm/ShortcutService.java)",
     "weakness": "Missing permission check: a URI-based icon was accepted from the caller without verifying that the caller has access to that URI",
     "root_cause": "In ShortcutService.java, the incoming-shortcut validation method patched by the hunk (it comes before fixUpIncomingShortcutInfo(ShortcutInfo, boolean)) called only ShortcutInfo.validateIcon(shortcut.getIcon()) on the icon. For icons of type Icon.TYPE_URI or Icon.TYPE_URI_ADAPTIVE_BITMAP, nothing checked that the calling UID had read access to the referenced content URI. The bulletin rates this High / EoP.",
     "fix_analysis": [
      "services/core/java/com/android/server/pm/ShortcutService.java: in the validation method just before fixUpIncomingShortcutInfo(ShortcutInfo, boolean) (its name is not shown in the diff), a call to validateIconURI(shortcut) is added after ShortcutInfo.validateIcon(shortcut.getIcon()), inside the `if (shortcut.getIcon() != null)` block.",
      "New private method ShortcutService.validateIconURI(ShortcutInfo si): gets callingUid from injectBinderCallingUid(); returns early if the icon is null or is neither TYPE_URI nor TYPE_URI_ADAPTIVE_BITMAP; otherwise calls mUriGrantsManagerInternal.checkGrantUriPermission(callingUid, si.getPackage(), ContentProvider.getUriWithoutUserId(uri), Intent.FLAG_GRANT_READ_URI_PERMISSION, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(callingUid))). The user id embedded in the URI is used, defaulting to the caller's user. Only READ is checked.",
      "Adds import android.content.ContentProvider. The diff adds no field: mUriGrantsManagerInternal already exists in ShortcutService."
     ],
     "completeness": [
      "Covers both URI icon types (TYPE_URI and TYPE_URI_ADAPTIVE_BITMAP) for shortcuts that pass through the patched validation method. Which ShortcutService entry points reach that method is not shown.",
      "Validates only at ingestion time, against the binder calling UID. The material does not show where the stored URI is later resolved, or whether a check exists there.",
      "Only Intent.FLAG_GRANT_READ_URI_PERMISSION is checked."
     ],
     "behavior_changes": [
      "Publishing or updating a shortcut with a URI-based icon now goes through a UriGrantsManagerInternal.checkGrantUriPermission check for the calling UID. Shortcuts whose caller lacks access to the URI should be rejected. The exact failure seen by the caller is not shown.",
      "The check uses the user id embedded in the URI (defaulting to the caller's user) and the shortcut's package (si.getPackage()) as the target package."
     ],
     "preconditions": [
      "An app calls a ShortcutService path that reaches the patched validation method, with a ShortcutInfo whose Icon is of type TYPE_URI or TYPE_URI_ADAPTIVE_BITMAP.",
      "Before the fix, no check of the caller's access to the referenced content URI was made at this point."
     ],
     "per_major": {
      "14": "same fix: commit 1332ecd5e322 in android-security-14.0.0_r3 (cherry-pick, Change-Id I392f8e923923bf40827a2b6207c4eaa262694fbc); at android-security-14.0.0_r29 all 8/8 lines of the patched region are present.",
      "15": "not affected per the bulletin; the patched region is present (8/8 lines) at android-security-15.0.0_r17.",
      "16": "not affected per the bulletin; the patched region is present (8/8 lines) 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": [
      "Single self-contained commit. It depends on an existing mUriGrantsManagerInternal field and on injectBinderCallingUid() in ShortcutService. On the older branches listed as affected (11, 12, 12L, 13), check that these exist, and that ContentProvider.getUriWithoutUserId / getUserIdFromUri and Icon.TYPE_URI_ADAPTIVE_BITMAP are available."
     ],
     "confidence": "medium",
     "unknowns": [
      "Which component later loads the stored URI icon and what it exposes; the consumer side is not shown.",
      "The name of the enclosing method of the patched hunk, and which ShortcutService entry points (publish, update, pin request) reach it.",
      "Whether URI icons can enter by other routes (for example persisted state or manifest shortcuts) that bypass this validation.",
      "The exact failure mode a caller sees when the check fails.",
      "Status of the fix on Android 11, 12, 12L and 13 (listed as affected); no per-major facts are given for them."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 11,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-45775": {
     "cve": "CVE-2023-45775",
     "summary": "Adds length checks (size >= 2) on the StreamingAudioContext LTV value in LeAudioBroadcasterImpl::CreateAudioBroadcast before it is written with UINT16_TO_STREAM and read with STREAM_TO_UINT16, returning early on short values.",
     "component": "platform/packages/modules/Bluetooth, system/bta/le_audio/broadcaster (LE Audio broadcaster)",
     "weakness": "Missing bounds check leading to out-of-bounds write and out-of-bounds read on a parsed LTV value buffer",
     "root_cause": "In system/bta/le_audio/broadcaster/broadcaster.cc, LeAudioBroadcasterImpl::CreateAudioBroadcast parses the subgroup metadata with LeAudioLtvMap::Parse and looks up the kLeAudioMetadataTypeStreamingAudioContext entry with ltv.Find(). The code then took the raw pointer to the entry's value (stream_context_vec.value().data()) and always treated it as a 2-byte field without checking its length. UINT16_TO_STREAM wrote two bytes into it on the PTS multiple-contexts path, and STREAM_TO_UINT16 read two bytes from it on every call. A value shorter than 2 bytes made the write and the read go past the end of the vector's storage.",
     "fix_analysis": [
      "system/bta/le_audio/broadcaster/broadcaster.cc : LeAudioBroadcasterImpl::CreateAudioBroadcast, PTS path (inside get_pts_force_le_audio_multiple_contexts_metadata()): after ltv.Find(kLeAudioMetadataTypeStreamingAudioContext) succeeds, the fix adds 'if (stream_context_vec.value().size() < 2) { LOG_ERROR(...); return; }' before UINT16_TO_STREAM(pp, context_type.value()). This prevents the out-of-bounds write.",
      "Same file and function, unconditional path: the fix adds the same size < 2 check before STREAM_TO_UINT16(context_type.value_ref(), pp). This prevents the out-of-bounds read.",
      "Both checks return from the function, which stops the whole operation instead of skipping the entry. The commit makes no other change to validation or to the parser."
     ],
     "completeness": [
      "Covers both uses of the StreamingAudioContext value in the patched function: the write (UINT16_TO_STREAM) under the PTS flag and the read (STREAM_TO_UINT16) on the normal path.",
      "Does not change LeAudioLtvMap::Parse or ltv.Find. Other consumers of LTV values that assume a fixed length are therefore not covered by this commit, but the material does not show any.",
      "The android-security-14.0.0_r29 excerpt shows an equivalent size < 2 check in a broadcast_id-keyed path of the same class (it uses broadcasts_[broadcast_id]->GetCodecConfig()). The log text differs and the check comes after 'auto pp = ...data()'. The material does not show whether this is the same function after refactoring or a sibling path patched separately. Taking the pointer before the check is harmless because the pointer is not dereferenced until after the check."
     ],
     "behavior_changes": [
      "If a StreamingAudioContext LTV value in the subgroup metadata is shorter than 2 bytes, the function now logs 'kLeAudioMetadataTypeStreamingAudioContext size < 2' and returns early. Before the fix it went on to access memory out of bounds.",
      "The diff adds no new return code or callback. The caller only sees that the operation does not complete."
     ],
     "preconditions": [
      "LE Audio broadcaster in use, and a caller that can invoke LeAudioBroadcasterImpl::CreateAudioBroadcast with controlled subgroup metadata (the bulletin classifies this as EoP, severity High).",
      "The metadata must pass LeAudioLtvMap::Parse (is_metadata_valid true) and contain a kLeAudioMetadataTypeStreamingAudioContext entry whose value is 0 or 1 byte long.",
      "The out-of-bounds write path also requires stack_config_get_interface()->get_pts_force_le_audio_multiple_contexts_metadata() to be true. The out-of-bounds read path has no such requirement."
     ],
     "per_major": {
      "14": "same fix: commit 8e3b3fc918b3 in android-security-14.0.0_r3 (cherry-pick of internal 5f9059acdfed, Change-Id Ia8e9c3a3e534f419b6bd6c902a35d2caf4c7727b). At android-security-14.0.0_r29 the patched region is fully present (8/8 lines); in the shown excerpt the log text and the position of the check differ slightly.",
      "15": "not affected per the bulletin. android-security-15.0.0_r17 carries 5/8 lines of the patched region; the material does not show the exact form of the code.",
      "16": "not affected per the bulletin. android-security-16.0.0_r8 carries 6/8 lines of the patched region; the exact form is not shown.",
      "17": "not affected per the bulletin. android-security-17.0.0_r1 carries 6/8 lines of the patched region; the exact form is not shown."
     },
     "backport_notes": [
      "Single commit: add the two size checks right after each successful ltv.Find(kLeAudioMetadataTypeStreamingAudioContext) in CreateAudioBroadcast, before the UINT16_TO_STREAM / STREAM_TO_UINT16 macros. If the target tree also has a broadcast_id-keyed path with the same Find/STREAM pattern (as in the r29 excerpt), add the same check there. Bluetooth is a mainline module, so the fix may also arrive through a module update rather than the platform tag (general platform knowledge)."
     ],
     "confidence": "high",
     "unknowns": [
      "Which caller or IPC surface a party uses to reach CreateAudioBroadcast with controlled metadata is not shown in the material.",
      "Whether LeAudioLtvMap::Parse enforces any per-type value length is not shown.",
      "Whether the r29 excerpt (broadcast_id-keyed, broadcasts_[broadcast_id]) is CreateAudioBroadcast after refactoring or a sibling function fixed by another change is not shown.",
      "The precise state of the code in the Android 15/16/17 security tags is not shown beyond partial line-match counts."
     ],
     "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-2023-45776": {
     "cve": "CVE-2023-45776",
     "summary": "Adds length checks in LeAudioBroadcasterImpl (system/bta/le_audio/broadcaster/broadcaster.cc) so that the 2-byte StreamingAudioContext LTV value from caller-supplied broadcast subgroup metadata is only read or written when the value vector holds at least 2 bytes.",
     "component": "platform/packages/modules/Bluetooth, LE Audio broadcaster (system/bta/le_audio/broadcaster/broadcaster.cc, LeAudioBroadcasterImpl)",
     "weakness": "Missing bounds check (out-of-bounds read and out-of-bounds write on a std::vector data buffer)",
     "root_cause": "In LeAudioBroadcasterImpl (commit title: CreateAudioBroadcast), each subgroup metadata blob is parsed into an LeAudioLtvMap and the kLeAudioMetadataTypeStreamingAudioContext entry is looked up with ltv.Find. The code then took stream_context_vec.value().data() and, without checking the size, ran UINT16_TO_STREAM (a write, in the PTS multiple-contexts branch) and STREAM_TO_UINT16 (a read, in the general path). Both macros access 2 bytes. If the entry's value was 0 or 1 bytes long, the 2-byte access went beyond the vector's storage: an OOB write at the first site and an OOB read at the second. The fix implies that parsing did not enforce a minimum length for this type.",
     "fix_analysis": [
      "system/bta/le_audio/broadcaster/broadcaster.cc, LeAudioBroadcasterImpl (metadata preparation, PTS branch guarded by get_pts_force_le_audio_multiple_contexts_metadata()): before UINT16_TO_STREAM(pp, context_type.value()), checks stream_context_vec.value().size() < 2. If the check fails, it logs 'kLeAudioMetadataTypeStreamingAudioContext size < 2' and returns from the function.",
      "system/bta/le_audio/broadcaster/broadcaster.cc, LeAudioBroadcasterImpl (same loop, general path): before STREAM_TO_UINT16(context_type.value_ref(), pp), applies the same size() < 2 check with LOG_ERROR and return.",
      "Both checks sit inside the per-subgroup loop and use return, so a malformed entry in any subgroup ends the whole function. That subgroup is not simply skipped."
     ],
     "completeness": [
      "Covers both 2-byte accesses on the StreamingAudioContext LTV value in the patched function: the write (PTS branch) and the read (general path).",
      "The check matches the access size (2 bytes) exactly and is applied to the vector returned by ltv.Find, so it does not depend on parsing having validated lengths for each type.",
      "The code context at android-security-14.0.0_r29 (lines 271-330) is a function that works on an existing broadcast_id and has the same two access sites. It contains equivalent checks, but with a different log message ('stream_context_vec.value() size < 2') and with pp assigned before the check. The material does not show whether this is the same function after refactoring or a sibling path that was fixed separately.",
      "This commit does not touch other LTV types that may be read elsewhere in the broadcaster with fixed-size expectations. The material does not show whether any exist."
     ],
     "behavior_changes": [
      "New error path: if the StreamingAudioContext LTV value in any subgroup's metadata is shorter than 2 bytes, the function logs an error and returns early, so the broadcast is not created or configured.",
      "The diff adds no new callback or error code. It does not show whether the caller is told about the failure."
     ],
     "preconditions": [
      "The caller reaches the LE Audio broadcaster metadata path with subgroup metadata (LTV-encoded) that passes LeAudioLtvMap::Parse.",
      "The metadata contains a kLeAudioMetadataTypeStreamingAudioContext entry whose value is 0 or 1 bytes.",
      "The OOB write site also requires the stack config flag get_pts_force_le_audio_multiple_contexts_metadata() to be enabled. The OOB read site is reached whenever the entry is present."
     ],
     "per_major": {
      "14": "same fix: commit 8e3b3fc918b3 in android-security-14.0.0_r3 (cherry-pick of internal commit 5f9059acdfed, Change-Id Ia8e9c3a3e534f419b6bd6c902a35d2caf4c7727b). At android-security-14.0.0_r29 the patched region is fully present (8/8 lines).",
      "15": "not affected per the bulletin. At android-security-15.0.0_r17, 5 of the 8 patched-region lines are present. The material does not show whether the checks are present.",
      "16": "not affected per the bulletin. At android-security-16.0.0_r8, 6 of the 8 patched-region lines are present. The material does not show whether the checks are present.",
      "17": "not affected per the bulletin. At android-security-17.0.0_r1, 6 of the 8 patched-region lines are present. The material does not show whether the checks are present."
     },
     "backport_notes": [
      "Single commit: add a size() < 2 check right before each UINT16_TO_STREAM / STREAM_TO_UINT16 on the StreamingAudioContext value. If the target tree has been refactored, find every site that calls ltv.Find(kLeAudioMetadataTypeStreamingAudioContext) and dereferences .data() with a 2-byte macro.",
      "In the r29 context, pp is assigned before the check and the log string is different. Either order is safe because pp is only dereferenced after the check."
     ],
     "confidence": "high",
     "unknowns": [
      "The hunk headers do not give the name of the function that contains the hunks (the commit title says CreateAudioBroadcast). The r29 context shown may be a different function, since it looks up an existing broadcast_id.",
      "Whether LeAudioLtvMap::Parse checks value lengths per type in any version (the fix implies it did not for this type).",
      "Whether the caller is notified of the failure after the new early return.",
      "Which process boundary the attacker-controlled metadata crosses, and what device or feature conditions (e.g. LE Audio broadcast support) are needed. The bulletin only states EoP, High.",
      "Whether the checks are present at the latest security tags for 15, 16 and 17, given that only part of the patched region matches."
     ],
     "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-2023-45777": {
     "cve": "CVE-2023-45777",
     "summary": "In AccountManagerService.checkKeyIntentParceledCorrectly, replaces the deprecated untyped Bundle.getParcelable(KEY_INTENT) read of the authenticator-supplied bundle with the typed getParcelable(KEY_INTENT, Intent.class).",
     "component": "platform/frameworks/base, services/core AccountManagerService (validation of authenticator KEY_INTENT results)",
     "weakness": "Insufficient type validation when reading a Parcelable from an untrusted Bundle",
     "root_cause": "checkKeyIntentParceledCorrectly(Bundle bundle) writes the result bundle to a Parcel and reads it back. Its comment says this makes sure the Authenticator cannot trick users into launching arbitrary intents through Parcel read/write mismatches. Before the fix it read KEY_INTENT from the original bundle with the deprecated untyped bundle.getParcelable(AccountManager.KEY_INTENT), and enforced the type only afterwards with an intent.getClass() != Intent.class check. The exact flaw this allowed is not shown in the material.",
     "fix_analysis": [
      "services/core/java/com/android/server/accounts/AccountManagerService.java: checkKeyIntentParceledCorrectly: `Intent intent = bundle.getParcelable(AccountManager.KEY_INTENT);` becomes `bundle.getParcelable(AccountManager.KEY_INTENT, Intent.class)`, which requests an Intent-typed read.",
      "Commit e6a018a83696 changes only this one line (1 insertion, 1 deletion). The existing `intent != null && intent.getClass() != Intent.class` check right after it is unchanged."
     ],
     "completeness": [
      "The r3 commit changes only the read from the original `bundle`. The diff does not show the read from `simulateBundle`.",
      "At android-security-14.0.0_r29 the method reads both `bundle` and `simulateBundle` with getParcelable(..., Intent.class), has an explicit `if (intent == null) return (simulateIntent == null);` branch, and checks both objects' classes, followed by filterEquals, selector and prohibited-flag checks. These lines are not part of this commit, and the material does not say which commits added them."
     ],
     "behavior_changes": [
      "The KEY_INTENT value from the authenticator bundle is now read through the typed, Intent-class getParcelable API. The material does not show the resulting control flow when that value is not an Intent."
     ],
     "preconditions": [
      "An account authenticator supplies a result Bundle containing AccountManager.KEY_INTENT that AccountManagerService validates (per the method comment and log text). The call site of checkKeyIntentParceledCorrectly is not shown in the material."
     ],
     "per_major": {
      "14": "same fix: commit e6a018a83696 in android-security-14.0.0_r3. At android-security-14.0.0_r29 the method contains the typed read of `bundle` (and of `simulateBundle`); 2/4 lines of the original patched region are present.",
      "15": "not affected (not listed by the bulletin); 2/4 lines of the patched region present at android-security-15.0.0_r17.",
      "16": "not affected (not listed by the bulletin); 2/4 lines of the patched region present at android-security-16.0.0_r8.",
      "17": "not affected (not listed by the bulletin); 2/4 lines of the patched region present at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "The commit is a one-line change. Bundle.getParcelable(String, Class) exists from API 33 / Android 13 (general platform knowledge). The later r29 form of the method also changes the simulateBundle read and adds a null branch; compare against that form when backporting."
     ],
     "confidence": "medium",
     "unknowns": [
      "The material does not show the object type or Parcel layout that bypassed the untyped read, or the rest of the r3-era method body below the diff (for example, how a null `intent` was handled).",
      "The commits that later changed the simulateBundle read and added the null branch are not in the material.",
      "Why only 2/4 lines of the patched region match in the latest tags.",
      "Where checkKeyIntentParceledCorrectly is called from.",
      "The bulletin lists Android 13 as affected, but the material gives no Android 13 per-major fact."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 11,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    },
    "CVE-2023-45781": {
     "cve": "CVE-2023-45781",
     "summary": "Adds a bounds check in parse_gap_data (system/main/shim/utils.cc). If a GAP data element's length byte points past the end of raw_data, parsing now stops instead of copying out of bounds.",
     "component": "platform/packages/modules/Bluetooth, system/main/shim (GD shim utilities, GAP/advertising data parsing)",
     "weakness": "Missing bounds check (out-of-bounds read)",
     "root_cause": "parse_gap_data walks raw_data as a sequence of length-prefixed GAP elements. For each element it read len = raw_data[offset], built iterators begin = raw_data.begin() + offset and end = begin + len + 1, and copied [begin, end) into a new vector. The only check was the loop condition offset < raw_data.size(). The per-element length was never compared against the remaining bytes. So a len larger than the remaining buffer produced an end iterator past raw_data.end(), and the copy (std::vector range construction) read out of bounds.",
     "fix_analysis": [
      "system/main/shim/utils.cc:parse_gap_data: after reading len, the fix adds `if (offset + len + 1 > raw_data.size()) break;` before computing begin/end and copying. If the element (1 length byte plus len payload bytes) would run past the end of raw_data, the loop exits. The truncated element is not copied, not parsed by hci::GapData::Parse and not pushed to output.",
      "The arithmetic is done in size_t (offset is size_t; len is a uint8_t that gets promoted), so offset + len + 1 cannot wrap for realistic sizes."
     ],
     "completeness": [
      "The check covers the only copy in parse_gap_data. It comes before the iterator computation, so no out-of-range iterator is formed. Well-formed elements before the bad one are still returned.",
      "An element with len == 0 passes the check and yields a 1-byte copy. offset then advances by 1, so there is no infinite loop.",
      "The fix only validates the length, not the contents. hci::GapData::Parse is still called on the copied bytes, and its own handling of the data is not shown in the material.",
      "Only this one function changes. The material does not show other length-prefixed parsers in the shim, so whether sibling paths are covered cannot be judged from it."
     ],
     "behavior_changes": [
      "GAP data parsing now stops silently at the first element whose declared length overruns the buffer. That element and all bytes after it are dropped from output. No error is logged or returned."
     ],
     "preconditions": [
      "parse_gap_data must be called with a raw_data vector containing a GAP element whose length byte exceeds the remaining bytes. The material does not show any callers of parse_gap_data (none found per index search), so where raw_data comes from (for example remote advertising data or local input) is not shown."
     ],
     "per_major": {
      "14": "Same fix: commit 423c0285e5ee in android-security-14.0.0_r3 (cherry-pick of 0d7e3d8fd963, marked Ignore-AOSP-First). At android-security-14.0.0_r29 all 5 lines of the patched region are present.",
      "15": "Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-15.0.0_r17.",
      "16": "Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-16.0.0_r8.",
      "17": "Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-17.0.0_r1."
     },
     "backport_notes": [
      "A single self-contained 4-line hunk with no dependencies. It applies anywhere parse_gap_data exists with the same loop structure. The bulletin lists Android 13 as affected, but no Android 13 commit is in the material."
     ],
     "confidence": "high",
     "unknowns": [
      "Who calls parse_gap_data, and whether raw_data comes from remote peers (reachability and attack surface).",
      "The Android 13 fix commit (the bulletin lists 13 as affected, but the commit is not in the material).",
      "How hci::GapData::Parse behaves on short or malformed element contents.",
      "Whether the fix is also delivered through a Bluetooth module update (not shown in the material)."
     ],
     "meta": {
      "generated": "2026-10-04",
      "author_model": "claude-fable-5-1",
      "review_model": "claude-opus-5-5",
      "review_corrections": 1,
      "note": "AI-generated from the bulletin, the fixing diffs and their code context, then checked claim by claim by a second model. Statements marked '(general platform knowledge)' are not taken from the material."
     }
    }
   }
  },
  "15": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 18,
    "first_ingested_tag": "android-security-15.0.0_r1",
    "latest_ingested_tag": "android-security-15.0.0_r18",
    "window_base_tag": "android-15.0.0_r1",
    "window_start": "2024-09-03",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  },
  "16": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 9,
    "first_ingested_tag": "android-security-16.0.0_r1",
    "latest_ingested_tag": "android-security-16.0.0_r9",
    "window_base_tag": "android-16.0.0_r2",
    "window_start": "2025-06-10",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  },
  "17": {
   "counts": {
    "announced": 0,
    "certain": 0,
    "probable": 0,
    "not_published": 0,
    "not_covered": 0,
    "awaiting": 0
   },
   "advisories": [],
   "tags": [],
   "unannounced": [],
   "coverage": {
    "n_ingested_tags": 2,
    "first_ingested_tag": "android-security-17.0.0_r1",
    "latest_ingested_tag": "android-security-17.0.0_r2",
    "window_base_tag": "android-17.0.0_r1",
    "window_start": "2026-06-16",
    "partial_tags": []
   },
   "platform_update_tags": {},
   "briefs": {}
  }
 },
 "bulletin": {
  "url": "https://source.android.com/docs/security/bulletin/2023-12-01",
  "latest_version": "1.1",
  "latest_revision": {
   "version": "1.1",
   "date": "January 22, 2024",
   "notes": "Revised CVE Table"
  },
  "revisions": [
   {
    "version": "1.0",
    "date": "December 4, 2023",
    "notes": "Bulletin published"
   },
   {
    "version": "1.1",
    "date": "December 6, 2023",
    "notes": "Bulletin revised to include AOSP links"
   },
   {
    "version": "1.1",
    "date": "January 22, 2024",
    "notes": "Revised CVE Table"
   }
  ],
  "tracked_since": "2026-09-30",
  "changes_since_tracking": [],
  "out_of_scope_rows": {
   "Arm components": 3,
   "Imagination Technologies": 15,
   "MediaTek components": 5,
   "Qualcomm closed-source components": 21,
   "Qualcomm components": 8,
   "Unisoc components": 7
  },
  "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."
 }
}