# CVE-2026-20931 — Windows Telephony Service `tapisrv.dll` Unvalidated Mailslot Handle in `ClientAttach` (External Path Control)

---

## Summary

| | |
|---|---|
| **Product** | Windows — `tapisrv.dll` (Telephony Service; remote service-provider attach) |
| **CVE ID** | CVE-2026-20931 |
| **Impact** | Elevation of Privilege |
| **MSRC severity** | Important |
| **CVSS** | 8.0 / 7.0 — `CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-73: External Control of File Name or Path |
| **Delivery** | Adjacent network (`AV:A`) — a client-supplied path in a Telephony service-provider attach request |
| **KB / Fixed build** | KB5074109 — `tapisrv.dll` 10.0.26100.7623 (Win11 24H2 x64) |
| **Patch Date** | January 13, 2026 (2026-Jan) |
| **Pre-patch binary** | `tapisrv.dll` 10.0.26100.7309 — SHA256 `aaffa1c72e0d4e65046bb74de7f6dee0b486841255907eb64d0abf40d8a83a1b` |
| **Post-patch binary** | `tapisrv.dll` 10.0.26100.7623 — SHA256 `3eda9356b2b1dbc9af6b3ea719536e05ba4011f82bbc12aff0cbb0a37b0efeb2` |
| **Feature flag** | `Feature_2464883000` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation Less Likely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`tapisrv.dll` is the Windows **Telephony Service**. Its `ClientAttach` handler
services remote service-provider connection requests. As part of attaching, it
opens a **mailslot** the client names, and then uses that handle assuming it is a
mailslot for subsequent messaging.

---

## Vulnerability Summary

`ClientAttach` opened the client-supplied path with `CreateFileW` and then used
the resulting handle as if it were a mailslot — **without verifying that it
actually is one**:

```c
// ClientAttach (10.0.26100.7309) — PRE-PATCH, from our diff
FileW = CreateFileW(lpFileName, 0x40000000, 1, 0, 3, 0x80, 0);   // path chosen by the client
*((_QWORD *)v19 + 16) = FileW;
if (FileW != (HANDLE)-1)                                          // *** success == "connected"; no type check ***
    goto LABEL_149;                                              // proceed to use the handle
```

Because the handle type is never checked, a client can supply a path to **any
kernel object `CreateFileW` will open** — a file, a named pipe, a device — not
just a mailslot. As long as `CreateFileW` succeeds the attach is treated as
established, and the service then performs operations on that handle **with
service (SYSTEM) privileges** — e.g. opening/writing an attacker-chosen file or
device — an external-path-control elevation (CWE-73).

---

## Prerequisites and Constraints

- Adjacent network (`AV:A`), low privilege (`PR:L`, `AC:L`): the attacker sends a
  Telephony service-provider attach request with an attacker-chosen `lpFileName`.
- The path can name a non-mailslot object (file/pipe/device); `CreateFileW`
  succeeding is sufficient to proceed pre-patch.
- Result: the SYSTEM service acts on the attacker-chosen object → EoP.

---

## Vulnerability Details

### Root Cause

`ClientAttach` conflated "`CreateFileW` succeeded" with "the handle is a
mailslot". The client controls the path, so the handle can reference an arbitrary
object that the privileged service then operates on.

### The patch (confirmed — diff, .7309 → .7623)

Gated behind `Feature_2464883000`, `ClientAttach` calls **`GetMailslotInfo`**
immediately after `CreateFileW` and only proceeds if it succeeds — i.e. the handle
is genuinely a mailslot. Otherwise it **closes the handle and rejects** the
attach:

```c
// ClientAttach (10.0.26100.7623) — PATCHED, feature-enabled branch
FileW = CreateFileW(lpFileName, 0x40000000, 1, 0, 3, 0x80, 0);
if (FileW != (HANDLE)-1
    && GetMailslotInfo(FileW, &cbDest, &NextSize, &MessageCount, &IsMember))   // *** must be a real mailslot ***
    goto LABEL_153;                                    // accept
...
CloseHandle(handle);                                   // not a mailslot -> close + reject
// log: "ClientAttach: GetMailslotInfo(%ws) failed, err=%u"
```

`GetMailslotInfo` fails for any handle that is not a mailslot, so files, pipes and
devices disguised as mailslots are rejected — closing the external-path-control
vector.

### Patch Completeness Assessment

**CFR-gated behind `Feature_2464883000`.** The `GetMailslotInfo` validation runs
only when the flag is enabled; the original unchecked path still ships in .7623.
Patch state is not determined by file version alone. Verify `Feature_2464883000`
is enabled to confirm the validation is live.

---

## Detection Guidance

**Behavioural.** Telephony service-provider attach requests naming non-mailslot
paths; the Telephony Service (`tapisrv`, SYSTEM) opening files/pipes/devices from
a client-supplied `lpFileName`.

**Trace.** With the fix active, rejected attaches log
`ClientAttach: GetMailslotInfo(%ws) failed, err=%u`.

**Config.** The fix is CFR-gated — confirm `Feature_2464883000` is enabled so the
mailslot validation runs.

---

## References

- MSRC advisory — CVE-2026-20931 (Windows Telephony Service Elevation of Privilege), released 2026-01-13, KB5074109.
- Full binary diff: `/data/patch_diffs/tapisrv_dll-cve-2026-20931-ghidriff.md`
- Related Telephony bugs: CVE-2026-42968 (tapisrv.dll event-mask OOB read), CVE-2024-43518 (tapi32.dll GrowBuf).
