//nefariousplan

CVE-2026-32202: The Trust Check Runs at the Click. The Coercion Runs at the Icon.

patterns

cve

proof of concept

In April 2026, Microsoft shipped a patch for CVE-2026-21510, the Windows Shell zero-day APT28 had been using to coerce NTLMv2 hashes out of victims who opened a folder containing a malicious .lnk. The patch added a class to shell32.dll named ControlPanelLinkSite that implements IVerifyingTrust::OnVerifyingTrust. The verifier asks SmartScreen whether to trust the link, and ShellExecuteExW honors the verdict.

CVE-2026-32202 is the same bug. The exploit does not call ShellExecuteExW.

The chain runs before the user clicks

Akamai's researchers reverse-engineered the structure in shell32.dll that drives the bug. It's an undocumented type called _IDCONTROLW, the in-memory shape of a Control Panel applet shell item, the third entry in the LinkTargetIDList that ships inside a .lnk when the link points at a CPL applet. Microsoft does not publish its layout. The PDB symbols don't include it. The Akamai team rebuilt it in IDA Pro, traced its validator _IsUnicodeCPLWorker, and confirmed the layout against the construction routine _IDControlCreateW.

The structure is a 24-byte header followed by a UTF-16LE string blob:

struct _IDCONTROLW {
    WORD  cb;           // +0x00  total size of structure
    WORD  pad1;         // +0x02  always 0
    DWORD dwAppletID;   // +0x04  signed applet ID, e.g. 0xFFFFFF37 (-201)
    WORD  pad2;         // +0x08  always 0  (validated by _IsUnicodeCPLWorker)
    WORD  pad3;         // +0x0A  always 0  (validated)
    BYTE  pad4;         // +0x0C  always 0  (validated)
    BYTE  typeFlag;     // +0x0D  = 0x6A    (Unicode CPL marker, validated)
    WORD  pad5;         // +0x0E
    DWORD pad6;         // +0x10
    WORD  cchModule;    // +0x14  WCHAR length of ModulePath
    WORD  offName;      // +0x16  WCHAR offset to Name in data[]
    WCHAR data[1];      // +0x18  ModulePath\0Name\0InfoTip
};

The validator at +0x0D checks for 0x6A, the marker that distinguishes the Unicode variant from its older ANSI cousin. The string blob starts at +0x18. The first string is the module path. The path is whatever the LNK author wrote.

When Explorer renders a folder containing a LNK whose LinkTargetIDList carries this shape as the third item, the call chain in shell32.dll is:

CControlPanelFolder::GetUIObjectOf      // icon extraction request
  └── CControlPanelFolder::GetModuleMapped
        └── PathFileExistsW(pszPath)    // SMB connection initiated here

pszPath is the module path from the _IDCONTROLW blob. If the path is \\attacker.example\share\anything.cpl, PathFileExistsW opens an SMB connection to attacker.example so it can ask whether the file exists. The Multiple UNC Provider routes the request to the SMB redirector; the SMB redirector negotiates a session before answering the existence question; the negotiation includes the workstation's NTLMv2 hash. The hash leaves the network before the user has decided whether to click anything.

The PoC that landed last week confirms the chain end-to-end. The third IDList item is built by hand: cb=0x9E, dwAppletID=-201 (the magic that registers a CPL slot), typeFlag=0x6A (the Unicode marker the validator demands), Unicode cchModule and offName, and a UTF-16LE UNC path at +0x18. The whole structure is 158 bytes. Wrap it in a 76-byte ShellLinkHeader with LinkFlags=0x00000041 (HasLinkTargetIDList | IsUnicode), drop the file in any folder a Windows user navigates to, and Explorer resolves the icon to the attacker's SMB server before the user has done anything but open the parent folder.

The patch is at the wrong gate

Microsoft's April patch did not touch GetUIObjectOf. It did not touch GetModuleMapped. It did not touch PathFileExistsW. The patch added ControlPanelLinkSite, registered it as the IVerifyingTrust site for Control Panel link execution, and wired the SmartScreen verdict into ShellExecuteExW.

IVerifyingTrust::OnVerifyingTrust is the COM interface SmartScreen consumes. It receives the link's effective execution context (the resolved target, the Mark of the Web on the host file, the Zone Identifier metadata) and returns an HRESULT the caller honors before invoking the underlying API. ShellExecuteExW is the API Windows calls when a user double-clicks a .lnk. The verifier is not wrong for that surface. SmartScreen vets execution; ControlPanelLinkSite ensures the vetting happens for Control Panel applet links the way it already happens for ordinary executables. As a fix for "the user clicks the LNK and Windows runs an attacker-controlled CPL," the patch is correct.

It is correct for the wrong API. The 2026-21510 bug class is not "the user clicks the LNK and Windows runs the CPL." The bug class is "Explorer touches the LNK during folder enumeration and Windows opens an SMB connection to wherever the LNK pointed." Click is one Shell entry point. Enumeration is a different one. Tooltip resolution is a third. Preview pane is a fourth. The patch landed at click. The other three ran unchanged.

PathFileExistsW is in the chain because, in shell32, file existence is not a security check. It's a substrate primitive: every Shell folder backend uses it to decide whether to load an icon or a fallback. The function has been call-trusted for as long as Windows has had a Shell namespace. Adding a trust verifier ahead of ShellExecuteExW does not change that. There is no code in the patched April binary that asks SmartScreen whether the icon-extraction call chain should be allowed to issue an SMB negotiation against a host the LNK author named.

The substrate is the design

This is the second iteration of the same primitive in the same file in the same quarter, against the same in-wild operator. CVE-2026-21510 was the original APT28 zero-day. The patch addressed one entry point. CVE-2026-32202 is the next entry point, found in days, exploited within weeks. CISA added it to KEV with a federal patch deadline of May 12, 2026. Microsoft has not yet shipped a corrected patch.

The Windows Shell has carried this class for years. CVE-2017-8464 was a LNK that triggered icon resolution against a UNC path and gave the attacker code execution; the fix added validation to one icon resolution code path. CVE-2024-43461 was Mark-of-the-Web bypass via LNK, also shipped with active in-wild exploitation. CVE-2026-21510 was CPL applet IDList plus UNC, fixed at execution. CVE-2026-32202 is the same bug, fixed at execution, exploited at enumeration.

This is design-debt-driver behavior. The substrate is not the trust verifier; the substrate is that the Windows Shell composes folder enumeration, icon extraction, tooltip generation, preview rendering, and execute through independent code paths that each touch attacker-influenced strings, and the trust pipeline guards exactly one of them. Each patch closes the entry point that produced the latest CVE. The next entry point is whichever Shell side effect a researcher or attacker traces next. Tooltip resolution calls back into the same applet metadata to render hover text. Preview pane has its own thumbnail providers that load resources from the link's targets. The current patch covers none of these.

The two repos

CVE-2026-21510 was used in the wild before Microsoft shipped the April patch, the disclosure-after-exploitation cadence: APT28 had the primitive, the vendor caught up, the vendor caught up incompletely. Akamai's research team published the reconstruction of the _IDCONTROLW structure and the observation that ControlPanelLinkSite only guarded ShellExecuteExW. Two PoC repositories naming CVE-2026-32202 appeared on GitHub the same week.

One of them is the artifact the previous section walks through: a Python LNK builder, two hundred lines of reverse engineering notes, citations to the Akamai writeup, and a working byte sequence that satisfies _IsUnicodeCPLWorker and reaches PathFileExistsW. The author shipped what they reconstructed.

The other repository contains a README that lists three Python files, smbcapture.py, coercegen.py, and coercestable.py, none of which exist in the repository. Under the heading Exploit there is one hyperlink, pointing at tinyurl.com. The README is sales copy: "Fast initial access in internal pentests / red team ops," "Actively used in engagements," "Custom SMB listener for hash capture (no Responder needed, cleaner logs)," "Ready for ntlmrelayx relay chains." The disclaimer is "authorized red teaming and penetration testing only."

A repository whose only deliverable is a URL shortener is not a research artifact. It is a delivery channel. We are not required to follow the redirect to recognize the convention.

What the patched administrator believed

A Windows administrator who applied the April 2026 cumulative update believed that the LNK-based NTLMv2 coercion vector was closed. The advisory said so. The KB article said so. The patch added a class whose name contains the words Verifying and Trust. Reasonable reading: trusted.

The administrator who applied the patch is not protected against the same operator using the same primitive against the same shell32 surface. They are protected against the click. The exploit does not click. They are protected against ShellExecuteExW. The exploit does not invoke ShellExecuteExW. They have an ordinary user opening an ordinary folder containing a LNK, and Explorer reaching out to the attacker's SMB server because file existence has never required a trust check and the patch did not make it one.

The KEV deadline is May 12, 2026. Federal agencies have ten days from the assignment to mitigate or remove the affected systems. There is no Microsoft patch to apply on that date. The available mitigations are the same ones operators have used since 2017 against this bug class: outbound SMB blocked at the firewall, NTLM authentication restricted to specific destinations, SMB client signing required, the Web Client service disabled. Each of those is a workaround. None of them is a fix. The fix would require the trust pipeline to extend beyond ShellExecuteExW to every Shell side effect that touches an attacker-supplied path, and that pipeline does not exist in the current shell32.

PoC: virus-or-not/CVE-2026-32202

The trust verifier guards ShellExecuteExW. The auth coercion never reaches ShellExecuteExW.