# The Twenty-Year Local Admin Password Crisis: From GPP cpassword to Windows LAPS

> Microsoft published the AES key that "protected" Group Policy Preferences passwords. Twelve years later, MS14-025 still has not deleted the artefacts. Here is how Windows LAPS finally fixed the architecture -- and what it still cannot solve.

*Published: 2026-06-03*
*Canonical: https://paragmali.com/blog/the-twenty-year-local-admin-password-crisis-from-gpp-cpasswo*
*License: CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/*

---
<TLDR>
**Eleven years separated Microsoft's December 2012 architectural articulation of the shared-local-admin problem from the April 11, 2023 in-box default.** Group Policy Preferences "encrypted" the local Administrator password with an AES key Microsoft published in its own protocol specification (2008-2014). MS14-025 disabled new authoring but deleted no SYSVOL artefacts (2014). Legacy LAPS shipped as a separate MSI with plaintext in `ms-Mcs-AdmPwd` (2015-2023). In-box Windows LAPS finally added CNG DPAPI encryption-at-rest, Microsoft Entra ID backup, and post-authentication rotation. The 2026 default is `BackupDirectory = 2` (AD) or `1` (Entra), `PasswordAgeDays` \<= 30, `ADPasswordEncryptionEnabled` left at its default `True` (the failure mode is silent fallback to plaintext when the domain functional level is below Windows Server 2016, not an off-by-default bit), `ADPasswordEncryptionPrincipal` overridden to a dedicated decryptor group, and `PostAuthenticationActions` left at default `3` (reset + sign out). The residual attack surface is delegated-decryptor compromise, the screenshotted-password OPSEC tail, unmanaged BYOD endpoints, and the multi-decade tail of un-cleaned SYSVOL `cpassword` XMLs that MS14-025 never deleted.
</TLDR>

## 1. One Password, Fifty Thousand Laptops

In May 2012, a domain user with twelve lines of PowerShell could read the local Administrator password for every machine in the organisation. The tool was `Get-GPPPassword.ps1` [@obscuresec-gpp-2012]. The "encryption" was AES-256-CBC with a 32-byte key Microsoft had published in its own protocol specification [@ms-gppref-aes-key] -- not leaked, *published*, as a feature, so that third-party Group Policy implementations could read the format. Eleven years later, on April 11, 2023, Microsoft finally shipped the in-box fix [@tc-windows-laps-ga-2023].

This is an article about those eleven years.

<Definition term="Pass-the-Hash">
A lateral-movement technique in which an attacker uses the NTLM hash of a captured password directly in an authentication exchange, without recovering the cleartext. If the same local Administrator password is reused across a fleet, one dumped hash unlocks every machine. MITRE catalogues the technique as **T1550.002**.
</Definition>

The pattern was old before 2012. Through the 2000s, the only practical way to provision the local Administrator account on a Windows fleet was to bake one shared password into the reference image and ship the image to every endpoint. Helpdesk knew the password. Pentesters guessed at it. And once Benjamin Delpy's Mimikatz had pulled the hash from a single phished workstation in 2011, the rest of the org fell to a single `psexec` spray. Microsoft documented the threat model precisely in its December 2012 *Mitigating Pass-the-Hash* whitepaper [@ms-pth-whitepaper], which named the shared local Administrator credential as the architectural enabler of the entire intrusion class [@mitre-t1550-002].

Microsoft also had a *fix*. It had shipped one in 2008 with Group Policy Preferences (GPP), the feature that could push a per-machine local-admin password from a Group Policy Object to every endpoint. GPP put the password in an XML file in SYSVOL. SYSVOL was world-readable to every authenticated user in the domain. Microsoft encrypted the password with AES-256-CBC -- and then published the key. The result, after a four-author weaponisation chain in mid-2012 [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp], was that GPP made the original problem *worse*: instead of one shared password recoverable by physical access to a help-desk laptop, it was now one shared password recoverable by any authenticated domain user with a copy of `Get-GPPPassword.ps1`. Microsoft "patched" it on May 13, 2014 with MS14-025 [@ms14-025-bulletin], which disabled new authoring but deleted nothing already deployed. Twelve years later, PingCastle still finds the artefacts in production AD [@pingcastle-rules].

The first real fix was Generation 2: the legacy Microsoft LAPS, shipped May 1, 2015 as a separate MSI [@ms-advisory-3062591-wayback]. It stored a per-machine random password in the `ms-Mcs-AdmPwd` attribute on the computer object, marked CONFIDENTIAL [@adsec-laps-2016]. The directory-side ACL was tighter than SYSVOL, but the deployment surface (install on every endpoint, extend the schema, delegate the OU) capped its real coverage; the password sat in plaintext in AD, one DCSync from "plaintext everywhere"; and a delegation pattern that helpdesks regularly issued -- "All Extended Rights" on the computer OU -- silently included read access to the CONFIDENTIAL attribute [@adsec-laps-2016]. SpecterOps modelled that bypass as the `ReadLAPSPassword` BloodHound edge on August 7, 2018 [@specterops-bh2].

Generation 3 -- Windows LAPS, in-box, no MSI -- shipped on Patch Tuesday April 11, 2023 [@tc-windows-laps-ga-2023] across Windows 11 22H2 and 21H2, Windows 10 22H2, Windows Server 2022, Windows Server 2019, and Windows Server Annual Channel. Windows Server 2016 was explicitly excluded [@ms-laps-overview]. The new architecture wrapped the password with CNG DPAPI's group key-protector against a configurable principal, exposed Microsoft Entra ID as a peer backup directory [@tc-entra-laps-ga-2023], and added a post-authentication rotation primitive that closed the screenshotted-password OPSEC tail on the *next* managed-account logon [@ms-laps-policy-settings].

<Sidenote>The local Administrator account always has the well-known **relative identifier (RID) 500** in the machine's SAM, irrespective of any administrative renaming. Renaming the account at the friendly-name level does not change its SID, which is why Windows LAPS resolves the target account by SID and not by name -- and why an empty `AdministratorAccountName` policy still finds the right account even on a renamed-built-in host.</Sidenote>

> **Key idea:** Microsoft knew the right architecture for managing local Administrator passwords in December 2012, when its own Pass-the-Hash whitepaper named the shared-credential pattern as the architectural enabler of lateral movement. It took until April 11, 2023 to ship that architecture as a Windows default. Eleven years is a long time. The intervening generations each solved part of the previous problem and introduced a new one. The 2026 baseline is, for the first time, an OS-default solution rather than an out-of-band one -- and for the first time, the residual attack surface is the actual surface rather than an artefact of incomplete shipping.

<Mermaid caption="Twenty-eight years of Microsoft's local-administrator password story, from the imaged-build era to the in-box Windows LAPS default. Eleven years separate Microsoft's December 2012 Pass-the-Hash architectural articulation from the April 11, 2023 in-box default.">
gantt
    dateFormat YYYY-MM-DD
    axisFormat %Y
    title Local-administrator password management on Windows, 1998-2026

    section Generation 0 -- Imaged-build era
    Shared local admin password baked into image          :gen0, 1998-01-01, 2008-02-26

    section Generation 1 -- GPP cpassword
    Group Policy Preferences ships in WS2008 RTM           :g1a, 2008-02-27, 2014-05-12
    Linda Moore re-posts "Passwords in GPP (Updated)"     :milestone, 2009-04-22, 1d
    Sogeti / obscuresec / rewtdance / Metasploit chain    :crit, 2012-04-01, 2012-07-31
    MS PtH whitepaper v1 (architecture articulated)       :milestone, 2012-12-01, 1d
    MS14-025 disables new authoring (no remediation)      :milestone, 2014-05-13, 1d

    section Generation 2 -- Legacy MSI LAPS
    Microsoft LAPS GA (KB3062591 MSI)                      :g2a, 2015-05-01, 2023-04-10
    Metcalf publishes All-Extended-Rights bypass           :milestone, 2016-08-01, 1d
    SpecterOps BloodHound 2.0 ships ReadLAPSPassword edge :milestone, 2018-08-07, 1d

    section Generation 3 -- In-box Windows LAPS
    Windows LAPS ships in-box (AD backup)                  :crit, 2023-04-11, 2026-12-31
    Windows LAPS with Entra ID GA                          :milestone, 2023-10-23, 1d
    Win 11 24H2 passphrases and Automatic Account Mgmt    :milestone, 2024-10-01, 1d
    Win 11 25H2 Administrator Protection (orthogonal)     :milestone, 2025-11-19, 1d
</Mermaid>

The article that follows traces the architecture of each generation, the attacks each one solved and each one enabled, and what "standard local admin password management" looks like as a 2026 default. To see why this took twenty years, we have to start in 1998, before Active Directory.

## 2. Origins: Why Every Workstation Had the Same Local-Admin Password (1998-2008)

Picture a system administrator in 2005. They are holding a CD-R labelled `Win-Build-7.iso` and a sticky note with a 12-character password. Those two artefacts are the entire local-Administrator-credential lifecycle for ten thousand desktops. The CD will be cloned to a USB drive, the USB drive will reseed Norton Ghost, and Ghost will paint the build onto every new workstation the company buys for the next eight months. Each painted machine will boot with the sticky-note password as its built-in local Administrator. Helpdesk knows the password because they typed it into the image. Five hundred field technicians know the password because they have to be able to recover unmanaged laptops off-network. The pentester who shows up in March will know the password by Tuesday lunch.

This was not a deviation. It was the architecture.

<Definition term="RID 500 (the built-in local Administrator)">
Every Windows machine ships with a built-in local Administrator account whose security identifier ends in the **relative identifier 500**. The RID is constant across machines, languages, and SKUs. Renaming the account changes the friendly name but not the RID, so identity-aware tooling (including Windows LAPS) resolves the account by SID rather than by name. Disabling the account is a configuration choice, not a deletion: the account remains in SAM and can be re-enabled at any time.
</Definition>

The mechanics were a function of how Windows was deployed at scale. Microsoft Sysprep `/generalize` strips a reference image's machine SID before duplication, but it leaves the SAM intact. Whatever local Administrator password sits in the reference image is the local Administrator password on every endpoint painted from that image. Imaging pipelines were built around this: Norton Ghost in the late 1990s, Microsoft Deployment Toolkit (MDT) and later System Center Configuration Manager Operating System Deployment in the 2000s, all assumed the same SAM. Sean Metcalf's December 2015 SYSVOL retrospective walks the era end-to-end and explains why every shop in the world ended up with a single password [@adsec-gpp-2015].

The operational reality kept the pattern alive. Help-desk needed *one* known credential to break-glass a laptop that had wandered off the corporate network for six months. Field technicians needed *one* known credential to swap a failed hard drive on a roof-top kiosk in Houston without phoning home. A known-to-the-org local-admin password was the only realistic fallback path, and the alternative -- a different password per machine, stored somewhere retrievable -- required a *retrieval* primitive Microsoft had not yet shipped.

The threat model that made the trade-off catastrophic did not get articulated by Microsoft itself until December 2012, in version 1 of the Pass-the-Hash whitepaper [@ms-pth-whitepaper]. The chain was already common knowledge in offensive-security circles: phish a single user, run Benjamin Delpy's 2011-vintage Mimikatz to pull credentials from LSASS, capture the NT hash of the built-in `Administrator` account, replay that hash to every other host via `psexec` or `wmiexec`, and pivot up to the first server an enterprise admin has touched. MITRE catalogues the default-account abuse as **T1078.001** [@mitre-t1078-001] and the hash-replay step as **T1550.002** [@mitre-t1550-002]. The whitepaper's recommended controls included exactly the architecture Microsoft would eventually ship as LAPS: per-machine random local-admin passwords, rotated frequently, retrievable only by an authorised principal.

<Aside label="Why per-machine random was not the obvious answer">
The hard part was never the cryptography. It was the operations. A pre-2008 sysadmin who proposed "let's give every workstation a random local-Administrator password" was correctly told that the answer required, at minimum, a directory-scoped retrieval primitive that did not exist; an ACL model that could distinguish "help-desk can read this for their own OU" from "any authenticated user can read this for the whole forest"; and a rotation pipeline that did not depend on the workstation being on the corporate network. Microsoft would not ship those primitives until 2008 (GPP, badly), 2015 (legacy LAPS, well), and 2023 (Windows LAPS, with encryption-at-rest). Until then, "do not get compromised" was the entire mitigation.
</Aside>

The third-party prehistory matters because it set the terms Microsoft would eventually use. PolicyMaker, the engineering parent of what became Group Policy Preferences, was a product of DesktopStandard Corporation that Microsoft acquired in October 2006 [@adsec-gpp-2015]. Thycotic was founded in 1996 by Jonathan Cogley and shipped its Secret Server vault from the mid-2000s [@kuppingercole-cogley]; Lieberman Software (later acquired by Bomgar in January 2018) had operated as Lieberman and Associates since 1978 [@wikipedia-lieberman]; Quest Software was founded in 1987 in Newport Beach, California and was a public company well before the mid-2000s LAPS prehistory began -- its August 14, 1999 NASDAQ IPO saw its shares surge to \$47 in a single Wall Street session [@wikipedia-quest; @latimes-quest-ipo-1999]. None of those vendors solved the local-admin-on-every-Windows-machine problem from inside the OS, and Microsoft's own first-party tooling -- restricted groups, logon scripts, Group Policy Object security templates -- offered no rotation primitive at all. The gap was not a knowledge gap; it was a *first-party-feature* gap.

In February 2008, Microsoft shipped Windows Server 2008. With it came Group Policy Preferences -- and with GPP came a "Local Users and Groups" preference that could push a per-machine local-admin password from a domain GPO to every endpoint in scope. It was the first first-party rotation mechanism Microsoft had ever shipped. It made the problem dramatically worse.

## 3. Decoration Is Not Encryption: GPP cpassword (2008-2012)

Microsoft Server 2008 reached release-to-manufacturing in February 2008. Group Policy Preferences shipped with it. The new "Local Users and Groups" preference -- alongside Scheduled Tasks, Services, Data Sources, Drive Maps, and Printers -- could push a password from a GPO down to every endpoint in scope. The password went into an XML file in SYSVOL, the domain's replicated policy share. SYSVOL was world-readable to every authenticated user in the domain. The password was AES-256-CBC encrypted in the XML, in a field called `cpassword`. The key was a 32-byte value published in `[MS-GPPREF]` section 2.2.1.1.4 [@ms-gppref-aes-key], in Microsoft's own Open Specifications protocol corpus -- *as a feature*, so that third-party Group Policy implementations could interoperate.

<Definition term="SYSVOL">
A file share replicated to every Domain Controller in an Active Directory domain, used to distribute Group Policy templates and logon scripts. The default share permissions allow **Read** access to every Authenticated User in the forest. Any file placed in SYSVOL is, operationally, readable by every domain user.
</Definition>

<Definition term="cpassword">
The XML attribute defined by `[MS-GPPREF]` that carries an encrypted password inside a Group Policy Preferences item. The encryption is AES-256-CBC with a 16-byte zero IV and a static 32-byte key published in the same protocol specification. The name is short for "ciphertext password" and was the canonical search term for finding deployed credentials in SYSVOL between 2012 and 2026.
</Definition>

<Definition term="Group Policy Client-Side Extension (CSE)">
A loadable component on each Windows endpoint that processes one class of Group Policy setting. Each preference type (Local Users and Groups, Scheduled Tasks, Services, etc.) is implemented by its own CSE, which runs during the Group Policy refresh cycle. CSEs read the policy XML out of SYSVOL, decrypt any `cpassword` field locally, and apply the setting to the host.
</Definition>

Microsoft was not unaware. On April 22, 2009, the Group Policy Team blog re-posted (and updated) a piece by Linda Moore titled *"Passwords in Group Policy Preferences (Updated)"* [@ms-gp-blog-grouppolicy-2009-wayback]. The phrasing is unambiguous.

<PullQuote>
"the password is not secured. Because the password is stored in SYSVOL, all authenticated users have read access to it." -- Linda Moore, Group Policy Team blog, April 22, 2009 [@ms-gp-blog-grouppolicy-2009-wayback]
</PullQuote>

The post recommended a list of mitigations: prefer secure mechanisms, audit who can read the SYSVOL share, prefer not to use the field at all. None of those mitigations could rotate the key. None could revoke the *static AES-256 key value* published in `[MS-GPPREF]`. Microsoft was telling its customers, in 2009, three years and eight months before the public weaponisation, that the credential they were storing was decryptable by every user in the domain by design.

Three years later, the offensive-security community spent twelve weeks turning the publication into a default-on red-team primitive.

In April and May of 2012, Emilien Girault of Sogeti ESEC published a Python decryptor on the firm's research blog [@sogeti-2012-wayback]. The site has since been retired and the canonical reference is the Wayback Machine capture. In mid-May 2012, Chris Campbell (@obscuresec) published `Get-GPPPassword.ps1`, a PowerShell port that fetched the relevant XML from SYSVOL, decoded the base64, and called .NET's AES primitives with the published key [@obscuresec-gpp-2012]. The script was folded into PowerSploit at `Exfiltration/Get-GPPPassword.ps1`, where its header still reads *"Author: Chris Campbell (@obscuresec)"* [@powersploit-getgpppwd] and explicitly credits Emilien Girault for the underlying research. In June 2012, **Ben Campbell** (the `rewtdance.blogspot.com` blog handle), working with `scriptmonkey` (a named collaborator with his own blog at `blog.owobble.co.uk`), extended the attack to *all six* XML wire-format carriers that `[MS-GPPREF]` permits [@rewtdance-gpp-2012]. The rewtdance post body credits the collaboration verbatim: *"Working with scriptmonkey (http://blog.owobble.co.uk/), who already had a DC configured, we verified this theory."* On July 25, 2012, the Metasploit module `post/windows/gather/credentials/gpp.rb` landed [@metasploit-gpp] with five co-authors: Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, and mubix. A companion auxiliary scanner, `auxiliary/scanner/smb/smb_enum_gpp.rb`, was authored independently by Joshua D. Abraham of Praetorian [@metasploit-smb-enum-gpp].

> **Note:** A widespread folk attribution credits `Get-GPPPassword.ps1` to "scriptjunkie." The primary sources do not support that claim. The PowerSploit script header credits Chris Campbell (@obscuresec) [@powersploit-getgpppwd]; the rewtdance June 2012 follow-up is by Ben Campbell with scriptmonkey as a named collaborator (scriptmonkey blogs at `blog.owobble.co.uk`, not at rewtdance) [@rewtdance-gpp-2012]; the Metasploit `gpp.rb` module's author field names Ben Campbell, Loic Jaquemet, scriptmonkey, theLightCosine, and mubix [@metasploit-gpp]; and the `smb_enum_gpp` scanner is by Joshua D. Abraham [@metasploit-smb-enum-gpp]. No primary source ties "scriptjunkie" (Matt Weeks) to the GPP cpassword research chain at all. The names are similar; the people are different.

The whole exercise was twelve lines of code. The interesting part was not the cryptography. The interesting part was that the operation was *decryption-by-reference*: with a published key, the AES envelope was not protecting a secret, it was carrying a secret in a format the protocol specification told everyone how to read.

<Spoiler kind="solution" label="The 32-byte AES key, as published by Microsoft in [MS-GPPREF] 2.2.1.1.4">
```
4e 99 06 e8  fc b6 6c c9  fa f4 93 10  62 0f fe e8
f4 96 e8 06  cc 05 79 90  20 9b 09 a4  33 b6 6c 1b
```
These bytes are reproduced verbatim from Microsoft's published `[MS-GPPREF]` Group Policy Preferences specification [@ms-gppref-aes-key]. They have appeared in the public Microsoft Open Specifications corpus since the `[MS-GPPREF]` protocol document was first published as part of the Windows Server 2008 protocol-documentation programme; the earliest tangible third-party reuse of the key dates to the April-July 2012 Sogeti / obscuresec / rewtdance / Metasploit research chain [@sogeti-2012-wayback; @obscuresec-gpp-2012; @rewtdance-gpp-2012; @metasploit-gpp]. The key is *not* a secret; it is an interoperability primitive.
</Spoiler>

<RunnableCode lang="python" title="Twelve-line cpassword decryptor (illustrative)">{`

    ReadSucceeds["Read succeeds (silent CONTROL_ACCESS bypass)"]
    ReadFails["Read fails (correctly ACL-gated)"]
    Endpoint --> GPRefresh
    GPRefresh --> Rotate
    Rotate --> SAMWrite
    Rotate --> ADWrite
    ADWrite --> LDAPRead
    LDAPRead --> Bypass
    Bypass -- yes --> ReadSucceeds
    Bypass -- no --> ReadFails
</Mermaid>

The other structural limit was the directory's own integrity boundary. The password sat in plaintext in the directory. A stolen `NTDS.dit` -- obtained via DCSync, NTDSUtil dump, or physical theft of a DC's disk -- exposed every managed local-Administrator password in the forest at once. There was no encryption-at-rest in legacy LAPS, by design. The trust model was "the directory is tier 0 and DCSync is a domain-compromise event already," which is operationally true and architecturally lazy.

Microsoft fixed both of those structural defects on April 11, 2023. The fix shipped in the operating system, with no MSI. We come to it next.

## 6. The In-Box Era: Windows LAPS (April 11, 2023 to Present)

Patch Tuesday, April 11, 2023. The April cumulative update for Windows 11 22H2 was KB5025239. The Windows 11 21H2 update was KB5025224. Windows 10 22H2 was KB5025221. Windows Server 2022 was KB5025230. Windows Server 2019 was KB5025229. The Server Annual Channel shipped it too. Windows Server 2016 was, and remains, explicitly excluded -- the per-SKU April-2023 cumulative-update KB numbers are catalogued in the Tenable retrospective on the Windows LAPS GA wave [@tc-windows-laps-ga-2023] and the official Microsoft LAPS overview page [@ms-laps-overview]. The MSI was gone. The `admpwd.dll` Client-Side Extension was gone. In its place: **exactly three** OS binaries -- `laps.dll` for core LAPS logic, `lapscsp.dll` for the Microsoft Intune Configuration Service Provider, and `lapspsh.dll` for the `LAPS` PowerShell module -- all shipped together, all part of the OS, all available without installing anything [@ms-laps-concepts-overview; @tc-windows-laps-ga-2023]. The Microsoft Learn `laps-concepts-overview` page enumerates the three binaries verbatim and lists no fourth.

The most consequential architectural change is the one most often missed.

> **Note:** The legacy `admpwd.dll` was a Group Policy CSE; its rotation cycle was driven by the GP refresh interval (90 minutes plus jitter on member computers). The new `laps.dll` is *not* a CSE. It runs on a hard-coded in-process background timer of approximately one hour inside `laps.dll` itself -- **not** a Windows Task Scheduler task, and not configurable. The cited Microsoft Learn page is unambiguous: *"Windows LAPS uses a background task that wakes up every hour to process the currently active policy. This task isn't implemented with a Windows Task Scheduler task and isn't configurable."* The polling cycle is decoupled from the Group Policy refresh cycle entirely [@ms-laps-concepts-overview]. The implications: the rotation cadence is not configurable below one hour; reducing the GP refresh interval does not accelerate LAPS rotation; the Task Scheduler library will not show a LAPS task because there isn't one; and Windows LAPS will rotate a password on an off-network domain-joined machine the moment it re-establishes line-of-sight to a Domain Controller, regardless of whether a GP refresh has fired.

The new schema added six attributes to the `Computer` object: `msLAPS-Password` (the plaintext-fallback location), `msLAPS-EncryptedPassword` (the CNG-DPAPI-wrapped ciphertext blob), `msLAPS-EncryptedPasswordHistory` (rotation history), `msLAPS-PasswordExpirationTime`, `msLAPS-EncryptedDSRMPassword` (Directory Services Restore Mode account on a DC), and `msLAPS-EncryptedDSRMPasswordHistory` [@ms-laps-concepts-overview]. The DSRM pair is a Windows-LAPS-only capability; legacy LAPS never covered Domain Controller DSRM accounts. The schema extension is performed once per forest by `Update-LapsADSchema`, which is idempotent and coexists with the legacy `ms-Mcs-AdmPwd` attribute [@ms-laps-mig-scenarios].

<Sidenote>A seventh attribute, `msLAPS-CurrentPasswordVersion`, exists in the **Windows Server 2025 forest schema** only. It is added automatically when the first Windows Server 2025 Domain Controller is promoted -- *not* by running `Update-LapsADSchema` -- and is used by `laps.dll` to mitigate a virtual-machine-snapshot torn-state class. The attribute is read-only as far as the LAPS feature is concerned and is not part of the `ReadLAPSPassword` BloodHound edge's calculus [@ms-laps-concepts-overview].</Sidenote>

### Encryption-at-rest with CNG DPAPI

The load-bearing addition is encryption of the password *before* it leaves the client. The mechanism is the **CNG DPAPI** group key-protector (still commonly called DPAPI-NG in Microsoft's older documentation) [@ms-cng-dpapi]. The client generates the new local-Administrator password, then wraps the plaintext against a security principal SID using the Active Directory Key Distribution Service (KDS) root key infrastructure. The wrapped blob is the only thing the LDAP write places into `msLAPS-EncryptedPassword`. To decrypt, a reader Kerberos-authenticates to the KDC; only members of the configured principal group at decryption time can derive the protector. The directory itself never sees plaintext, and a stolen `NTDS.dit` yields ciphertext only [@ms-laps-concepts-overview].

<Definition term="CNG DPAPI (DPAPI-NG) group key-protector">
A protection mechanism in Windows's CNG (Cryptography API: Next Generation) Data Protection API in which a payload is encrypted against a security principal -- typically an AD group SID -- rather than against a local user. Decryption is gated by Kerberos authentication and the principal's group membership at the time of decryption [@ms-cng-dpapi]. Microsoft Learn currently spells the primitive *"CNG DPAPI"* on the canonical reference; older Microsoft documentation and Win32 references continue to use the shorthand *"DPAPI-NG"*. They are the same primitive.
</Definition>

There are two policy settings that gate the encryption path, and the failure modes are operationally important.

> **Note:** Microsoft Learn's `laps-management-policy-settings` page lists `ADPasswordEncryptionEnabled` with a default of **True** [@ms-laps-policy-settings]. The genuine failure mode is *not* an unset default; it is silent fallback to plaintext in `msLAPS-Password` when (a) the forest's Domain Functional Level is below Windows Server 2016, or (b) the `BackupDirectory` value is not `2` (AD). Configure the policy *explicitly* anyway: the explicit configuration makes the choice visible to policy audits and forces the operator to verify the DFL prerequisite. Do not flip a bit that is already True; do verify the prerequisites that make True work.

> **Note:** When `ADPasswordEncryptionPrincipal` is unspecified, Windows LAPS wraps the password against the *Domain Admins* group of the computer's domain [@ms-laps-concepts-overview; @ms-laps-policy-settings]. Most fleets do not want every Domain Admin to be a routine LAPS reader. Configure a dedicated, audited, minimum-membership decryption group (a common naming convention is `LAPS-DPAPI-Decryptors`) and assign it explicitly. Decryption authority is delegated separately from LDAP read authority; minimising membership of the decryption group is the single most useful hardening lever on a Windows LAPS deployment.

### The backup-directory choice

<Definition term="BackupDirectory (Windows LAPS policy)">
The CSP / GPO node `BackupDirectory` selects where Windows LAPS writes the rotated password. The three valid values are **0** (do not back up; passwords rotate locally but are not retrievable), **1** (Microsoft Entra ID via the `deviceLocalCredentials` resource on Microsoft Graph), and **2** (Active Directory via the `msLAPS-*` attribute set). The values are mutually exclusive per device; a hybrid-joined device can choose either backend but not both [@ms-laps-policy-settings; @ms-laps-entra-scenarios].
</Definition>

The Entra-backup path went generally available on October 23, 2023 [@tc-entra-laps-ga-2023]. With `BackupDirectory = 1`, the local LAPS component posts the rotated password to the `deviceLocalCredentials` resource on the device object in Microsoft Entra ID via the Microsoft Graph API [@ms-graph-localcredinfo]. Retrieval is via `Get-LapsAADPassword` (a thin wrapper over the Graph endpoint), the Entra portal Devices blade, or a direct `GET /directory/deviceLocalCredentials/{deviceId}` call [@ms-laps-entra-scenarios].

<Sidenote>The Entra-backup path has a **seven-day minimum** for `PasswordAgeDays`. The AD-backup path's minimum is one day. A tier-0 fleet that targets daily rotation on Entra-joined endpoints will not get daily rotation -- Entra-side policy validation rejects the value. Section 7's baseline table reflects this asymmetry.</Sidenote>

### Policy surface and the FQ-anchored corrections

Windows LAPS is configurable via Group Policy (for AD-joined hosts), the LAPS Configuration Service Provider at `./Device/Vendor/MSFT/LAPS/Policies/*` for Intune-managed hosts [@ms-laps-csp], local policy, or the legacy LAPS GPO if `PolicySourceMode` selects emulation mode. The settings include `BackupDirectory`, `PasswordComplexity` (values 1 through 8), `PasswordLength`, `PasswordAgeDays`, `PostAuthenticationActions`, `PostAuthenticationResetDelay`, `AdministratorAccountName`, `PassphraseLength`, `ADPasswordEncryptionEnabled`, `ADPasswordEncryptionPrincipal`, and `ADBackupDSRMPassword`. On Windows 11 24H2 and Windows Server 2025 and later, the policy surface adds Automatic Account Management settings: `AutomaticAccountManagementEnabled`, `AutomaticAccountManagementNameOrPrefix`, `AutomaticAccountManagementRandomizeName`, `AutomaticAccountManagementTarget`, and `AutomaticAccountManagementEnableAccount` [@ms-laps-policy-settings; @ms-laps-account-modes].

<Definition term="PostAuthenticationActions">
The action Windows LAPS performs after the managed account has authenticated to the host. Valid values are **1** (reset the password), **3** (reset and sign out the interactive session; default), **5** (reset and reboot, with a one-minute reboot delay), and **11** (reset, sign out, and terminate remaining processes; Windows 11 24H2 / Windows Server 2025 and later). The action fires after `PostAuthenticationResetDelay` hours have elapsed since the authentication that triggered it [@ms-laps-policy-settings].
</Definition>

> **Note:** A widespread misreading of the older Microsoft documentation lists `PostAuthenticationActions` as a 1-2-3 enum. The correct enumeration per the current Microsoft Learn reference [@ms-laps-policy-settings] is **1** (reset password), **3** (reset + sign out; *default*), **5** (reset + reboot), and **11** (reset + sign out + terminate remaining processes; Win 11 24H2 / Server 2025+). Value **11** is *not* "force shutdown without warning"; interactive users receive the same non-configurable two-minute warning as on value 3, and remaining processes are terminated after the warning expires. SMB sessions on the host are deleted on values 3 and 11.

`PostAuthenticationResetDelay` defaults to **24 hours**. The range is 0 to 24 hours; a value of 0 disables the post-authentication action entirely [@ms-laps-policy-settings]. A tier-0 fleet aiming to close the screenshotted-password OPSEC tail aggressively will configure this down to 1 hour; tier-2 deployments typically leave it at 8 or 24.

### PasswordComplexity values 5 through 8 (Windows 11 24H2+ / Windows Server 2025+)

`PasswordComplexity` values **1 through 4** are character-class modes (uppercase only; uppercase plus lowercase; uppercase plus lowercase plus numbers; and -- value 4, the default -- all four character classes). Value **5** is *not* a "no vowels or numbers" mode, despite a common folk attribution; it is the **"improved readability" four-class variant** of value 4, equivalent to value 4 with the visually ambiguous glyphs `I`, `O`, `Q`, `l`, `o`, `0`, `1` removed and the symbols `:`, `=`, `?`, `*` added [@ms-laps-passwords-passphrases]. Microsoft's own documented example password for value 5 is `vnJ!!?MTb5=U7Y` -- which retains vowels and digits 2 through 9. Values **6, 7, and 8** are passphrase modes drawn from a Microsoft-curated wordlist derived from the EFF Diceware wordlists [@eff-dice; @eff-wordlists-2016] with internal modifications. The published word counts after Microsoft's curation are **7776 / 1276 / 1276** for modes 6 / 7 / 8 respectively; the EFF originals (the EFF Long Wordlist, EFF Short Wordlist #1, and EFF Short Wordlist #2 published July 2016) are **7776 / 1296 / 1296** [@eff-dice; @eff-wordlists-2016]. **Values 5 through 8 are all gated on Windows 11 24H2 / Windows Server 2025 and later** -- not only values 6-8. The cited Microsoft Learn page reads verbatim for value 5: *"The PasswordComplexity setting of '5' is only supported in Windows 11 24H2, Windows Server 2025, and later releases."* [@ms-laps-passwords-passphrases]. Passphrase modes exist for DSRM-account scenarios where the password must be typed by a human under duress; the article's section 7 baseline recommends them for tier-0 break-glass accounts.

### PowerShell surface and one important cmdlet name

The native `LAPS` PowerShell module ships eight cmdlets the article calls out by name: `Get-LapsADPassword`, `Reset-LapsPassword`, `Update-LapsADSchema`, `Set-LapsADAuditing`, `Set-LapsADComputerSelfPermission`, `Set-LapsADReadPasswordPermission`, `Set-LapsADResetPasswordPermission`, and `Find-LapsADExtendedRights` [@ms-laps-ps-overview; @ms-laps-get-adpassword]. The auditing cmdlet is `Set-LapsADAuditing` -- *not* `Set-LapsADAuditingSettings`, which does not exist as a cmdlet name [@ms-laps-set-adauditing]. The Entra-backup retrieval cmdlet is `Get-LapsAADPassword`, a wrapper around Microsoft Graph.

> **Note:** A common copy-paste error in deployment runbooks is to write `Set-LapsADAuditingSettings`. The cmdlet name is `Set-LapsADAuditing` [@ms-laps-set-adauditing], and the cmdlet emits Directory Service audit event 4662 on configured attribute reads. The SACL it installs targets the LAPS attribute set; you still need the host-side Audit Directory Service Access subcategory enabled on Domain Controllers for the event to land in the Security log.

### Migration coexistence

Legacy LAPS and Windows LAPS can coexist on the same host only if they target *different* local accounts. The documented coexistence pattern is to run legacy LAPS against the built-in RID 500 Administrator while introducing Windows LAPS against a named secondary local-admin account, then retire the legacy MSI once Windows LAPS coverage is verified [@ms-laps-mig-scenarios]. The cross-pointer in section 11 details the seven-step migration sequence.

<Mermaid caption="Windows LAPS runs on a hard-coded ~1-hour background timer in laps.dll. Encryption to AD requires DFL of Server 2016 or higher AND BackupDirectory = 2 AND ADPasswordEncryptionEnabled = True (the default per the Microsoft Learn policy-settings page); any failed precondition silently falls back to plaintext in msLAPS-Password.">
flowchart TD
    Tick["laps.dll background timer (~1 hr)"]
    ReadPolicy["Read effective policy<br/>CSP > GPO > local > legacy emulation"]
    BackupDir&#123;"BackupDirectory<br/>1 (Entra) / 2 (AD) / 0?"&#125;
    EntraPath["Write to Graph deviceLocalCredentials<br/>(min PasswordAgeDays = 7)"]
    ADPath["Write to msLAPS-* attribute set<br/>(min PasswordAgeDays = 1)"]
    EncryptionGate&#123;"ADPasswordEncryptionEnabled = True<br/>AND DFL ≥ Server 2016?"&#125;
    Encrypted["msLAPS-EncryptedPassword<br/>(DPAPI-NG, principal = ADPasswordEncryptionPrincipal)"]
    Plaintext["msLAPS-Password (plaintext fallback)"]
    SetSAM["Set SAM password on<br/>AdministratorAccountName (empty = RID 500)"]
    Auth["Managed account authenticates"]
    PAA&#123;"PostAuthenticationActions<br/>0 / 1 / 3 / 5 / 11?"&#125;
    Wait["Wait PostAuthenticationResetDelay (default 24 h)"]
    Action1["1: reset password"]
    Action3["3: reset + sign out, 2-min warning, DEFAULT"]
    Action5["5: reset + reboot, 1-min delay"]
    Action11["11: reset + sign out + terminate procs (24H2 / WS2025+)"]
    Tick --> ReadPolicy
    ReadPolicy --> BackupDir
    BackupDir -- 1 --> EntraPath
    BackupDir -- 2 --> EncryptionGate
    BackupDir -- 0 --> SetSAM
    EncryptionGate -- yes --> Encrypted
    EncryptionGate -- no --> Plaintext
    EntraPath --> SetSAM
    Encrypted --> SetSAM
    Plaintext --> SetSAM
    SetSAM --> Auth
    Auth --> Wait
    Wait --> PAA
    PAA -- 1 --> Action1
    PAA -- 3 --> Action3
    PAA -- 5 --> Action5
    PAA -- 11 --> Action11
</Mermaid>

With the in-box era settled, what does a 2026 deployment actually look like? A short list of policy settings, and a slightly longer list of footguns.

## 7. The 2026 Baseline as a Settings Table

Architecture is interesting. Audits are not. Here is the 2026 settings table that, in production, separates a deployment that meets its goal from one that quietly does not. Every row carries the policy node, the documented default, the recommended tier-2 value (a typical end-user fleet), the recommended tier-0 value (Domain Controllers and break-glass), and the citation. Cross-check the row against the Microsoft Learn policy-settings page before you ship it.

| Policy | Default | Recommended (tier 2) | Recommended (tier 0) | Why | Citation |
|---|---|---|---|---|---|
| `BackupDirectory` | `0` (no backup) | `2` (AD) for AD-joined and hybrid-joined; `1` (Entra) for pure Entra-joined | same as tier 2 | One directory per device; AD for hybrid where on-prem identity is canonical | [@ms-laps-policy-settings] |
| `PasswordComplexity` | `4` (all character classes) | `4` | `6` (3-word passphrase) for accounts a human must type under duress (DSRM / break-glass); `4` for automated retrieval | Passphrases for human typing; character-set for tool-only retrieval. Values **5 through 8** are gated on Windows 11 24H2 / Windows Server 2025 and later: value 5 is the "improved-readability" four-class variant of 4 (not a "no vowels" mode); values 6/7/8 are passphrase modes with Microsoft-curated EFF-derived wordlists of 7776 / 1276 / 1276 entries (EFF originals: 7776 / 1296 / 1296) | [@ms-laps-passwords-passphrases; @eff-dice; @eff-wordlists-2016] |
| `PasswordLength` | `14` | `24` | `24` | Eliminates the rainbow-table threat class | [@ms-laps-passwords-passphrases] |
| `PasswordAgeDays` | `30` (1-day minimum AD; 7-day minimum Entra; 365-day max) | `30` | `1` (AD) / `7` (Entra; lower fails policy validation) | Caps the blast radius of an undetected credential theft to one rotation window | [@ms-laps-policy-settings] |
| `PostAuthenticationActions` | `3` (reset + sign out) | `3` | `3`, or `11` on Win 11 24H2+ if process termination is required | Closes the screenshot-leak OPSEC tail on the next managed-account interactive logon. Value `11` is *not* "force shutdown without warning" -- it is reset + sign out + terminate remaining processes with the same two-minute warning as `3` | [@ms-laps-policy-settings] |
| `PostAuthenticationResetDelay` | `24` (hours) | `8` | `1` | Trade-off between operational task completion and exposure window | [@ms-laps-policy-settings] |
| `ADPasswordEncryptionEnabled` | `True` per Microsoft Learn's defaults table -- *not* off-by-default | `True`, configured explicitly so the choice is visible in policy audits and the DFL prerequisite is verified | same | The genuine failure mode is silent fallback to plaintext when DFL is below Server 2016 or `BackupDirectory` is not `2`, *not* a default-off bit | [@ms-laps-policy-settings; @ms-laps-csp] |
| `ADPasswordEncryptionPrincipal` | `Domain Admins` of the computer's domain when unspecified | Dedicated `LAPS-DPAPI-Decryptors` group, *not* Domain Admins | same, with PIM-gated activation | Decryption authority is delegated separately from LDAP read; minimise membership | [@ms-laps-concepts-overview] |
| `AdministratorAccountName` | empty (manages built-in RID 500) | empty on Server SKUs; named account (e.g. `lapsadmin`) on Client SKUs with the built-in disabled | On Win 11 24H2 / WS2025+, prefer Automatic Account Management with random name and disabled-by-default | Defeats predictable-RID-500 enumeration | [@ms-laps-policy-settings; @ms-laps-account-modes] |
| `ADBackupDSRMPassword` | `False` | n/a (member servers) | `True` on Domain Controllers | Brings DSRM-account management into LAPS scope -- a capability legacy LAPS never had | [@ms-laps-concepts-overview] |

<Aside label="Tier-0 hardening deltas">
Tier-0 deviations from the tier-2 baseline are narrow but consequential. (a) `PasswordAgeDays` to 1 (AD) or 7 (Entra) caps the undetected-theft window. (b) `PostAuthenticationResetDelay` to 1 hour aggressively rotates after legitimate use. (c) `ADPasswordEncryptionPrincipal` to a dedicated decryptor group with PIM-gated activation [@ms-entra-pim] -- not standing membership. (d) `ADBackupDSRMPassword = True` only on DCs, so the Directory Services Restore Mode account is in LAPS scope. (e) `PasswordComplexity = 6` on accounts that a human must type under duress (DSRM, ESAE break-glass), `4` everywhere else. The tier-0 baseline is more expensive operationally -- daily rotation and 1-hour post-auth delay create a non-trivial volume of password reads through the decryption group -- and the cost is the entire point. Anything cheaper does not warrant the tier-0 label.
</Aside>

> **Note:** The single most useful hardening move on a Windows LAPS deployment is to explicitly set `ADPasswordEncryptionPrincipal` to a dedicated group with minimum membership. Default = Domain Admins of the computer's domain is operationally correct (Domain Admins should be the readers of last resort) but architecturally lazy (most fleets do not want their DA group to be the routine LAPS-read group). Name the group something searchable -- `LAPS-DPAPI-Decryptors` is a defensible convention -- and put helpdesk LAPS-read permissions in *that* group, gated by Entra PIM activation [@ms-entra-pim] for non-emergency reads.

### The audit-primitives sub-table

The decision of which tool answers which question is, in practice, the difference between a LAPS deployment that meets its goal and one that quietly does not. The five (and a half) primitives:

| Primitive | Question it answers | Primary source |
|---|---|---|
| BloodHound `ReadLAPSPassword` edge | Which principals can read the LAPS password on which computer objects, transitively across the graph? | [@bloodhound-edge-readlaps] |
| PingCastle `A-LAPS-Not-Installed` | Does this domain have any LAPS solution installed for the native local administrator account? | [@pingcastle-rules] |
| PingCastle `A-LAPS-Joined-Computers` | Can a user who manually domain-joined a computer (via `mS-DS-CreatorSID` ownership) still read that computer's LAPS password? | [@pingcastle-rules] |
| PingCastle `A-PwdGPO` | Does this domain still have residual GPP `cpassword` artefacts in SYSVOL? (MITRE T1552.006) | [@pingcastle-rules; @mitre-t1552-006] |
| Windows event 4662 on `msLAPS-*` (SACL via `Set-LapsADAuditing`) | Who read which LAPS attribute on which computer object, and when? | [@ms-laps-set-adauditing; @ms-laps-ps-overview] |
| Entra audit log + Graph `GET /directory/deviceLocalCredentials/{deviceId}` reads | Who retrieved which LAPS password from Microsoft Entra ID (`BackupDirectory = 1`), and when? | [@ms-graph-localcredinfo; @ms-laps-entra-scenarios] |

No Microsoft Defender for Identity alert in the current public taxonomy names LAPS specifically [@ms-defender-alerts]; instead, lean on the event 4662 SACL primitive plus advanced hunting in the `IdentityDirectoryEvents` table for principal-pattern anomalies. Microsoft's Compromised Credentials and Lateral Movement categories surface the downstream behaviour when a stolen LAPS password gets used.

<RunnableCode lang="js" title="LAPS coverage verifier (illustrative; mirrors the logic of a Get-LapsADPassword sweep)">{`
// In production, run: Get-LapsADPassword -Identity * | Where-Object {
//   $_.ExpirationTimestamp -lt (Get-Date) -or $_.Source -eq 'Plaintext'
// }
// This in-browser demo mirrors the same logic against an array of mock computer objects.

const ONE_DAY_MS = 86400000;
const computers = [
  { name: "WS-001", msLapsExpiry: Date.now() + 5 * ONE_DAY_MS, encrypted: true  },
  { name: "WS-002", msLapsExpiry: Date.now() - 2 * ONE_DAY_MS, encrypted: true  },
  { name: "WS-003", msLapsExpiry: null,                        encrypted: false },
  { name: "WS-004", msLapsExpiry: Date.now() + 1 * ONE_DAY_MS, encrypted: false },
];

const gaps = computers.flatMap(c => {
  const issues = [];
  if (c.msLapsExpiry === null)           issues.push("no password stored");
  else if (c.msLapsExpiry < Date.now())  issues.push("expired (overdue rotation)");
  if (!c.encrypted)                      issues.push("plaintext (msLAPS-Password)");
  return issues.length ? [\`\${c.name}: \${issues.join(", ")}\`] : [];
});

console.log(gaps.length === 0
  ? "All computers have current, encrypted LAPS passwords"
  : "Coverage gaps:\\n  " + gaps.join("\\n  "));
`}</RunnableCode>

The `AdministratorAccountName` decision deserves one paragraph of its own. On Server SKUs, the built-in Administrator (RID 500) is enabled by default, and leaving the policy empty manages it -- this is what most deployments want. On Client SKUs the built-in is disabled by default; many shops create a named admin account (a common convention is `lapsadmin`) and set `AdministratorAccountName` to that name. On Windows 11 24H2 and Windows Server 2025 and later, the better answer is Automatic Account Management: set `AutomaticAccountManagementEnabled = 1`, `AutomaticAccountManagementRandomizeName = 1`, and `AutomaticAccountManagementEnableAccount = 0`, and the host will auto-create a randomised-name disabled-by-default local-admin account that Windows LAPS owns end to end [@ms-laps-account-modes]. The result is that an attacker enumerating local accounts cannot guess the LAPS-managed account name from RID 500, RID 1000, or any other predictable identifier.

This is the baseline. But LAPS is not the only answer to "who knows the local admin password." For three classes of fleet, the right answer is something else.

## 8. When LAPS Is Not the Right Tool

Three classes of fleet should not -- or should not *only* -- run Windows LAPS. The first wants a workflow LAPS does not offer. The second wants no standing local admin at all. The third is orthogonal: it changes the in-session elevation surface without changing the recoverable break-glass.

**Third-party Privileged Access Management (PAM) vaults.** Delinea Secret Server [@delinea-secretserver], CyberArk Endpoint Privilege Manager [@cyberark-epm], and BeyondTrust Password Safe are the dominant 2026 commercial offerings in the category. The case for running a PAM vault alongside (or instead of) Windows LAPS is rarely about cryptography and almost always about workflow. PAM vaults bring multi-factor authentication on checkout, full session recording, dual-approval gates for high-risk accounts, and cross-OS scope (Windows, macOS, Linux, network gear, hypervisors) under one ACL model. The total cost of ownership is higher than LAPS; the security model, properly deployed, is comparable. Many shops run both: Windows LAPS for the workstation floor, PAM for tier-0 break-glass with session recording. The split is a *workflow* trade-off, not an architectural one.

**Zero standing local admin plus Entra PIM JIT elevation.** Tier-0 fleets that have reached the "no routine local admin" architectural state disable the built-in RID 500 entirely and gate every admin operation through just-in-time elevation. Microsoft Entra Privileged Identity Management [@ms-entra-pim] supports the eligibility / activation / approval workflow at scale: an operator is *eligible* for an admin role, *activates* it for a bounded duration with optional MFA and ticket reference, and an *approver* signs off on the activation if policy requires. Windows LAPS coexists in this model as the absolute-last-resort break-glass mechanism -- for the case where Entra itself is down, the network is partitioned, and a human has to walk to a console and type a password. The architectural alignment is with MITRE T1078.001 (Default Accounts) [@mitre-t1078-001]: if the default account is permanently disabled and only re-enabled under PIM workflow, the entire technique class is bounded by the PIM activation log.

**Windows 11 25H2 Administrator Protection.** Per-elevation transient admin sessions arrived as a Tech Community preview in late 2025 [@tc-admin-protection-win11]. The feature creates a temporary, isolated "shadow admin" identity for the duration of each elevation prompt, brokering UAC-class elevation through a per-elevation token that is destroyed when the elevated process exits. **This is orthogonal to LAPS, not a replacement.** Administrator Protection addresses in-session UAC elevation; Windows LAPS addresses the recoverable break-glass password for off-network and non-bootable recovery. The two systems answer different questions. Conflating them produces designs that drop LAPS in favour of Administrator Protection and then discover, six months later, that there is no recovery primitive for a laptop the user has dropped off the corporate network for a year.

| Situation | Recommended method |
|---|---|
| On-premises AD-joined, no Entra ID | **A** -- in-box Windows LAPS with AD backup |
| Microsoft Entra hybrid-joined, on-prem AD authoritative | **A** -- Microsoft's current hybrid recommendation |
| Pure Entra-joined, no on-prem AD | **B** -- in-box Windows LAPS with Entra ID backup |
| Stuck on Windows Server 2016 (excluded from Windows LAPS) | **C** -- legacy MSI LAPS until OS migration completes |
| In active migration from legacy LAPS to Windows LAPS | **C** in side-by-side mode with different managed accounts |
| Non-Windows scope (Linux, macOS, network gear) needs unified vaulting | **D** -- third-party PAM vault, often alongside A/B |
| Regulated industry requiring session recording / MFA checkout | **D** alongside A/B |
| Tier-0 fleet with a zero-standing-credential goal and Entra ID P2 | **E** -- PIM-gated JIT elevation layered on A or B |
| Windows 11 fleet wanting in-session credential-theft mitigation | **F** -- Administrator Protection alongside A/B (orthogonal) |
| BYOD, workgroup, or unmanaged endpoints | None of A through F -- *enrollment* is the answer, not LAPS |

<Mermaid caption="Pick the right tool for the fleet. Methods A and B are the in-box defaults for AD-joined and Entra-joined respectively; Methods D and E layer on top; Methods C and F have narrow remaining roles.">
flowchart TD
    Start["Local-admin password problem for a fleet"]
    BYOD&#123;"BYOD or unmanaged?"&#125;
    EnrollFirst["Enrollment is the answer, not LAPS"]
    Join&#123;"AD-joined / hybrid / Entra-joined?"&#125;
    WS2016&#123;"Stuck on WS2016 or in migration?"&#125;
    Tier0&#123;"Tier 0 with zero-standing-credential goal?"&#125;
    CrossOS&#123;"Non-Windows scope or checkout workflow needed?"&#125;
    WinElev&#123;"Win 11 25H2 in-session elevation hardening?"&#125;
    MA["Method A: Windows LAPS, AD backup"]
    MB["Method B: Windows LAPS, Entra backup"]
    MC["Method C: legacy MSI LAPS"]
    MD["Method D: PAM vault, alongside A/B"]
    ME["Method E: PIM-gated JIT, layered on A/B"]
    MF["Method F: Administrator Protection (orthogonal)"]
    Start --> BYOD
    BYOD -- yes --> EnrollFirst
    BYOD -- no --> Join
    Join -- AD or hybrid --> MA
    Join -- pure Entra --> MB
    MA --> WS2016
    MB --> WS2016
    WS2016 -- yes --> MC
    WS2016 -- no --> Tier0
    Tier0 -- yes --> ME
    Tier0 -- no --> CrossOS
    CrossOS -- yes --> MD
    CrossOS -- no --> WinElev
    WinElev -- yes --> MF
</Mermaid>

<Aside label="Hybrid joined is not Hybrid Worker">
The terminology is genuinely confusing. *Microsoft Entra hybrid joined* is a device join state: the workstation is joined to both an on-premises AD domain and Microsoft Entra ID, and both directories know about it. *Microsoft Entra hybrid runbook worker*, by contrast, is an Azure Automation primitive that runs Automation runbooks on a worker process inside an on-premises environment. They share a word and nothing else. Windows LAPS policy for hybrid-*joined* devices is a `BackupDirectory` choice (typically AD for on-prem-authoritative hybrid fleets, Entra for Entra-authoritative); Hybrid runbook workers are an Azure Automation concern and entirely outside the LAPS scope.
</Aside>

All five answers above -- methods A through F -- have a structural ceiling. There is one bound none of them can break.

## 9. What LAPS Structurally Cannot Solve

Every recoverable-secret system has a privileged reader. Whether you call it `ADPasswordEncryptionPrincipal`, a "CyberArk vault admin," or a "PIM eligible approver," somebody can break the glass -- which means somebody can compromise the glass. This is a lower bound, not an implementation defect.

The eleven-year arc converged on a tight bound. It did not abolish the underlying problem. Four structural limits are worth naming, because each maps onto a real residual attack surface in 2026 deployments.

**Bound 1: at least one reader exists, by construction.** Symbolically, $|\text{readers}| \geq 1$. CNG DPAPI's group-key-protector substitution does not eliminate the privileged class; it relocates the trust boundary. The boundary moves from "every principal with LDAP read on the attribute" (legacy LAPS) to "every principal in the configured `ADPasswordEncryptionPrincipal` group at decryption time" (Windows LAPS). The relocation tightens the bound by orders of magnitude in typical fleets -- a `LAPS-DPAPI-Decryptors` group with five members beats an "All Extended Rights on the helpdesk OU" delegation with five hundred -- but it does not move the bound to zero. The directory that stores the LAPS secret remains a tier-0 asset, and the decryptor group remains a tier-0 principal class.

<PullQuote>
Every recoverable secret has a privileged reader. The architectural game is to make the reader class small, audited, time-bounded, and reachable from the directory only through Kerberos. The game is not to make the reader class empty. That game has no winning move.
</PullQuote>

**Bound 2: the out-of-protocol OPSEC tail.** Once a plaintext password leaves the directory -- pasted into a helpdesk ticket, screenshotted into a Slack DM, stored in a shared KeePass database that the team forgot to rotate -- the protocol's rotation knob is the only remaining mitigation. `PostAuthenticationActions` only fires after the *next managed-account interactive logon* [@ms-laps-policy-settings]; pre-logon exposure is bounded only by `PasswordAgeDays`. A password screenshotted into a chat log at 10:14 AM and never used is the password on that endpoint for the remainder of the configured rotation window, regardless of whether anyone has noticed the leak. The protocol does not, and cannot, solve "the password is now in a chat log."

**Bound 3: unmanaged and BYOD endpoints.** A machine that is neither AD-joined nor Microsoft Intune-managed has no LAPS policy applied to it. Personal-device BYO MAM scope is outside the LAPS protection model entirely. The fix for these endpoints is enrollment, not LAPS. A non-trivial portion of the residual local-admin-password risk in 2026 is concentrated on the long tail of unmanaged endpoints that exist precisely because management was politically or contractually infeasible. The protocol does not solve this; *governance* solves this.

**Bound 4: verification asymmetry.** The directory's audit log says what it *chose* to log. An unprivileged observer cannot verify enforcement from outside the directory. This is the structural ceiling that motivates external audit primitives -- PingCastle [@pingcastle-rules], BloodHound [@bloodhound-edge-readlaps], Defender for Identity [@ms-defender-alerts] -- because they sit outside the directory's own self-report. The bound cannot be closed inside the protocol; only an out-of-band attestation primitive can certify enforcement to a party that does not trust the directory.

> **Key idea:** Somebody has to break the glass. The decryptor group is the new tier-0 asset; LAPS bounds the problem, it does not abolish it. The eleven-year arc was a convergence on a tighter bound, not an arrival at a clean answer. The right framing for the 2026 baseline is "the residual attack surface is now the *actual* attack surface, rather than an artefact of incomplete shipping." That is real progress -- it just is not closure.

<Aside label="What an ideal solution would look like">
A structurally tighter design would have three properties: threshold cryptography so no single principal can decrypt (an $m$-of-$n$ Shamir secret-sharing scheme over the password protector, with $m \geq 2$ in tier-0 fleets); attestation-bound retrieval so the decryptor's device state is part of the decryption policy (Azure Managed HSM's secure-key-release policy grammar [@ms-mhsm-policy-grammar] is the closest shipping primitive that approaches this -- a key-release decision conditioned on attestation claims like `x-ms-attestation-type` or `tee:sevsnpvm`); and a ledger-of-reads so every retrieval is recorded on a tamper-evident substrate that the directory itself cannot rewrite (Azure Confidential Ledger [@ms-conf-ledger] is the closest shipping primitive on the Microsoft side). None of these three are wired into Windows LAPS in 2026. Each exists as an adjacent Microsoft product. The architectural integration -- a Windows LAPS that requires two `LAPS-DPAPI-Decryptors` members to co-sign a retrieval, attests the retrieving device's state at decryption time, and writes the retrieval event to an append-only ledger the directory cannot edit -- is engineering work that nobody has shipped.
</Aside>

Some of those structural bounds map onto open problems with no clean 2026 answer. We close on six of them.

## 10. Open Problems in 2026

Six open problems in local-admin password management for which no first-party Microsoft answer ships in 2026. Each is one paragraph, framed as "what is the question," "what has been tried," and "what is the current best partial result."

| Open question | What has been tried | Current best partial result |
|---|---|---|
| Legacy SYSVOL `cpassword` cleanup at scale | MS14-025 (UI disable, no remediation); PingCastle scanning; community `Get-GPPDeployedPasswords` | Third-party scan-and-manual-delete; no first-party cmdlet ships in the OS |
| Cross-tenant / cross-directory LAPS coverage report | Microsoft Intune compliance reports; manual `Get-LapsADPassword` and `Get-LapsAADPassword` joins | DIY KQL across two directories; no unified portal report |
| Hybrid-joined `BackupDirectory` ambiguity | Microsoft Learn guidance ("AD for hybrid") | Most shops configure both and reconcile downstream |
| Win 11 25H2 Administrator Protection and LAPS interaction | Tech Community guidance; Microsoft Learn architectural notes | Operate them as orthogonal, with no architectural integration |
| LDAP channel binding / signing enforcement migration | Microsoft KB4520412 enforcement push 2020-2024; cross-platform tool updates | Some Linux pentest tooling still incomplete; `bloodyAD` / `lapsv2decrypt` lead the field [@kb4520412-canonical] |
| Retrieval-event audit gap (cross-directory) | Event 4662 SACL via `Set-LapsADAuditing`; Entra audit log; Defender for Identity hunting | DIY KQL unification across AD + Entra; no unified audit pane |

**1. Legacy SYSVOL cpassword cleanup at scale.** MS14-025 disabled new authoring twelve years ago; it never deleted what it patched [@ms14-025-bulletin]. No first-party `Find-GPPPassword` or `Remove-GPPPassword` cmdlet ships in the OS in 2026. PingCastle's `A-PwdGPO` rule and Semperis Purple Knight's equivalent scanner fill the gap [@pingcastle-rules]. The 2026 answer is: scan with a third-party tool, rotate the discovered credentials in whatever account-management primitive owns them, then delete the XML. The open question is why Microsoft has not shipped this in the twelve years since the bulletin. The blast-radius argument from 2014 -- "we cannot risk auto-deleting policy XMLs from SYSVOL" -- is now strictly weaker than the cleanup-tail argument that the residual artefacts keep showing up on internal pentest reports a decade later.

**2. Cross-tenant and cross-directory LAPS coverage view.** No portal-level "every Entra-joined and every AD-joined device that does not have a current LAPS password" report exists. Microsoft Intune compliance reports help on the Intune-managed side; `Get-LapsADPassword -Identity *` covers the AD side; `Get-LapsAADPassword` covers the Entra side. There is no single pane that unifies them. The 2026 answer is custom KQL or PowerShell that joins the three result sets on a normalised device identifier. The bottleneck is identity: Intune device IDs, AD `objectGuid` values, and Entra `deviceId` values are three different surrogate keys, and a fleet's mapping table is its own engineering investment.

**3. Hybrid-joined `BackupDirectory` ambiguity.** Microsoft Learn's current guidance is that hybrid-joined devices should typically use `BackupDirectory = 2` (AD) when on-premises AD is the canonical identity store, and may use `BackupDirectory = 1` (Entra) when Intune is the primary policy-delivery mechanism [@ms-laps-entra-scenarios]. In practice, the documentation hedges, and many shops configure both directions (one via GPO, one via Intune CSP) and rely on the per-device evaluation order to pick one. The result is a coverage-verification problem: a device that is "configured for AD backup" by GPO and "configured for Entra backup" by CSP can end up with the password in either backend, and the source of truth depends on policy precedence rules most operators do not memorise.

**4. Windows 11 25H2 Administrator Protection and LAPS interaction.** Administrator Protection's per-elevation transient admin tokens and Windows LAPS's recoverable break-glass password are operationally adjacent but architecturally disjoint [@tc-admin-protection-win11]. The documentation covers each feature on its own; the interaction matrix -- "what does a LAPS-managed RID 500 look like under Administrator Protection on a Win 11 25H2 host" -- is not laid out in one place. Tier-0 architects who want both behaviours have to assemble the answer from two product pages.

**5. LDAP channel binding and signing enforcement migration.** Microsoft has been hardening LDAP channel binding through a multi-year 2020-2024 enforcement push tracked under KB4520412 [@kb4520412-canonical]. The original March 10, 2020 update introduced Channel Binding Token (CBT) signing events 3039, 3040, and 3041; the manual enablement step was removed on November 14, 2023 for Windows Server 2022 and on January 9, 2024 for Windows Server 2019, after which the hardening became the default posture; starting with Windows Server 2022 23H2, all new versions ship with the full set of changes in the KB applied [@kb4520412-canonical]. Tooling that does not speak LDAPS-with-channel-binding will break when enforcement reaches its terminal state. Modern attack-graph tooling -- `bloodyAD` [@bloodyad-repo] and the `lapsv2decrypt` reference implementation [@lapsv2decrypt-repo] -- has tracked the changes. Not every Linux pentest stack has. Practitioners building Linux-based LAPS retrieval pipelines should validate their stack against the channel-binding-required posture before the enforcement wave reaches them.

**6. The retrieval-event audit gap (cross-directory).** Active Directory does not natively log every read of `msLAPS-EncryptedPassword`; `Set-LapsADAuditing` installs a SACL that emits Directory Service event 4662 for configured attribute reads [@ms-laps-set-adauditing]. Microsoft Entra ID logs LAPS retrieval through its own audit log, surfaced via the Graph endpoint [@ms-graph-localcredinfo]. The two log streams have different schemas, different timestamp normalisations, and different principal identifiers. Cross-pane unification of "who read which LAPS password when" across both backends is a DIY engineering problem in 2026. Microsoft Defender for Identity surfaces some of the AD-side reads under the Compromised Credentials and Lateral Movement categories [@ms-defender-alerts] but does not name LAPS specifically in the public alert taxonomy.

<Sidenote>The threshold-cryptography open problem (an $m$-of-$n$ Shamir scheme over the LAPS password protector, with $m \geq 2$ in tier-0 fleets) is theoretically closed by the 1979 Shamir secret-sharing construction. The deployment-side block is that no Microsoft-shipped primitive wires the construction to the LAPS rotation pipeline. Adjacent shipping primitives (Azure Managed HSM key-release [@ms-mhsm-policy-grammar], Azure Confidential Ledger [@ms-conf-ledger]) exist on the Azure side, but the integration with on-premises LAPS clients is not on any public roadmap. The companion posts on DPAPI internals (#20) and Defender for Identity (#87) cover adjacent territory but do not close this gap.</Sidenote>

None of those six dissolves the architectural lesson the eleven-year arc taught: the right defaults take a decade to ship. Here is the practitioner field manual for the meantime.

## 11. Practitioner Field Manual and FAQ

What follows is a seven-step deployment list, three named sidebars that surface the most common misconceptions, and a seven-question FAQ. Lift the step list verbatim into your deployment runbook; the sidebars exist because the article would not be defensible without them.

### The audit-and-migrate seven-step list

1. **Audit SYSVOL for `cpassword` first.** Run PingCastle's `A-PwdGPO` (MITRE T1552.006) [@pingcastle-rules; @mitre-t1552-006] before touching anything else. A Windows triage one-liner -- `findstr /s /i cpassword \\domain\SYSVOL\*.xml` -- will land on most environments in under a minute. Remediate the discovered XML files (rotate the underlying account passwords, then delete the XMLs) before deploying Windows LAPS so the attack surface and the defence are not co-evolving in the same window.
2. **Extend the AD schema for Windows LAPS.** Run `Update-LapsADSchema` once per forest from a Domain Admin context. The cmdlet is idempotent and coexists with the legacy `ms-Mcs-AdmPwd` attribute on the same `Computer` object [@ms-laps-mig-scenarios].
3. **Delegate.** Run `Set-LapsADComputerSelfPermission` on each target OU so that computer accounts can write their own `msLAPS-*` attributes. Audit existing "All Extended Rights" delegations with `Find-LapsADExtendedRights` and remove any that do not have an explicit operational justification [@ms-laps-ps-overview]. This is the legacy-LAPS lesson applied to the new attribute set.
4. **Configure encryption-at-rest.** Verify that the forest's Domain Functional Level is Windows Server 2016 or higher. Configure `ADPasswordEncryptionEnabled = 1` *explicitly* even though the default is True -- the explicit configuration makes the choice visible in policy audits and forces the operator to verify the DFL prerequisite [@ms-laps-policy-settings]. Assign `ADPasswordEncryptionPrincipal` to a dedicated `LAPS-DPAPI-Decryptors` group, not Domain Admins [@ms-laps-concepts-overview].
5. **Deploy policy.** GPO for AD-joined, Intune CSP for Entra-joined and hybrid-joined [@ms-laps-csp]. Settings as per section 7's baseline table. Validate via `Get-LapsADPassword -Identity <computer>` against a representative sample of hosts after the first one-hour rotation timer has fired [@ms-laps-get-adpassword].
6. **Migrate from legacy LAPS.** Use the documented coexistence pattern: the legacy MSI's CSE keeps running against the built-in RID 500, the new in-box LAPS takes over against a named secondary local-admin account, then retire the legacy `ms-Mcs-AdmPwd` schema readers and uninstall the MSI once Windows LAPS coverage is verified [@ms-laps-mig-scenarios]. The legacy MSI's installation is blocked on Windows 11 23H2 and later [@ms-laps-msi-download].
7. **Continuous audit.** PingCastle for coverage rules (`A-LAPS-Not-Installed`, `A-LAPS-Joined-Computers`, and the GPP `A-PwdGPO`) [@pingcastle-rules]; BloodHound for the `ReadLAPSPassword` edge across the graph [@bloodhound-edge-readlaps]; Defender for Identity for downstream behaviour under Compromised Credentials and Lateral Movement [@ms-defender-alerts]; and a custom KQL on the Entra audit log for `LapsPasswordRetrieved` events. None of these is optional in a deployment that intends to detect compromise.

### Sidebar A: MS16-072 is NOT the LAPS attribute-readability bulletin

A recurring misattribution credits MS16-072 / KB3163622 / CVE-2016-3223 (June 14, 2016) [@ms16-072-bulletin; @ms16-072-kb; @cve-2016-3223] with closing the legacy LAPS attribute-readability issue. It does not. MS16-072 is a Group Policy retrieval-context fix: it moved user-side GPO fetch into the *computer's* security context to defeat a man-in-the-middle class on policy traffic. The actual LAPS attribute-readability issue -- "All Extended Rights" delegations silently including `CONTROL_ACCESS` on the CONFIDENTIAL `ms-Mcs-AdmPwd` attribute -- has no Microsoft-assigned CVE or bulletin. The canonical write-up is Sean Metcalf's August 2016 ADSecurity piece [@adsec-laps-2016], and the operational primitive is SpecterOps's `ReadLAPSPassword` BloodHound edge [@bloodhound-edge-readlaps].

### Sidebar B: "Hybrid joined" is not "Hybrid Worker"

Microsoft Entra *hybrid joined* devices are workstations joined to both an on-premises AD domain and Microsoft Entra ID. The LAPS conversation about hybrid joined is a `BackupDirectory` choice. Microsoft Entra *hybrid runbook workers*, on the other hand, are an Azure Automation primitive -- worker processes that execute Automation runbooks against on-premises resources. They share a word and nothing else. A LAPS policy targeted at "hybrid devices" means hybrid joined; it has nothing to do with hybrid runbook workers. The article's section 8 includes the same disambiguation because operators conflate them with surprising frequency.

### Sidebar C: How GPP cpassword still gets found in 2026

MS14-025 disabled new authoring but did not delete the artefacts [@ms14-025-bulletin]. The artefacts persist because SYSVOL replication is conservative -- nothing in the forest's design *deletes* anything from SYSVOL just because the editor UI was hot-patched on the administrative workstation. A fresh PingCastle scan against a long-lived forest will routinely surface 2010-era `Groups.xml` files [@pingcastle-rules], and the third-party scanner cohort is the only practical defence. The one-shot remediation pattern is: find with `A-PwdGPO`, rotate the underlying password via the replacement tool (Windows LAPS for built-in local admin; a PAM vault for service accounts that were stored in GPP), then delete the `Groups.xml` and let SYSVOL replication propagate the deletion.

<FAQ title="Frequently asked questions">

<FAQItem question="Does Windows 11 25H2 Administrator Protection replace LAPS?">
No. Administrator Protection addresses in-session UAC-class elevation by brokering each elevation through a per-elevation transient shadow-admin identity [@tc-admin-protection-win11]; it does not provide a recoverable break-glass password for an off-network or non-bootable endpoint. The two systems are orthogonal and Microsoft recommends running them together on Windows 11 25H2 fleets. Replacing LAPS with Administrator Protection produces designs that lose the recovery primitive for laptops that have wandered off the corporate network for a year.
</FAQItem>

<FAQItem question="If I encrypt with DPAPI-NG, why do I still need to delegate the AD ACL tightly?">
Defence in depth, plus a coverage-leak primitive. An LDAP reader who is not in `ADPasswordEncryptionPrincipal` gets only an opaque ciphertext blob [@ms-laps-concepts-overview] -- but the same reader can still enumerate which computer objects have a current `msLAPS-EncryptedPassword`, which gives them target-selection telemetry on managed-versus-unmanaged hosts. The canonical write-up of this class is Sean Metcalf's August 2016 ADSecurity piece on the legacy `ms-Mcs-AdmPwdExpirationTime` attribute [@adsec-laps-2016], and the architectural lesson carries forward to Windows LAPS unchanged.
</FAQItem>

<FAQItem question="Can attackers still decrypt cpassword in 2026?">
Yes, in seconds. The 32-byte AES-256-CBC key is published verbatim in `[MS-GPPREF]` section 2.2.1.1.4 of Microsoft's Open Specifications corpus [@ms-gppref-aes-key] and that publication is permanent under the Open Specifications Promise. Any residual `Groups.xml` (or five sibling carriers including the asymmetric `Printers.xml` [@rewtdance-gpp-2012]) in SYSVOL that contains a `cpassword` attribute is operationally plaintext. The 2026 answer is to find them with PingCastle's `A-PwdGPO` rule [@pingcastle-rules] and remediate -- not to expect the artefacts to expire on their own.
</FAQItem>

<FAQItem question="Will Windows LAPS rotate the password on every login?">
No. The rotation cycle is the `PasswordAgeDays` interval (default 30 days, minimum 1 on AD backup, minimum 7 on Entra backup) [@ms-laps-policy-settings]. After authentication, `PostAuthenticationActions` (default `3` = reset + sign out) fires once the `PostAuthenticationResetDelay` window (default 24 hours) has elapsed. Value `11` (Windows 11 24H2 / Server 2025+) adds termination of remaining processes; it is *not* a forced shutdown without warning -- the standard two-minute warning still applies and SMB sessions are deleted.
</FAQItem>

<FAQItem question="Does LAPS work for the built-in Administrator (RID 500) when the account is disabled?">
Yes. LAPS rotates the password on a disabled account; the account simply cannot be used to log on until it is enabled. The break-glass runbook is: enable the account, retrieve the LAPS password, perform the recovery, rotate immediately, re-disable. On Windows 11 24H2 and Windows Server 2025 and later, Microsoft's recommendation is to enable Automatic Account Management with a randomised name and `AutomaticAccountManagementEnableAccount = 0` so the managed account ships disabled-by-default with a non-predictable name [@ms-laps-account-modes]. The pattern defeats predictable-RID-500 enumeration entirely.
</FAQItem>

<FAQItem question="Where does the password go for an Entra-joined device with no on-prem AD?">
Microsoft Entra ID. With `BackupDirectory = 1` [@ms-laps-policy-settings], the local LAPS component posts the rotated password to the `deviceLocalCredentials` resource on the Entra device object via Microsoft Graph [@ms-graph-localcredinfo]. Retrieval is via `Get-LapsAADPassword` (a wrapper around the Graph endpoint), the Microsoft Entra portal Devices blade, or a direct `GET /directory/deviceLocalCredentials/{deviceId}` call [@ms-laps-entra-scenarios]. Read permission requires the Cloud Device Administrator or Intune Service Administrator Entra role.
</FAQItem>

<FAQItem question="Is the BloodHound LAPS edge called CanReadGMSAPassword?">
No. `CanReadGMSAPassword` is the edge for **Group Managed Service Accounts** -- a different Active Directory feature with a different ACL on a different attribute (`msDS-GroupMSAMembership`). The correct LAPS edge is **`ReadLAPSPassword`**, introduced in BloodHound 2.0 on August 7, 2018 [@specterops-bh2], and the current edge documentation covers both the legacy `ms-Mcs-AdmPwd` and the modern `msLAPS-*` attribute paths [@bloodhound-edge-readlaps].
</FAQItem>

</FAQ>

<MarginNote>The companion posts in this series cover Pass-the-Hash itself (#76), DPAPI internals (#20), Microsoft Entra Privileged Identity Management (#90), Active Directory tiering (#72), Microsoft Defender for Identity (#87), and BloodHound (#77). Each of those is referenced in this article at the point where the topic would otherwise demand a digression; each has its own deep treatment elsewhere.</MarginNote>

Twenty years. Eleven years of which separated Microsoft's December 2012 articulation of the architecture from the April 11, 2023 in-box default [@ms-pth-whitepaper; @tc-windows-laps-ga-2023]. Four residual attack surfaces -- delegated-decryptor compromise, the pre-rotation OPSEC tail, BYOD endpoints, and the multi-decade MS14-025 cleanup tail [@ms14-025-bulletin] -- still resist the architecture rather than fall to it. One through-line: this is what shipping the right default a decade late looks like. The right defaults are now in the box. The directory is still tier 0. Somebody still has to break the glass. The architectural game from here is not to invent a new generation; it is to make sure the one we finally have is actually deployed, audited, and clean.
