#Requires -RunAsAdministrator <# .SYNOPSIS FileWave Booster (Windows): remove the compromised eMudhra emSign G3 root certificates from the booster trust store (fw_cacert.pem). .DESCRIPTION In October 2026 the private keys of eight eMudhra intermediate CAs were compromised. The booster trusts every certificate in its trust_store folder, plus the Windows root store, so the emSign G3 roots are removed from fw_cacert.pem, as upstream certifi 2026.10.19 does, and the Windows root store is checked. The other emSign roots (G1, C1, C3) are not affected and are kept. The backup of fw_cacert.pem is written OUTSIDE the trust_store folder, because the booster loads every file in that folder. The script is idempotent: running it again changes nothing. .PARAMETER DryRun Only report what would be removed. .PARAMETER NoRestart Do not restart the "FileWave Booster" service (restart it later yourself). .PARAMETER File Clean this CA file instead of %ProgramData%\FileWave\FWBooster\trust_store\fw_cacert.pem. .EXAMPLE powershell -ExecutionPolicy Bypass -File .\fw_booster_remove_emsign.ps1 -DryRun #> param( [switch]$DryRun, [switch]$NoRestart, [string]$File = (Join-Path $env:ProgramData 'FileWave\FWBooster\trust_store\fw_cacert.pem') ) $ErrorActionPreference = 'Stop' $ServiceName = 'FileWave Booster' # The roots excluded by certifi 2026.10.19; the TLS one is not in certifi but may be in the OS store. $AffectedRoots = 'CN=emSign (ECC Root CA|Root TLS CA) - G3' if (-not (Test-Path -LiteralPath $File -PathType Leaf)) { Write-Error "$File not found, is this a FileWave Booster?" } Write-Host "Checking $File" $text = [IO.File]::ReadAllText($File) $chunks = [regex]::Matches($text, '(?s).*?-----END CERTIFICATE-----(\r?\n)?') $output = New-Object Text.StringBuilder $removed = 0 $kept = 0 $consumed = 0 foreach ($chunk in $chunks) { $consumed = $chunk.Index + $chunk.Length $isAffected = $false $pem = [regex]::Match($chunk.Value, '(?s)-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----') if ($pem.Success) { try { $der = [Convert]::FromBase64String(($pem.Groups[1].Value -replace '\s', '')) $cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 (, $der) if ($cert.Subject -match $AffectedRoots) { $isAffected = $true Write-Host " affected root: $($cert.Subject)" } } catch { # Not a parsable certificate: keep it untouched. } } if ($isAffected) { $removed++ } else { [void]$output.Append($chunk.Value); $kept++ } } [void]$output.Append($text.Substring($consumed)) $changed = $false if ($removed -eq 0) { Write-Host ' no affected emSign root found, nothing to do' } elseif ($kept -eq 0) { Write-Error 'nothing would be left in the file, left untouched' } elseif ($DryRun) { Write-Host " dry run: would remove $removed certificate(s) and keep $kept" } else { $backupDir = Split-Path -Parent (Split-Path -Parent $File) $stamp = Get-Date -Format 'yyyyMMddHHmmss' $backup = Join-Path $backupDir "$(Split-Path -Leaf $File).bak-emsign-$stamp" $tmp = Join-Path $backupDir ".emsign-$stamp.tmp" Copy-Item -LiteralPath $File -Destination $backup [IO.File]::WriteAllText($tmp, $output.ToString(), (New-Object Text.UTF8Encoding $false)) Get-Acl -LiteralPath $File | Set-Acl -LiteralPath $tmp Move-Item -LiteralPath $tmp -Destination $File -Force $changed = $true Write-Host " removed $removed certificate(s), kept $kept, backup: $backup" } Write-Host 'Checking the Windows root store (the booster trusts it too)...' $osCerts = @(Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -match $AffectedRoots }) $disallowed = @(Get-ChildItem Cert:\LocalMachine\Disallowed | ForEach-Object { $_.Thumbprint }) $stillTrusted = @($osCerts | Where-Object { $disallowed -notcontains $_.Thumbprint }) if ($stillTrusted.Count -gt 0) { Write-Host " WARNING: the Windows root store still trusts $($stillTrusted.Count) affected emSign root(s), the booster keeps trusting them:" $stillTrusted | ForEach-Object { Write-Host " $($_.Subject) ($($_.Thumbprint))" } Write-Host ' Install the latest Windows updates once Microsoft ships the removal.' } else { Write-Host ' OK, no trusted affected emSign root in the Windows root store' } if ($changed) { if ($NoRestart) { Write-Host "Restart the booster to apply: Restart-Service '$ServiceName'" } else { Write-Host 'Restarting the FileWave Booster...' Restart-Service -Name $ServiceName } } Write-Host 'Done.'