Short answer: run .\Get-SecureBootCertStatus.ps1 -ComputerName (Get-Content .\servers.txt) -CsvPath .\secureboot.csv from an elevated PowerShell. For each computer it checks that Secure Boot is on (Confirm-SecureBootUEFI), whether the 2023 Microsoft certificates are in DB and KEK (Get-SecureBootUEFI), and reads the servicing values Windows keeps for the update, mainly UEFICA2023Status (NotStarted, InProgress or Updated) under HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing. It changes nothing.
We ran this script on 6 October 2026 on a Windows Server 2025 Standard domain controller (build 26100.33438, September 2026 update, Windows PowerShell 5.1) and a Windows 11 Pro member PC in our lab domain contoso.com. The example output below is from that run; the lab domain is small and new, so your numbers will be bigger. It was also syntax-checked with PowerShell 7.4.6 and PSScriptAnalyzer 1.25.
Table of Contents
What it does
Microsoft’s 2011 Secure Boot certificates expire during 2026 and are being replaced by 2023 certificates: Windows UEFI CA 2023, Microsoft UEFI CA 2023 and Microsoft Option ROM UEFI CA 2023 in the DB, and Microsoft Corporation KEK 2K CA 2023 in the KEK. Windows tracks its progress in the registry and in the System event log. Checking that by hand on one PC is easy; on 200 servers it is not. The script collects, per computer:
| Check | Source |
|---|---|
| Secure Boot on? | Confirm-SecureBootUEFI, falling back to ...\SecureBoot\State\UEFISecureBootEnabled |
| 2023 certificates in DB | Get-SecureBootUEFI db, bytes decoded as ASCII and searched for the certificate names |
| 2023 KEK present | Get-SecureBootUEFI KEK, searched for “Microsoft Corporation KEK 2K CA 2023” |
| Update status | UEFICA2023Status, UEFICA2023Error, UEFICA2023ErrorEvent under ...\SecureBoot\Servicing |
| Rollout settings | AvailableUpdates (as hex), HighConfidenceOptOut, MicrosoftUpdateManagedOptIn under ...\SecureBoot; ConfidenceLevel under ...\Servicing |
| Latest event | Newest System log event 1801 (new certificates not yet applied) or 1808 (device has the new certificates), plus its BucketConfidenceLevel text |
| Hardware | OEM manufacturer, model, firmware version and date from ...\Servicing\DeviceAttributes |
The DB check is the method Microsoft uses in its boot manager guidance: [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match 'Windows UEFI CA 2023'. The Assessment column sums it up: Updated when UEFICA2023Status is Updated, Secure Boot off, Unreachable, or Action needed with what is missing (for example “KEK: KEK 2K CA 2023; Status: InProgress”).
Requirements
- Windows PowerShell 5.1 or PowerShell 7, run as Administrator:
Get-SecureBootUEFIneeds elevation, and without it the DB/KEK columns stay empty. - UEFI firmware. On legacy BIOS systems
Confirm-SecureBootUEFIfails and the row shows Secure Boot as unknown or off. - Windows updates from 11 November 2025 or later on each computer: Microsoft added the Servicing registry values in those updates. Older systems still get the DB/KEK and event checks.
- For
-ComputerName: PowerShell remoting (WinRM) enabled on the targets, and an account that is a local administrator there. Domain controllers and servers have remoting on by default since Windows Server 2012; client PCs usually need it enabled by Group Policy.
Download and first run
- Copy the script from the box on this page (or use the download button) and save it as
C:\Scripts\Get-SecureBootCertStatus.ps1. - If you downloaded the file, clear the “downloaded from the internet” mark so the execution policy lets it run:
Unblock-File C:\Scripts\Get-SecureBootCertStatus.ps1. - Read the built-in help, then run it once interactively and look at the result on screen before you export or schedule anything.
cd C:\Scripts
Get-Help .\Get-SecureBootCertStatus.ps1 -Full
# This computer
.\Get-SecureBootCertStatus.ps1
# A list of servers
.\Get-SecureBootCertStatus.ps1 -ComputerName (Get-Content C:\Scripts\servers.txt) -CsvPath C:\Reports\secureboot.csv
Options
| Parameter | What it does | Default |
|---|---|---|
-ComputerName | Computers to check through Invoke-Command | This computer |
-Credential | Credential for the remote computers | Current user |
-ThrottleLimit | Parallel remote connections (1 to 256) | 32 |
-CsvPath | Write the result to CSV | Screen only |
-PassThru | Send the objects down the pipeline | Off |
Usage examples
# All servers in AD
.\Get-SecureBootCertStatus.ps1 -ComputerName (Get-ADComputer -Filter 'OperatingSystem -like "*Server*"').DNSHostName -CsvPath C:\Reports\secureboot.csv
# Only the ones that still need work
.\Get-SecureBootCertStatus.ps1 -ComputerName HV01,HV02,FS01 -PassThru | Where-Object Assessment -ne 'Updated'
# Count by status per hardware model
.\Get-SecureBootCertStatus.ps1 -ComputerName (Get-Content .\pcs.txt) -PassThru |
Group-Object Model, UEFICA2023Status | Select-Object Count, Name
The Get-ADComputer example needs the ActiveDirectory module; see Install RSAT on Windows 11.
CSV columns
The example output further down is from our lab run. Columns:
| Column | Meaning |
|---|---|
| ComputerName, OS | Computer name and OS caption |
| SecureBootEnabled | True, False, or empty if it could not be read |
| Assessment | Updated, Secure Boot off, Unreachable, or Action needed: … |
| DB_WindowsUEFICA2023, DB_MicrosoftUEFICA2023, DB_OptionROMUEFICA2023 | True if the certificate name is found in DB |
| KEK_2023 | True if Microsoft Corporation KEK 2K CA 2023 is in KEK |
| UEFICA2023Status, UEFICA2023Error, UEFICA2023ErrorEvent | Servicing status; error code (0 on success) and the event ID Windows used to report an error |
| WindowsUEFICA2023Capable | Reference value (0, 1, 2); Microsoft says not to use it for status |
| AvailableUpdates | Pending update bits, as hex (for example 0x5944 when all updates were requested) |
| HighConfidenceOptOut, MicrosoftUpdateManagedOptIn, ConfidenceLevel | Rollout opt-out/opt-in and the device’s bucket confidence |
| LastEventId, LastEventTime, EventBucketConfidence | Newest 1801 or 1808 event and its BucketConfidenceLevel line |
| Manufacturer, Model, FirmwareVersion, FirmwareReleaseDate | From Servicing\DeviceAttributes |
| Notes | Why something could not be read (not elevated, no Servicing values, event log error) |
Example output
Our lab DC is a KVM virtual machine with Secure Boot turned off, which is a common case on hosted VPS servers. The CSV row, as a list:
ComputerName : WINSRV
OS : Microsoft Windows Server 2025 Standard
SecureBootEnabled : False
Assessment : Secure Boot off
UEFICA2023Status : InProgress
UEFICA2023Error : 2147946825
UEFICA2023ErrorEvent : 1796
AvailableUpdates : 0x5944
ConfidenceLevel : High Confidence
LastEventId : 1801
Manufacturer : QEMU
Model : Standard PC (i440FX + PIIX, 1996)
Windows Update had already queued the certificate update (AvailableUpdates 0x5944), but every step failed with event 1796, “Secure Boot is not enabled on this machine”. On a machine like this the expiring certificates do not matter until you turn Secure Boot on; if you do, apply the update first.
Schedule it
Run it weekly during the rollout so you can watch devices move from NotStarted to Updated. The account needs local admin rights on every target, so use a dedicated account or a gMSA (see our gMSA guide).
$action = New-ScheduledTaskAction -Execute 'powershell.exe' `
-Argument '-NoProfile -ExecutionPolicy Bypass -Command "& C:\Scripts\Get-SecureBootCertStatus.ps1 -ComputerName (Get-Content C:\Scripts\servers.txt) -CsvPath C:\Reports\secureboot.csv"'
$trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 7am
$principal = New-ScheduledTaskPrincipal -UserId 'CONTOSO\gmsa-sbcheck$' -LogonType Password -RunLevel Highest
Register-ScheduledTask -TaskName 'Secure Boot certificate check' -Action $action -Trigger $trigger -Principal $principal
This script only reports. To start the update on a device, Microsoft documents several routes for IT-managed devices: setting AvailableUpdates to 0x5944 and letting the Windows scheduled Secure Boot update task and normal restarts do the work, Group Policy, Intune, or the Windows Configuration System (WinCS). Test on a few devices per hardware model first and have BitLocker recovery keys at hand.
How it works
- A self-contained script block (no outside functions) runs locally, or on each computer through
Invoke-Command -ComputerName ... -ThrottleLimit. - It calls
Confirm-SecureBootUEFI; if that fails, it readsUEFISecureBootEnabledunder...\SecureBoot\State. - If Secure Boot is on, it reads the
dbandKEKvariables withGet-SecureBootUEFI, decodes the bytes as ASCII and matches the certificate names. - It reads the registry values with
Get-ItemProperty; missing values become empty columns rather than errors. - It reads the newest System event with ID 1801 or 1808 (
Get-WinEvent -FilterHashtable @{LogName='System'; Id=1801,1808} -MaxEvents 1), the same event IDs Microsoft’s sample inventory script collects. - Computers that do not answer get a row with Assessment “Unreachable” and the remoting error, so the CSV always has one row per name you passed.
Limitations
- Name matching on the decoded bytes tells you a certificate with that name is present; it does not validate the certificate chain. It is the same check Microsoft shows.
- Virtual machines have virtual firmware. Hyper-V Generation 2, VMware EFI and cloud VMs report their own DB/KEK; Generation 1 / BIOS VMs show Secure Boot off.
- Updated is the goal, but a device can have the new DB certificates and still be InProgress until the boot manager is replaced after a restart.
- Remoting must already work; the script does not enable WinRM.
- Not yet run against live devices (see the note at the top).
Official documentation: Registry key updates for Secure Boot (IT-managed) · Secure Boot certificate updates: guidance for IT · Get-SecureBootUEFI · Sample Secure Boot inventory script
Related: Invalid Signature Detected Secure Boot Policy: Fix · Windows 11 Patch Tuesday September 2026 (KB5124008) and the KB5129195 out-of-band fix: what changed · Group Managed Service Accounts (gMSA): Complete Windows Server 2025 Guide · Install RSAT on Windows 11: 5 Methods, Including Offline · A basic RMM monitoring policy for small-business endpoints: disk, patching and antivirus
See also: Secure Boot Certificate Expiry 2026: Check and Update to 2023 CAs
The script
# Secure Boot 2023 Certificate Check: PowerShell Script for Many PCs (v1.0.0) - from srvScripts.com
# Source, docs and updates: https://srvscripts.com/scripts/secure-boot-cert-check/
# Copyright (c) 2026 srvScripts.com. MIT licence: if you copy, share or adapt this script, keep this notice and credit srvScripts.com.
<#
.SYNOPSIS
Secure Boot 2023 certificate status for one or many Windows computers: Secure Boot state, whether the
2023 Microsoft certificates are in DB and KEK, the servicing registry values Windows keeps for the
certificate update, and the latest 1801/1808 event. Read-only. CSV output.
.DESCRIPTION
Microsoft's 2011 Secure Boot certificates expire during 2026 and are being replaced by 2023
certificates. For each computer this script collects:
Secure Boot Confirm-SecureBootUEFI (falls back to HKLM\...\SecureBoot\State\UEFISecureBootEnabled).
DB / KEK Get-SecureBootUEFI db / kek, decoded as ASCII and searched for the certificate names, the
method Microsoft uses in its boot manager guidance:
DB: Windows UEFI CA 2023, Microsoft UEFI CA 2023, Microsoft Option ROM UEFI CA 2023
KEK: Microsoft Corporation KEK 2K CA 2023
Registry HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot:
AvailableUpdates, HighConfidenceOptOut, MicrosoftUpdateManagedOptIn
HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing:
UEFICA2023Status (NotStarted / InProgress / Updated), UEFICA2023Error,
UEFICA2023ErrorEvent, WindowsUEFICA2023Capable (reference only), ConfidenceLevel
...\Servicing\DeviceAttributes: OEM manufacturer, model, firmware version and date.
These values exist on systems with Windows updates from 11 November 2025 or later.
Events Newest System log event 1801 (certificates not yet applied) or 1808 (device has the new
certificates), with the BucketConfidenceLevel text if the event carries it.
The Assessment column is a summary: "Updated" when UEFICA2023Status is Updated, "Secure Boot off" when
Secure Boot is disabled or not supported, otherwise "Action needed" (with what is missing).
The script changes nothing. To start the update itself, follow Microsoft's guidance for IT-managed
devices (AvailableUpdates = 0x5944 processed by Windows' scheduled Secure Boot update task, Group Policy,
Intune or WinCS).
Requirements: run elevated (Get-SecureBootUEFI needs administrator rights). For -ComputerName, PowerShell
remoting (WinRM) must be enabled on the targets and your account must be an administrator there.
.PARAMETER ComputerName Computers to check through Invoke-Command. Default: this computer only.
.PARAMETER Credential Credential for the remote computers.
.PARAMETER ThrottleLimit Maximum parallel remote connections (default 32).
.PARAMETER CsvPath Write the result to this CSV file.
.PARAMETER PassThru Output the objects to the pipeline.
.EXAMPLE .\Get-SecureBootCertStatus.ps1
.EXAMPLE .\Get-SecureBootCertStatus.ps1 -ComputerName (Get-Content .\servers.txt) -CsvPath .\secureboot.csv
.EXAMPLE .\Get-SecureBootCertStatus.ps1 -ComputerName (Get-ADComputer -Filter 'OperatingSystem -like "*Server*"').DNSHostName -CsvPath C:\Reports\secureboot.csv
.EXAMPLE .\Get-SecureBootCertStatus.ps1 -ComputerName HV01,HV02 -PassThru | Where-Object Assessment -ne 'Updated'
.NOTES
Name: Get-SecureBootCertStatus.ps1
Purpose: Read-only audit of the Secure Boot 2023 certificate update
Source: https://srvscripts.com/scripts/secure-boot-cert-check/
License: MIT
Version: 1.0.0
Requires: Windows PowerShell 5.1 or PowerShell 7 on Windows, Administrator; WinRM for remote computers.
#>
[CmdletBinding()]
param(
[ValidateNotNullOrEmpty()]
[string[]]$ComputerName,
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential = [System.Management.Automation.PSCredential]::Empty,
[ValidateRange(1, 256)]
[int]$ThrottleLimit = 32,
[string]$CsvPath,
[switch]$PassThru
)
Set-StrictMode -Version 2
$ErrorActionPreference = 'Stop'
function Write-Status([string]$Message) { Write-Information $Message -InformationAction Continue }
# Runs on each computer. Self-contained: no functions or variables from the outer script are used.
$probe = {
$ErrorActionPreference = 'Stop'
$sbKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot'
$notes = [System.Collections.Generic.List[string]]::new()
function Get-RegValue([string]$Path, [string]$Name) {
try {
$item = Get-ItemProperty -LiteralPath $Path -Name $Name -ErrorAction Stop
return $item.$Name
} catch { return $null }
}
function Test-UefiVar([string]$Name, [string]$Pattern) {
try {
$var = Get-SecureBootUEFI -Name $Name -ErrorAction Stop
return ([System.Text.Encoding]::ASCII.GetString($var.Bytes) -match [regex]::Escape($Pattern))
} catch { return $null }
}
$secureBoot = $null
try { $secureBoot = [bool](Confirm-SecureBootUEFI -ErrorAction Stop) }
catch {
$v = Get-RegValue "$sbKey\State" 'UEFISecureBootEnabled'
if ($null -ne $v) { $secureBoot = ([int]$v -eq 1) }
$notes.Add('Confirm-SecureBootUEFI failed (legacy BIOS, not elevated, or not supported)')
}
$dbWin = $null; $dbUefi = $null; $dbOprom = $null; $kek = $null
if ($secureBoot) {
$dbWin = Test-UefiVar 'db' 'Windows UEFI CA 2023'
$dbUefi = Test-UefiVar 'db' 'Microsoft UEFI CA 2023'
$dbOprom = Test-UefiVar 'db' 'Microsoft Option ROM UEFI CA 2023'
$kek = Test-UefiVar 'KEK' 'Microsoft Corporation KEK 2K CA 2023'
if ($null -eq $dbWin) { $notes.Add('Get-SecureBootUEFI could not read db/KEK (run elevated)') }
}
$avail = Get-RegValue $sbKey 'AvailableUpdates'
$status = Get-RegValue "$sbKey\Servicing" 'UEFICA2023Status'
$err = Get-RegValue "$sbKey\Servicing" 'UEFICA2023Error'
$errEvent = Get-RegValue "$sbKey\Servicing" 'UEFICA2023ErrorEvent'
$capable = Get-RegValue "$sbKey\Servicing" 'WindowsUEFICA2023Capable'
$confidence = Get-RegValue "$sbKey\Servicing" 'ConfidenceLevel'
$attr = "$sbKey\Servicing\DeviceAttributes"
if ($null -eq $status) { $notes.Add('No UEFICA2023Status value (needs Windows updates from 11 Nov 2025 or later)') }
$lastEventId = $null; $lastEventTime = $null; $bucketConfidence = $null
try {
$ev = Get-WinEvent -FilterHashtable @{ LogName = 'System'; Id = 1801, 1808 } -MaxEvents 1 -ErrorAction Stop
if ($ev) {
$lastEventId = $ev.Id; $lastEventTime = $ev.TimeCreated
if ($ev.Message -match 'BucketConfidenceLevel:\s*(.+)') { $bucketConfidence = $Matches[1].Trim() }
}
} catch {
if ($_.FullyQualifiedErrorId -notlike 'NoMatchingEventsFound*') { $notes.Add("Event log: $($_.Exception.Message)") }
}
$os = $null
try { $os = (Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop).Caption } catch { $os = $null }
$missing = @()
if ($dbWin -eq $false) { $missing += 'DB: Windows UEFI CA 2023' }
if ($kek -eq $false) { $missing += 'KEK: KEK 2K CA 2023' }
if ($status -and $status -ne 'Updated') { $missing += "Status: $status" }
$assessment = if ($secureBoot -eq $false) { 'Secure Boot off' }
elseif ($null -eq $secureBoot) { 'Unknown (Secure Boot state not readable)' }
elseif ($status -eq 'Updated') { 'Updated' }
elseif ($missing.Count) { 'Action needed: ' + ($missing -join '; ') }
else { 'Action needed: status unknown' }
[pscustomobject]@{
ComputerName = $env:COMPUTERNAME
OS = $os
SecureBootEnabled = $secureBoot
Assessment = $assessment
DB_WindowsUEFICA2023 = $dbWin
DB_MicrosoftUEFICA2023 = $dbUefi
DB_OptionROMUEFICA2023 = $dbOprom
KEK_2023 = $kek
UEFICA2023Status = $status
UEFICA2023Error = $err
UEFICA2023ErrorEvent = $errEvent
WindowsUEFICA2023Capable = $capable
AvailableUpdates = $(if ($null -ne $avail) { '0x{0:X}' -f [int64]$avail } else { $null })
HighConfidenceOptOut = Get-RegValue $sbKey 'HighConfidenceOptOut'
MicrosoftUpdateManagedOptIn = Get-RegValue $sbKey 'MicrosoftUpdateManagedOptIn'
ConfidenceLevel = $confidence
LastEventId = $lastEventId
LastEventTime = $lastEventTime
EventBucketConfidence = $bucketConfidence
Manufacturer = Get-RegValue $attr 'OEMManufacturerName'
Model = Get-RegValue $attr 'OEMModelNumber'
FirmwareVersion = Get-RegValue $attr 'FirmwareVersion'
FirmwareReleaseDate = Get-RegValue $attr 'FirmwareReleaseDate'
Notes = ($notes -join '; ')
}
}
if ([System.Environment]::OSVersion.Platform -ne [System.PlatformID]::Win32NT -and -not $ComputerName) {
throw 'Run this script on Windows, or use -ComputerName to query Windows computers remotely.'
}
$rows = [System.Collections.Generic.List[object]]::new()
if (-not $ComputerName) {
$principal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Warning 'Not elevated: Get-SecureBootUEFI and Confirm-SecureBootUEFI need administrator rights, so DB/KEK columns will be empty.'
}
$rows.Add((& $probe))
} else {
$targets = @($ComputerName | ForEach-Object { $_.Trim() } | Where-Object { $_ } | Sort-Object -Unique)
Write-Status ("Querying {0} computer(s)..." -f $targets.Count)
$ic = @{ ComputerName = $targets; ScriptBlock = $probe; ThrottleLimit = $ThrottleLimit; ErrorAction = 'SilentlyContinue'; ErrorVariable = 'remoteErrors' }
if ($Credential -ne [System.Management.Automation.PSCredential]::Empty) { $ic.Credential = $Credential }
$remoteErrors = $null
$results = @(Invoke-Command @ic)
foreach ($r in $results) {
$rows.Add(($r | Select-Object -Property * -ExcludeProperty PSComputerName, RunspaceId, PSShowComputerName))
}
$answered = @($results | ForEach-Object { [string]$_.PSComputerName })
foreach ($t in $targets) {
if ($answered -notcontains $t) {
$msg = @($remoteErrors | Where-Object { $_.TargetObject -eq $t -or "$($_.Exception.Message)" -like "*$t*" } | Select-Object -First 1)
$rows.Add([pscustomobject]@{
ComputerName = $t; OS = $null; SecureBootEnabled = $null
Assessment = 'Unreachable'
Notes = $(if ($msg) { $msg[0].Exception.Message } else { 'No result (WinRM, DNS or permissions)' })
})
}
}
}
$out = @($rows | Sort-Object Assessment, ComputerName)
if ($CsvPath) {
# Select explicit columns so rows for unreachable computers line up with the others.
$cols = 'ComputerName', 'OS', 'SecureBootEnabled', 'Assessment', 'DB_WindowsUEFICA2023', 'DB_MicrosoftUEFICA2023', 'DB_OptionROMUEFICA2023',
'KEK_2023', 'UEFICA2023Status', 'UEFICA2023Error', 'UEFICA2023ErrorEvent', 'WindowsUEFICA2023Capable', 'AvailableUpdates',
'HighConfidenceOptOut', 'MicrosoftUpdateManagedOptIn', 'ConfidenceLevel', 'LastEventId', 'LastEventTime', 'EventBucketConfidence',
'Manufacturer', 'Model', 'FirmwareVersion', 'FirmwareReleaseDate', 'Notes'
$out | Select-Object -Property $cols | Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8
Write-Status ("CSV written: {0} ({1} rows)" -f $CsvPath, $out.Count)
}
$summary = $out | Group-Object { ($_.Assessment -split ':')[0] } | ForEach-Object { "{0} {1}" -f $_.Count, $_.Name }
Write-Status ("Computers: {0}. {1}" -f $out.Count, ($summary -join ', '))
if ($PassThru) { return $out }
if (-not $CsvPath) {
$out | Select-Object ComputerName, SecureBootEnabled, Assessment, UEFICA2023Status, LastEventId | Format-Table -AutoSize -Wrap
}
546b4f4fe5620c1e2217d52ba7329d0f47b0b11551d5bf29f7460e1969a254d8curl -fsSL -o Get-SecureBootCertStatus.ps1 https://scr.srvscripts.com/secure-boot-cert-check/Get-SecureBootCertStatus.ps1 && curl -fsSL https://scr.srvscripts.com/secure-boot-cert-check/Get-SecureBootCertStatus.ps1.sha256 | sha256sum -cInvoke-WebRequest -Uri 'https://scr.srvscripts.com/secure-boot-cert-check/Get-SecureBootCertStatus.ps1' -OutFile 'Get-SecureBootCertStatus.ps1'; if ((Get-FileHash 'Get-SecureBootCertStatus.ps1' -Algorithm SHA256).Hash -eq '546B4F4FE5620C1E2217D52BA7329D0F47B0B11551D5BF29F7460E1969A254D8') { 'OK: the file is intact' } else { 'MISMATCH: do not run this file' }Copy the whole line. In Windows PowerShell, curl and sha256sum are not the Linux tools, so use the PowerShell line there.Also on GitHub: github.com/srvscripts/scripts
Frequently asked questions
How do I check if the Secure Boot 2023 certificates are installed?
In an elevated PowerShell run [System.Text.Encoding]::ASCII.GetString((Get-SecureBootUEFI db).bytes) -match ‘Windows UEFI CA 2023’. True means the certificate is in DB. This script runs that check and the KEK check on many computers.
What does UEFICA2023Status mean?
It is the Secure Boot certificate update state Windows keeps under HKLM\SYSTEM\CurrentControlSet\Control\SecureBoot\Servicing: NotStarted, InProgress or Updated.
What are events 1801 and 1808?
Event 1801 in the System log means the updated certificates have not been applied yet; 1808 means the device has the new Secure Boot certificates.
Why is UEFICA2023Status missing?
Microsoft added these registry values in Windows updates released on 11 November 2025 or later. Install current updates; until then rely on the DB/KEK and event columns.
Does the script install the new certificates?
No. It only reads. Use Microsoft’s documented routes (AvailableUpdates 0x5944, Group Policy, Intune or WinCS) to start the update.
Why are the DB and KEK columns empty?
Get-SecureBootUEFI needs an elevated session, and it only works on UEFI systems with Secure Boot. Run PowerShell as Administrator.