# CVE-2026-69605 — Microsoft Install Service `installservice.dll` Scan-Result View Use-After-Free (Local EoP to SYSTEM)

---

## Summary

| | |
|---|---|
| **Product** | Windows — `installservice.dll` (Microsoft Install Service, runs as SYSTEM) |
| **CVE ID** | CVE-2026-69605 |
| **Impact** | Elevation of Privilege (to SYSTEM) via a race condition |
| **MSRC severity** | Important |
| **CVSS** | 7.0 / 6.1 — `CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-416: Use After Free |
| **Delivery** | Local — an authorized caller invokes the Install Service scan methods |
| **KB / Fixed build** | KB5124008 — `installservice.dll` 10.0.26100.9444 (Win11 24H2/25H2 x64) |
| **Patch Date** | September 8, 2026 (2026-Sep) |
| **Pre-patch binary** | `installservice.dll` 10.0.26100.9278 — SHA256 `9ffe7d85355f54ba87028c86c0708e4d636bb97c1bb097f96ef131d5e3cf3299` |
| **Post-patch binary** | `installservice.dll` 10.0.26100.9444 — SHA256 `5172d5d3ac77c56b60899ae468b154c80b77972302c1fafff99470483223c8c2` |
| **Feature flag** | `Feature_1047758136` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation More Likely; not publicly disclosed; not exploited (per MSRC) |

> This build also carries unrelated **WIL feature-reporting churn**
> (`FeatureImpl<__WilFeatureTraits_Feature_1047758136>` state cache, `ReportUsageToService`); that is the
> gate's own infrastructure, not the fix. The security-relevant change is the scan-result view lifetime,
> below.

---

## Product Description

`installservice.dll` implements the **Microsoft Install Service** (Windows Update / Store install
orchestration), running as **SYSTEM**. Its WinRT `InstallServiceControl` methods `ScanForAllUpdates` and
`ScanForMultipleUpdates` return an `IVectorView<InstallItem>` of scan results to the caller.

---

## Vulnerability Summary

Pre-patch, the returned view was produced by wrapping the results in a WinRT `single_threaded_vector`
built over a local (`single_threaded_vector((vector<InstallItem>*)&local_130) → GetView(...)`) and then
**releasing that backing** (`com_ptr::unconditional_release_ref(&local_130)`). The returned
`IVectorView<InstallItem>`'s lifetime was therefore **not tied to its storage** — a caller that iterates
the returned collection while the backing is released/reused reads freed memory. Because the Install
Service runs as SYSTEM and the methods are reachable by an authorized (medium-privilege) caller, winning
the race gives a **use-after-free in a SYSTEM process** → elevation to SYSTEM. Microsoft rates it
**Important, 7.0**, `AC:H` (race), **Exploitation More Likely**.

---

## Prerequisites and Constraints

- Local, authorized (medium-privilege) access to invoke the Install Service scan methods (`AV:L`, `PR:L`,
  `UI:N`).
- A race must be won (`AC:H`): the returned view must be used while its backing store is released/reused.

---

## Vulnerability Details

### Root Cause

The scan methods handed back a collection **view** over a `single_threaded_vector` whose backing was
released independently of the view, so the returned `IVectorView` could dangle.

### The patch (confirmed — diff, .9278 → .9444)

Gated behind `Feature_1047758136`, `ScanForAllUpdates` / `ScanForMultipleUpdates` build the result through
a **new** `CreateReadOnlyInstallItemView<std::vector<InstallItem>>` (an owned read-only snapshot) instead
of a view over the released `single_threaded_vector`:

```c
// InstallServiceControl::ScanForAllUpdates (.9444) — PATCHED (Feature_1047758136 enabled)
bVar4 = wil::details::FeatureImpl<Feature_1047758136>::__private_IsEnabled(...);
if (bVar4) {
    InstallQueue2::CreateScanForAllUpdatesWork(this_01, local_110, ctx, args);
    CreateReadOnlyInstallItemView<std::vector<InstallItem>>(param_1);   // *** owned read-only view ***
    std::vector<InstallItem>::_Tidy((vector<InstallItem>*)local_110);
    ...
    return param_1;
}
// else (feature disabled) = ORIGINAL vulnerable path:
InstallQueue2::CreateScanForAllUpdatesWork(this_01, local_f8, ctx, args);
single_threaded_vector((vector<InstallItem>*)&local_130) -> GetView(...);   // view over local backing
com_ptr::unconditional_release_ref(&local_130);                            // ... which is then released
```

With the flag enabled, the returned collection owns its storage (`CreateReadOnlyInstallItemView`), so it
no longer dangles when the scan's working vector is tidied.

### Patch Completeness Assessment

**CFR-gated behind `Feature_1047758136`.** The owned-view path runs only when the flag is enabled; the
original `single_threaded_vector`/`GetView`/`unconditional_release_ref` path still ships when disabled.
Verify the flag is enabled to confirm the fix is live. The vulnerable functions, the gate, and the switch
to `CreateReadOnlyInstallItemView` are cleanly isolable in the diff; this RCA asserts the returned-view
lifetime bug and its fix rather than a single fully traced free.

---

## Detection Guidance

**Behavioural.** Crashes / heap-corruption in `installservice!...InstallServiceControl::ScanForAllUpdates`
or `ScanForMultipleUpdates` under concurrent update-scan activity; medium-privilege processes rapidly
invoking the Install Service scan methods and racing the returned collection.

**Config.** The fix is CFR-gated — confirm `Feature_1047758136` is enabled and the Sep-2026 update
(`installservice.dll` 10.0.26100.9444, KB5124008) is installed.

---

## References

- MSRC advisory — CVE-2026-69605 (Microsoft Install Service Elevation of Privilege), 2026-09-08, KB5124008.
- Full binary diff: `/data/patch_diffs/installservice_dll-cve-2026-69605-ghidriff.md`
