A security researcher publicly released a working proof-of-concept exploit for CVE-2026-45585, a vulnerability that lets attackers bypass BitLocker on Windows 11 using a USB drive. Microsoft confirmed the flaw, published interim mitigation guidance, and accused the researcher of violating responsible disclosure best practices. The researcher responded publicly, claiming Microsoft deleted their MSRC reporting account without explanation.

Here is what the vulnerability does, who is at risk, how to apply the fix, and what happened between Microsoft and the researcher.
How CVE-2026-45585 Bypasses BitLocker Using WinRE
CVE-2026-45585 is a Security Feature Bypass vulnerability in the Windows Recovery Environment (WinRE). The researcher who discovered it, using the handle Nightmare-Eclipse, named the exploit “YellowKey.”
An attacker with physical access to a device can plug in a USB drive containing an FsTx folder and boot the machine into WinRE. Inside the recovery environment, a malicious executable called autofstx.exe runs through the BootExecute registry value very early in the boot process, before the operating system fully loads. Because this execution happens before BitLocker’s full verification runs, the attacker gains read and write access to encrypted data on the system storage device.
No password and no MFA bypass are needed. Physical access and the right USB drive are sufficient.
Microsoft classified the vulnerability as Important with a CVSS 3.1 score of 6.8. The attack vector is Physical, attack complexity is Low, and no privileges or user interaction are required. The underlying weakness is CWE-77 (Improper Neutralization of Special Elements used in a Command, or Command Injection).
Nightmare-Eclipse also disclosed a separate vulnerability called “MiniPlasma” around the same time. MiniPlasma lets threat actors plant malicious Registry modifications on a target system. That flaw is tracked and handled independently.
Which Windows Versions Are Affected
Microsoft released CVE-2026-45585 on May 19, 2026. The following versions are confirmed affected:
- Windows 11 Version 24H2 (x64-based Systems)
- Windows 11 Version 25H2 (x64-based Systems)
- Windows 11 Version 26H1 (x64-based Systems)
- Windows Server 2025
- Windows Server 2025 (Server Core installation)
No security update patch is available yet. Microsoft is providing only an interim mitigation script while a full fix is in development.
Are You at Risk From the YellowKey BitLocker Attack
Your exposure depends on how BitLocker is configured on your device.
If you use TPM+PIN, you are not vulnerable. Microsoft confirmed in its official advisory that TPM+PIN configurations block this exploit entirely.
If you use TPM-only, which is the default on most consumer laptops and many enterprise devices, your device is at risk whenever an attacker can physically access it. The threat is highest for employees who take work laptops home or travel with them. Devices that stay in a locked, controlled environment face much lower practical risk, but the vulnerability is still present.
If you are unsure which BitLocker configuration you use, open PowerShell as Administrator and run:
manage-bde -protectors -get C:If the output shows TPM And PIN, you are protected. If it shows only TPM, your device is affected.
How to Apply Microsoft’s Interim Fix
Microsoft published a PowerShell script as an official interim mitigation. The script removes autofstx.exe from the BootExecute registry value inside the WinRE image. This blocks the malicious executable from running during recovery boot.
Applying the mitigation does not impact service availability or management operations. When Microsoft releases a full security update, you do not need to revert the script’s changes. The patch will preserve the mitigation automatically.
Requirements: Run PowerShell as Administrator on a system where WinRE is enabled.
Save the script below as Remove-AutoFsTxFromWinRE.ps1. You can also copy the official version directly from the CVE-2026-45585 MSRC advisory.
<#
.SYNOPSIS
Removes autofstx.exe from the WinRE BootExecute registry value.
.DESCRIPTION
This remediation script removes the "autofstx.exe" entry from the BootExecute
REG_MULTI_SZ value inside the Windows Recovery Environment (WinRE) offline
SYSTEM registry hive. This is a security fix to prevent autofstx.exe from
executing during WinRE boot.
The script performs the following steps:
1. Verify administrator privileges
2. Verify WinRE is enabled
3. Mount the WinRE image via reagentc
4. Load the offline SYSTEM registry hive
5. Read BootExecute and remove autofstx.exe if present
6. Unload the offline hive
7. Unmount the WinRE image with commit
8. Disable and re-enable WinRE to re-seal BitLocker trust chain
Exit 0 = Success (entry removed or not present)
Exit 1 = Failure (error during remediation)
.PARAMETER MountPath
Directory to use as the WinRE mount point. Created if it does not exist.
Default: C:\Mount
.EXAMPLE
# Standard run
.\Remove-AutoFsTxFromWinRE.ps1
.EXAMPLE
# Custom mount path
.\Remove-AutoFsTxFromWinRE.ps1 -MountPath D:\mount
.NOTES
Requirements: Windows with WinRE and reagentc support, Administrator privileges.
The WinRE disable/enable cycle at the end is required to re-seal the
BitLocker measurement chain after modifying the WinRE image.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
#>
param(
[Parameter(Mandatory = $false)]
[string]$MountPath = "C:\Mount"
)
# Target entry to remove from BootExecute
$EntryToRemove = "autofstx.exe"
# Internal constant for the offline hive key name
$HiveName = "WinREHive"
# State tracking for cleanup
$hiveLoaded = $false
$imageMounted = $false
$mountCreated = $false
$changesMade = $false
Write-Host "Remove autofstx.exe from WinRE BootExecute"
# 1. Verify Administrator Privileges
try {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]$identity
$isAdmin = $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
Write-Host "[1/8] Administrator check: FAILED" -ForegroundColor Red
Write-Host " This script must be run as Administrator."
Write-Host " Right-click PowerShell and select 'Run as administrator'."
exit 1
}
Write-Host "[1/8] Administrator check: Passed" -ForegroundColor Green
} catch {
Write-Warning "Error checking administrator privileges: $_"
exit 1
}
# 2. Check WinRE Status
try {
$winreOutput = & reagentc /info 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "[2/8] WinRE status check: FAILED" -ForegroundColor Red
Write-Warning "reagentc /info returned exit code $LASTEXITCODE"
exit 1
}
$winreOutputStr = $winreOutput -join "`n"
if ($winreOutputStr -match "[::]\s*Enabled\b") {
Write-Host "[2/8] WinRE status: Enabled" -ForegroundColor Green
} else {
Write-Host "[2/8] WinRE status: NOT ENABLED. Exiting." -ForegroundColor Green
exit 0
}
} catch {
Write-Warning "Error checking WinRE status: $_"
exit 1
}
# 3. Mount WinRE Image
try {
if (-not (Test-Path $MountPath)) {
New-Item -ItemType Directory -Path $MountPath -Force | Out-Null
$mountCreated = $true
Write-Host "[3/8] Created mount directory: $MountPath"
} else {
$existing = Get-ChildItem -Path $MountPath -Force -ErrorAction SilentlyContinue
if ($existing) {
Write-Host "[3/8] Mount WinRE image: FAILED" -ForegroundColor Red
Write-Host " Mount directory $MountPath is not empty."
Write-Host " Clean it or specify a different -MountPath."
exit 1
}
}
$mountOutput = & reagentc /mountre /path $MountPath 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "[3/8] Mount WinRE image: FAILED" -ForegroundColor Red
Write-Warning "reagentc /mountre output: $mountOutput"
exit 1
}
$imageMounted = $true
Write-Host "[3/8] WinRE image mounted: $MountPath" -ForegroundColor Green
} catch {
Write-Warning "Error mounting WinRE image: $_"
exit 1
}
# 4. Load Offline SYSTEM Registry Hive
try {
$hivePath = $null
$hiveCandidates = @(
"$MountPath\Windows\System32\config\SYSTEM",
"$MountPath\windows\system32\config\SYSTEM"
)
foreach ($candidate in $hiveCandidates) {
if (Test-Path $candidate) {
$hivePath = $candidate
break
}
}
if (-not $hivePath) {
$found = Get-ChildItem -Path $MountPath -Recurse -Filter "SYSTEM" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -match "config\\SYSTEM$" } |
Select-Object -First 1
if ($found) {
$hivePath = $found.FullName
}
}
if (-not $hivePath) {
Write-Host "[4/8] Load offline hive: FAILED" -ForegroundColor Red
Write-Warning "Cannot locate SYSTEM hive in mounted WinRE image."
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
exit 1
}
Write-Host "[4/8] Found SYSTEM hive: $hivePath"
$loadOutput = & reg load "HKLM\$HiveName" $hivePath 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "[4/8] Load offline hive: FAILED" -ForegroundColor Red
Write-Warning "reg load output: $loadOutput"
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
exit 1
}
$hiveLoaded = $true
Write-Host "[4/8] Hive loaded as HKLM\$HiveName" -ForegroundColor Green
} catch {
Write-Warning "Error loading offline hive: $_"
if ($imageMounted) {
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
}
exit 1
}
# 5. Read BootExecute and Remove autofstx.exe
try {
$selectPath = "Registry::HKEY_LOCAL_MACHINE\$HiveName\Select"
$selectProps = Get-ItemProperty -Path $selectPath -ErrorAction SilentlyContinue
if ($selectProps -and $selectProps.Current) {
$csNumbers = @($selectProps.Current)
if ($selectProps.Default -and $selectProps.Default -ne $selectProps.Current) {
$csNumbers += $selectProps.Default
}
$controlSets = $csNumbers | ForEach-Object { "ControlSet{0:D3}" -f [int]$_ }
Write-Host "[5/8] Active ControlSets (from Select key): $($controlSets -join ', ')"
} else {
$controlSets = @("ControlSet001")
Write-Host "[5/8] Select key not readable, falling back to ControlSet001"
}
$foundEntry = $false
foreach ($cs in $controlSets) {
$regPath = "Registry::HKEY_LOCAL_MACHINE\$HiveName\$cs\Control\Session Manager"
$testResult = Get-ItemProperty -Path $regPath -Name "BootExecute" -ErrorAction SilentlyContinue
if (-not $testResult) {
Write-Host " $cs\Session Manager\BootExecute: not found, skipping"
continue
}
$currentValue = $testResult.BootExecute
if (-not $currentValue) {
Write-Host " $cs BootExecute: (empty)"
continue
}
$updatedValue = @($currentValue | Where-Object {
$_ -and
($_ -ne $EntryToRemove) -and
($_ -notmatch "^\s*$([regex]::Escape($EntryToRemove))\s*$")
})
if ($updatedValue.Count -eq @($currentValue).Count) {
Write-Host " $cs BootExecute: '$EntryToRemove' not present"
continue
}
Set-ItemProperty -Path $regPath -Name "BootExecute" -Value $updatedValue
$foundEntry = $true
Write-Host " $cs BootExecute: removed '$EntryToRemove'" -ForegroundColor Green
$verifyValue = (Get-ItemProperty -Path $regPath -Name "BootExecute" -ErrorAction Stop).BootExecute
Write-Host " $cs verification: $($verifyValue -join '; ')"
}
if (-not $foundEntry) {
Write-Host "[5/8] '$EntryToRemove' not found in any active ControlSet. No changes needed." -ForegroundColor Green
[gc]::Collect()
Start-Sleep -Seconds 1
$null = & reg unload "HKLM\$HiveName" 2>&1
$hiveLoaded = $false
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
if ($mountCreated) { Remove-Item -Path $MountPath -Recurse -Force -ErrorAction SilentlyContinue }
exit 0
}
$changesMade = $true
Write-Host "[5/8] Removed '$EntryToRemove' from BootExecute" -ForegroundColor Green
} catch {
Write-Warning "Error modifying BootExecute: $_"
[gc]::Collect()
Start-Sleep -Seconds 2
if ($hiveLoaded) {
$null = & reg unload "HKLM\$HiveName" 2>&1
$hiveLoaded = $false
}
if ($imageMounted) {
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
}
exit 1
}
# 6. Unload Offline Registry Hive
try {
[gc]::Collect()
Start-Sleep -Seconds 2
$unloadOutput = & reg unload "HKLM\$HiveName" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Warning "First unload attempt failed, retrying..."
[gc]::Collect()
Start-Sleep -Seconds 3
$unloadOutput = & reg unload "HKLM\$HiveName" 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "[6/8] Unload hive: FAILED" -ForegroundColor Red
Write-Warning "reg unload output: $unloadOutput"
Write-Host " Close any Registry Editor windows and retry."
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
exit 1
}
}
$hiveLoaded = $false
Write-Host "[6/8] Offline hive unloaded" -ForegroundColor Green
} catch {
Write-Warning "Error unloading hive: $_"
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
$imageMounted = $false
exit 1
}
# 7. Unmount WinRE Image with Commit
try {
if ($changesMade) {
$unmountOutput = & reagentc /unmountre /path $MountPath /commit 2>&1
} else {
$unmountOutput = & reagentc /unmountre /path $MountPath /discard 2>&1
}
if ($LASTEXITCODE -ne 0) {
Write-Host "[7/8] Unmount WinRE: FAILED" -ForegroundColor Red
Write-Warning "reagentc /unmountre output: $unmountOutput"
if ($changesMade) {
Write-Host " Attempting discard to avoid leaving image in broken state..."
$null = & reagentc /unmountre /path $MountPath /discard 2>&1
}
$imageMounted = $false
exit 1
}
$imageMounted = $false
if ($changesMade) {
Write-Host "[7/8] WinRE image unmounted and committed" -ForegroundColor Green
} else {
Write-Host "[7/8] WinRE image unmounted (no changes)" -ForegroundColor Green
}
} catch {
Write-Warning "Error unmounting WinRE image: $_"
exit 1
}
# 8. Re-seal WinRE (Disable + Enable Cycle for BitLocker Trust Chain)
try {
if (-not $changesMade) {
Write-Host "[8/8] Re-seal WinRE: Skipped (no changes made)" -ForegroundColor Green
} else {
$disableOutput = & reagentc /disable 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Warning "reagentc /disable returned non-zero: $disableOutput"
} else {
Write-Host " WinRE disabled."
}
$enableOutput = & reagentc /enable 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "[8/8] Re-seal WinRE: FAILED" -ForegroundColor Red
Write-Warning "reagentc /enable output: $enableOutput"
Write-Host " WinRE may need manual recovery. Run: reagentc /enable"
exit 1
}
Write-Host "[8/8] WinRE re-sealed (disable + enable cycle)" -ForegroundColor Green
}
} catch {
Write-Warning "Error during WinRE re-seal: $_"
Write-Host " Run manually: reagentc /enable"
exit 1
}
Write-Host ""
Write-Host " COMPLETE: '$EntryToRemove' removed from WinRE BootExecute" -ForegroundColor Green
# Cleanup: remove mount directory if we created it
if ($mountCreated -and (Test-Path $MountPath)) {
Remove-Item -Path $MountPath -Recurse -Force -ErrorAction SilentlyContinue
}
exit 0Open PowerShell as Administrator and run:
.\Remove-AutoFsTxFromWinRE.ps1To use a custom mount path instead of the default C:\Mount:
.\Remove-AutoFsTxFromWinRE.ps1 -MountPath D:\mountThe script runs through eight steps automatically:
- Verifies that you are running as Administrator
- Confirms WinRE is enabled on the device using
reagentc /info - Creates the mount directory and mounts the WinRE image using
reagentc /mountre - Locates and loads the offline SYSTEM registry hive from the mounted WinRE image
- Reads the
BootExecutevalue across all active ControlSets and removesautofstx.exeif present - Unloads the offline registry hive cleanly
- Unmounts the WinRE image and commits changes using
reagentc /unmountre /commit - Runs a disable and re-enable cycle on WinRE to re-seal the BitLocker trust chain
If autofstx.exe is not present in your WinRE image, the script exits at step 5 without making any changes. A green COMPLETE message in the terminal confirms success.
Microsoft Blamed the Researcher. The Researcher Blamed Microsoft Back.
After Nightmare-Eclipse publicly released the YellowKey proof-of-concept, Microsoft included a pointed statement in its CVE advisory: the PoC publication violated coordinated vulnerability disclosure (CVD) best practices.
The researcher responded directly on their public blog, pushing responsibility back onto Microsoft. According to the researcher, Microsoft first revoked their access to the MSRC account they used to report vulnerabilities, then wiped the account completely when they asked for an explanation. Multiple follow-up requests to MSRC leadership went unanswered. The researcher described Microsoft’s public accusation as a defamation of their personal reputation and stated they are taking the statement personally.
Microsoft has not publicly addressed the researcher’s account of events.
This dispute highlights a recurring tension in security research. When a vendor cuts off a researcher’s disclosure channel without explanation, the researcher loses the normal path for coordinated disclosure. Public release of a PoC becomes the only remaining leverage. Whether that justifies publication is a genuinely contested question in the security community, but the sequence of events matters when assigning responsibility.
