# CVE-2026-20844 — Windows Clipboard Server `clipboardserver.dll` Use-After-Free: EDP Policy Evaluated Without the Server Lock

---

## Summary

| | |
|---|---|
| **Product** | Windows — `clipboardserver.dll` (Clipboard Server; EDP/enterprise clipboard policy) |
| **CVE ID** | CVE-2026-20844 |
| **Impact** | Elevation of Privilege |
| **MSRC severity** | Important |
| **CVSS** | 7.4 / 6.4 — `CVSS:3.1/AV:L/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H/E:U/RL:O/RC:C` |
| **CWE** | CWE-416 Use After Free; CWE-362 Race Condition (improper synchronization) |
| **Delivery** | Local race — replace the clipboard data package during the unlocked policy evaluation window |
| **KB / Fixed build** | KB5074109 — `clipboardserver.dll` 10.0.26100.7623 (Win11 24H2 x64) |
| **Patch Date** | January 13, 2026 (2026-Jan) |
| **Pre-patch binary** | `clipboardserver.dll` 10.0.26100.7309 — SHA256 `2eb79a6b3542a8fcaec984faacb5f137b114179f89f9ae45a0b9355ef4c53879` |
| **Post-patch binary** | `clipboardserver.dll` 10.0.26100.7623 — SHA256 `73a6e152f6ce90fd19db87572514f57550837fe6e12397278339cb97ae70f5a2` |
| **Feature flag** | `Feature_3404159289` — **the fix is CFR-gated** |
| **Exploitability** | Exploitation Less Likely; not publicly disclosed; not exploited (per MSRC) |

---

## Product Description

`clipboardserver.dll` implements the Windows **Clipboard Server**, including the
enterprise data-protection (EDP) policy that decides whether clipboard content
may be read across enterprise/personal boundaries. The server holds an SRW lock
(at `this + 22`) that guards the current clipboard **data package** (at
`this + 25`). The server runs on behalf of clipboard clients, so a
synchronization flaw in its policy path is a local elevation / cross-boundary
disclosure vector.

---

## Vulnerability Summary

The **root cause is a race condition**: the clipboard server evaluated the
security policy of clipboard data **without holding the server lock**. In
`GetEnterpriseIdOfContent`, `EDPPolicyManager::GetEnterpriseIdFromDataPackage`
reads the data package (`this + 25`) to extract the EnterpriseID **unlocked**:

```c
// ClipboardServer::GetEnterpriseIdOfContent (10.0.26100.7309) — PRE-PATCH, from our diff
lVar1 = EDPPolicyManager::GetEnterpriseIdFromDataPackage(v4, *(this + 25), a2);  // *** no server lock held ***
```

Likewise `GetContentInternal` calls `UpdateEdpDataPackageLockState` (which runs
`EDPPolicyManager::EvaluateClipboardReadPolicy` against the previously computed
EnterpriseID and decides the data lock) **without** taking the lock. If an
attacker **replaces the clipboard data package at the right moment**, a TOCTOU
mismatch arises between when the policy is checked and when the data is actually
returned/released — the server can act on the wrong (already-freed or swapped)
package, giving access to data without permission or an invalid-pointer
access/use-after-free (CWE-416 / CWE-362).

---

## Prerequisites and Constraints

- Local, `PR:N` / `AV:L`; `AC:H` reflects the race timing.
- Race: replace the clipboard data package during the window in which the server
  evaluates EDP read policy without the lock.
- Winning the race lets the policy decision and the data access diverge → cross
  boundary disclosure or UAF.

---

## Vulnerability Details

### Root Cause

The EnterpriseID lookup and the EDP read-policy evaluation read the clipboard
data package (`this + 25`) outside the protection of the server SRW lock
(`this + 22`), so a concurrent replacement of the package makes the checked
policy and the used data inconsistent.

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

Gated behind `Feature_3404159289`, the policy path now **acquires the server SRW
shared lock before evaluating**. `GetEnterpriseIdOfContent` wraps the lookup in
`SRWLock::LockShared(this + 22)` and calls the new locked helper
`GetEnterpriseIdOfContentInternal`:

```c
// ClipboardServer::GetEnterpriseIdOfContent (10.0.26100.7623) — PATCHED, feature-enabled branch
if (FeatureImpl<Feature_3404159289>::__private_IsEnabled(...)) {
    Microsoft::WRL::Wrappers::SRWLock::LockShared(&lock, this + 22, ...);  // *** acquire shared lock ***
    lVar2 = GetEnterpriseIdOfContentInternal(this, a2);                    // locked EnterpriseID read
    ...
    ReleaseSRWLockShared(lock.Ptr);
}
else {
    lVar2 = EDPPolicyManager::GetEnterpriseIdFromDataPackage(v4, *(this + 25), a2);  // original unlocked path
}
```

`GetContentInternal` similarly adds `AcquireSRWLockShared(this + 22)` before
`GetContentDetails` / `UpdateEdpDataPackageLockState` (with a matching
`ReleaseSRWLockShared`), and `UpdateEdpDataPackageLockState` is gated so
`EvaluateClipboardReadPolicy` runs under the lock. Holding the shared lock across
the EnterpriseID computation and the read-policy evaluation makes the package
stable, so a concurrent replacement can no longer desynchronize the check from
the use.

### Patch Completeness Assessment

**CFR-gated behind `Feature_3404159289`.** The locked paths run only when the flag
is enabled; the original unlocked paths still ship in .7623. Patch state is not
determined by file version alone — the runtime-gated pattern seen across this
corpus. Verify `Feature_3404159289` is enabled to confirm the locking is live.

---

## Detection Guidance

**Behavioural.** Rapid clipboard data-package replacement concurrent with
enterprise clipboard reads (EDP policy checks); crashes or policy anomalies in
the Clipboard Server during cross-boundary paste.

**Crash signature.** UAF / invalid-pointer access in
`clipboardserver!ClipboardServer::GetContentInternal` /
`GetEnterpriseIdOfContent` / `UpdateEdpDataPackageLockState` on unpatched or
flag-disabled builds.

**Config.** The fix is CFR-gated — confirm `Feature_3404159289` is enabled so the
SRW-lock-before-policy paths are active.

---

## References

- MSRC advisory — CVE-2026-20844 (Windows Clipboard Server Elevation of Privilege), released 2026-01-13, KB5074109.
- Full binary diff: `/data/patch_diffs/clipboardserver_dll-cve-2026-20844-ghidriff.md`
