Merge latest dev before process command-line integration

This commit is contained in:
Shirofune-Security committed 2026-09-22 18:13:26 +09:00
commit 3db5d73180
13 files changed
+599 -1

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
$ErrorActionPreference='Stop';$repo=Split-Path $PSScriptRoot -Parent;$engine=(Get-Process -Id $PID).Path;$count=0
$cases=@(
@{Args=@('wmi-sacl-recovery','-Help');Code=0;Pattern='one proven parent-only'},
@{Args=@('configure','-WmiRecoveryAction','Recover','-Auto');Code=1;Pattern='require wmi-sacl-recovery'},
@{Args=@('wmi-sacl-recovery','-Help','-Auto');Code=1;Pattern='only dedicated'},
@{Args=@('wmi-sacl-recovery','-Help','-DryRun');Code=1;Pattern='only dedicated'},
@{Args=@('wmi-sacl-recovery','-Help','-WmiAction','Configure');Code=1;Pattern='only dedicated'},
@{Args=@('wmi-sacl-recovery','-Help','-WmiIncludeChildren');Code=1;Pattern='only dedicated'},
@{Args=@('wmi-sacl-recovery','-Help','-Profile','wela-2.2.0');Code=1;Pattern='only dedicated'},
@{Args=@('wmi-sacl-recovery','-Help','-UnknownOption');Code=1;Pattern='Unsupported|Unexpected|unbound|only dedicated'},
@{Args=@('wmi-sacl-recovery','extra');Code=1;Pattern='Unsupported|Unexpected|unbound|only dedicated'},
@{Args=@('wmi-sacl-recovery');Code=1;Pattern='Plan requires'},
@{Args=@('wmi-sacl-recovery','-WmiRecoveryAction','Recover','-WmiRecoveryPlanPath','absent','-WmiRecoveryPlanHash','bad');Code=1;Pattern='Recover requires'})
foreach($case in $cases){$ErrorActionPreference='Continue';$text=& $engine -NoLogo -NoProfile -NonInteractive -File "$repo/WELA.ps1" @($case.Args) 2>&1|Out-String;$code=$LASTEXITCODE;$ErrorActionPreference='Stop';if($code -ne $case.Code -or $text -notmatch $case.Pattern){throw "CLI boundary failed: $($case.Args -join ' ') [$code] $text"};$count++}
Write-Host "PASS: $count WMI SACL recovery public CLI guards.";$global:LASTEXITCODE=0
+124
View File
@@ -0,0 +1,124 @@
$ErrorActionPreference='Stop';$repo=Split-Path $PSScriptRoot -Parent;$script:ScriptRoot=$repo
Import-Module "$repo/modules/AuditProfiles.psm1" -Force
. "$repo/scripts/Configuration.ps1"
. "$repo/scripts/WmiNamespaceAuditing.ps1"
. "$repo/scripts/WmiProbe.ps1"
. "$repo/scripts/WefArrival.ps1"
. "$repo/scripts/WecUpdate.ps1"
. "$repo/scripts/WmiSaclRecovery.ps1"
$script:checks=0
function Assert($Value,$Message){if(-not $Value){throw $Message};$script:checks++}
function Clone($Value){ConvertFrom-WelaArrivalJson (Get-WelaWmiRecoveryKey $Value)}
function Save($Path,$Value){[IO.File]::WriteAllText($Path,(Get-WelaWmiRecoveryKey $Value),[Text.UTF8Encoding]::new($false))}
function Reject([scriptblock]$Action){$failed=$false;try{&$Action|Out-Null}catch{$failed=$true};Assert $failed 'Unsupported or malformed evidence must be refused.'}
function Get-WelaWmiRecoveryContext {[pscustomobject][ordered]@{Host=[pscustomobject]@{Computer='TEST';Build=26100};TokenKey=$script:token;Policies='unchanged'}}
function Get-WelaWmiNamespaceSnapshot {
param($Namespace)
if($Namespace -cne 'root\default'){throw 'Unexpected fixture namespace'}
[pscustomobject]@{Namespace=$Namespace;DescriptorJson=(ConvertTo-WelaWmiJson $script:descriptor);DescriptorMof='complete-native-fixture';SaclReadPrivilege='SeSecurityPrivilege enabled'}
}
function Set-WelaWmiNamespaceDescriptor {
param($Namespace,$ExpectedJson,$Definitions)
Assert ($ExpectedJson -ceq (ConvertTo-WelaWmiJson $script:descriptor)) 'Original production configuration supplies the exact current descriptor.'
foreach($definition in $Definitions){
$ace=[pscustomobject][ordered]@{AccessMask=[uint32]$definition.AccessMask;AceFlags=[uint32]$definition.AceFlags;AceType=2;GuidInheritedObjectType=$null;GuidObjectType=$null;Trustee=[pscustomobject]@{SIDString=$definition.Sid};TIME_CREATED=$null}
$script:descriptor.SACL=@($script:descriptor.SACL|Where-Object {$null -ne $_})+@($ace)
}
$script:descriptor.ControlFlags=[uint32]$script:descriptor.ControlFlags -bor 16
'Original fixture append succeeded.'
}
function Remove-WelaWmiRecoveryAce {
param($Plan,$State)
Assert (Test-Path (Join-Path $script:output 'pending.json')) 'Durable pending receipt precedes native removal.'
$script:writes++;$State.WriteAttempted=$true
if($script:scenario -eq 'native-failure'){throw 'Injected native failure'}
if($script:scenario -ne 'false-success'){$script:descriptor=Get-WelaWmiRecoveryExpectedDescriptor $script:descriptor (Get-WelaWmiRecoveryKey $Plan.AddedAce)}
if($script:scenario -eq 'empty-null'){$script:descriptor.SACL=$null}
if($script:scenario -eq 'preservation'){$script:descriptor.Owner.SIDString='S-1-5-19'}
if($script:scenario -eq 'token'){$script:token='changed'}
if($script:scenario -eq 'last-history'){[IO.File]::AppendAllText($Plan.OriginalResults.Path,' ')}
if($script:scenario -eq 'last-artifact'){[IO.File]::AppendAllText((Join-Path $script:output 'pending.json'),' ')}
$State.After=Get-WelaWmiNamespaceSnapshot $Plan.Namespace
}
$root=Join-Path ([IO.Path]::GetTempPath()) ('wela-wmi-recovery-'+[guid]::NewGuid().ToString('N'));$null=New-Item -ItemType Directory $root
$oldComputer=$env:COMPUTERNAME;$env:COMPUTERNAME='TEST'
function Original([string]$Directory,[switch]$Empty){
$script:descriptor=Get-Content "$repo/tests/fixtures/wmi-namespace-descriptor.json" -Raw|ConvertFrom-Json
if($Empty){$script:descriptor.SACL=$null}
$script:token='original';$script:writes=0;$script:scenario=''
$definitions=@(Get-WelaWmiAuditDefinitions -Namespace 'root\default')
$entry=[pscustomobject]@{Namespace='root\default';Definitions=$definitions}
$context=New-WelaConfigurationContext -Auto -BackupPath "$Directory/journal"
Set-WelaWmiAuditControls $context @($entry)
$r=Complete-WelaConfiguration $context -Scope 'wmi-namespace-sacl-only'
Save "$Directory/original.json" $r
Assert ($r.ExitCode -eq 0 -and $r.Results[0].Status -ceq 'Applied') 'Original journal and completed result come from actual shared configuration callbacks.'
}
try {
foreach($case in @('ok','empty','empty-null','missing-consent','hash','tamper','duplicate-json','source','descriptor-drift','native-failure','false-success','preservation','token','last-history','last-artifact')){
$dir=Join-Path $root $case;$null=New-Item -ItemType Directory $dir;Original $dir -Empty:($case -in @('empty','empty-null'))
$plan=Invoke-WelaWmiSaclRecovery -Namespace 'root\default' -JournalPath "$dir/journal/before.jsonl" -OriginalResultsPath "$dir/original.json" -OutputPath "$dir/plan"
Assert ($plan.Status -ceq 'ReviewRequired' -and $plan.ExitCode -eq 0) "Plan $case : $($plan.Diagnostic)"
Assert ($script:writes -eq 0 -and -not $plan.WriteAttempted) 'Plan performs no native mutation.'
$path="$dir/plan/plan.json";$hash=$plan.PlanHash
if($case -eq 'hash'){$hash='f'*64}
if($case -in @('tamper','duplicate-json')){
$text=[IO.File]::ReadAllText($path)
$text=if($case -eq 'tamper'){$text.Replace('audit ACE','unexpected ACE')}else{$text.Replace('"SchemaVersion":1,','"SchemaVersion":1,"SchemaVersion":1,')}
[IO.File]::WriteAllText($path,$text);$hash=(Get-FileHash $path).Hash.ToLowerInvariant()
}
if($case -eq 'source'){[IO.File]::AppendAllText("$dir/original.json",' ')}
if($case -eq 'descriptor-drift'){$script:descriptor.Group.SIDString='S-1-5-19'}
$script:scenario=$case;$script:output="$dir/recover"
$result=Invoke-WelaWmiSaclRecovery Recover -PlanPath $path -PlanHash $hash -OutputPath $script:output -AllowAuditReduction:($case -ne 'missing-consent')
Assert (($result.ExitCode -eq 0) -eq ($case -in @('ok','empty','empty-null'))) "Recover $case : $($result.Diagnostic)"
Assert ($result.ReadyRuleCredit -eq 0 -and $result.PolicyChanges -eq 0 -and (Test-Path "$dir/recover/manifest.json")) 'Recovery reports no event/policy/Sigma credit and retains outcome evidence.'
if($case -in @('ok','empty','empty-null')){
Assert ($result.Status -ceq 'AddedAceRemoved' -and $result.WriteAttempted -and $script:writes -eq 1) 'Successful recovery removes one proven ACE once.'
Assert (@(Get-WelaWmiMissingAces $script:descriptor @(Get-WelaWmiAuditDefinitions -Namespace 'root\default')).Count -eq 1) 'The original proven addition is absent after recovery.'
$again=Invoke-WelaWmiSaclRecovery Recover -PlanPath $path -PlanHash $hash -OutputPath "$dir/replay" -AllowAuditReduction
Assert ($again.Status -ceq 'Refused' -and $script:writes -eq 1) 'Completed recovery cannot be replayed against an already changed descriptor.'
}elseif($case -in @('native-failure','false-success','preservation','token','last-history','last-artifact')){
Assert ($result.Status -ceq 'WriteAttemptedUnverified' -and $result.WriteAttempted -and $script:writes -eq 1) 'Possible mutation is never reported as a pre-write refusal or verified recovery.'
}else{Assert ($result.Status -ceq 'Refused' -and -not $result.WriteAttempted -and $script:writes -eq 0) 'Stale, malformed, unconsented or drifted input cannot write.'}
foreach($artifact in $result.Artifacts){$valid=(Get-FileHash (Join-Path $result.OutputPath $artifact.Name)).Hash.ToLowerInvariant() -ceq $artifact.Sha256;Assert ($valid -eq (-not ($case -eq 'last-artifact' -and $artifact.Name -ceq 'pending.json'))) 'Artifact hashes reflect actual saved bytes, including deliberate tampering.'}
}
$dir=Join-Path $root 'history';$null=New-Item -ItemType Directory $dir;Original $dir
$savedResult=[IO.File]::ReadAllText("$dir/original.json");$savedJournal=[IO.File]::ReadAllText("$dir/journal/before.jsonl")
foreach($bad in @('failed','dryrun','wrong-host','future','duplicate-row','duplicate-journal','wrong-kind','desired-inheritance','target','incomplete','changed-owner','removed-other','extra-addition','ambiguous-addition','unknown-added-field','false-privilege','string-flags','null-ace','propagation-control')){
$r=ConvertFrom-WelaArrivalJson $savedResult;$e=ConvertFrom-WelaArrivalJson $savedJournal
switch($bad){
'failed' {$r.Results[0].Status='Failed'}
'dryrun' {$r.DryRun=$true}
'wrong-host' {$e.ComputerName='OTHER'}
'future' {$e.RecordedUtc=[DateTime]::UtcNow.AddDays(1).ToString('o')}
'duplicate-row' {$r.Results+=,$r.Results[0]}
'wrong-kind' {$r.Results[0].Kind='Other'}
'desired-inheritance' {$r.Results[0].Desired[0].AceFlags=66;$e.Desired=Clone $r.Results[0].Desired}
'target' {$r.Results[0].Target.Operation='Replace descriptor';$e.Target=Clone $r.Results[0].Target}
'incomplete' {$r.Results[0].Before.PSObject.Properties.Remove('DescriptorMof');$e.Before=Clone $r.Results[0].Before}
'false-privilege' {$r.Results[0].Before.SaclReadPrivilege='Not enabled';$e.Before=Clone $r.Results[0].Before}
default {
$d=ConvertFrom-WelaArrivalJson $r.Results[0].After.DescriptorJson
switch($bad){
'changed-owner' {$d.Owner.SIDString='S-1-5-19'}
'removed-other' {$d.SACL=@($d.SACL|Select-Object -Skip 1)}
'extra-addition' {$d.SACL+=,(Clone $d.SACL[0])}
'ambiguous-addition' {$d.SACL+=,(Clone $d.SACL[-1])}
'unknown-added-field' {$d.SACL[-1]|Add-Member NoteProperty Unknown 'unsafe'}
'string-flags' {$d.ControlFlags=[string]$d.ControlFlags}
'null-ace' {$d.SACL+=,$null}
'propagation-control' {$d.ControlFlags=[int]$d.ControlFlags -bor 512}
}
$r.Results[0].After.DescriptorJson=Get-WelaWmiRecoveryKey $d
}
}
Save "$dir/original.json" $r;$text=Get-WelaWmiRecoveryKey $e;if($bad -eq 'duplicate-journal'){$text+="`n"+$text};[IO.File]::WriteAllText("$dir/journal/before.jsonl",$text)
$p=Invoke-WelaWmiSaclRecovery -Namespace 'root\default' -JournalPath "$dir/journal/before.jsonl" -OriginalResultsPath "$dir/original.json" -OutputPath "$dir/reject-$bad"
Assert ($p.Status -ceq 'Refused' -and -not $p.WriteAttempted) "Original $bad refused: $($p.Diagnostic)"
}
foreach($args in @(@{Namespace='root\*'},@{Namespace='\\remote\root\default'},@{Namespace='root\default';AllowAuditReduction=$true},@{Action='Recover';PlanHash='bad';PlanPath='absent'})){
Reject {Invoke-WelaWmiSaclRecovery @args -OutputPath "$dir/unused"}
}
}finally{$env:COMPUTERNAME=$oldComputer;Remove-Item -LiteralPath $root -Recurse -Force}
Write-Host "PASS: $script:checks WMI recovery proof, consent, preservation, replay and partial-outcome assertions. Native behavior is tested separately."
+133
View File
@@ -0,0 +1,133 @@
param([switch]$AllowDisposableNamespaceWrite)
$ErrorActionPreference='Stop'
if([Environment]::OSVersion.Platform -ne [PlatformID]::Win32NT -or -not $AllowDisposableNamespaceWrite -or $env:GITHUB_ACTIONS -ne 'true' -or $env:RUNNER_ENVIRONMENT -ne 'github-hosted'){throw 'Explicit disposable hosted Windows namespace-write opt-in is required.'}
$repo=Split-Path $PSScriptRoot -Parent;$script:ScriptRoot=$repo
Import-Module "$repo/modules/AuditProfiles.psm1" -Force
. "$repo/scripts/Configuration.ps1"
. "$repo/scripts/WmiNamespaceAuditing.ps1"
. "$repo/scripts/WmiProbe.ps1"
. "$repo/scripts/WefArrival.ps1"
. "$repo/scripts/WecUpdate.ps1"
. "$repo/scripts/WmiSaclRecovery.ps1"
$script:checks=0;$errors=@();$primary=$null;$owned=@();$engine=(Get-Process -Id $PID).Path
function Assert($Value,$Message){if(-not $Value){throw $Message};$script:checks++}
function Key($Value){ConvertTo-Json -InputObject $Value -Depth 40 -Compress}
$root=Join-Path $env:RUNNER_TEMP ('wela-wmi-recovery-'+[guid]::NewGuid().ToString('N'));$null=New-Item -ItemType Directory $root
function Save($Name,$Value){[IO.File]::WriteAllText((Join-Path $root $Name),(Key $Value),[Text.UTF8Encoding]::new($false))}
function Inventory {@(Get-CimInstance -Namespace root -ClassName __Namespace -ErrorAction Stop|ForEach-Object Name|Sort-Object)}
function Services {@(foreach($name in @('Winmgmt','EventLog','WinRM')){$s=Get-CimInstance Win32_Service -Filter "Name='$name'" -ErrorAction Stop;[pscustomobject][ordered]@{Name=$s.Name;State=$s.State;StartMode=$s.StartMode}})}
function Masks {$m=Get-WelaEffectiveAuditPolicy;$o=[ordered]@{};foreach($id in @($m.Keys|Sort-Object)){$o[$id]=$m[$id]};[pscustomobject]$o}
Add-Type -TypeDefinition @'
using System; using System.IO; using System.Text; using System.Threading.Tasks;
public static class WelaWmiRecoveryFixturePipe {
public static async Task<string> Read(TextReader reader) {
var text=new StringBuilder();var buffer=new char[1024];
while(true){int n=await reader.ReadAsync(buffer,0,buffer.Length).ConfigureAwait(false);if(n==0)return text.ToString();
if(n>1048576-text.Length)throw new InvalidDataException("Fixture output exceeds one Mi characters.");text.Append(buffer,0,n);}
}
}
'@
function Public([string]$Name,[string[]]$Arguments,[int]$Expected=0){
$all=@('-NoLogo','-NoProfile','-NonInteractive','-File',"$script:checkout/WELA.ps1")+$Arguments
foreach($a in $all){if($a.Contains('"') -or $a.EndsWith('\') -or $a -match '[\x00-\x1f]'){throw 'Unsupported fixture argument.'}}
$info=[Diagnostics.ProcessStartInfo]::new();$info.FileName=$engine;$info.Arguments=(@($all|ForEach-Object {'"'+$_+'"'}) -join ' ');$info.UseShellExecute=$false;$info.CreateNoWindow=$true;$info.RedirectStandardOutput=$true;$info.RedirectStandardError=$true
$process=[Diagnostics.Process]::new();$process.StartInfo=$info;$started=$false
try{
if(-not $process.Start()){throw 'Owned public child did not start.'};$started=$true
$stdout=[WelaWmiRecoveryFixturePipe]::Read($process.StandardOutput);$stderr=[WelaWmiRecoveryFixturePipe]::Read($process.StandardError)
if(-not $process.WaitForExit(120000)){throw 'Public command exceeded two minutes.'}
if(-not [Threading.Tasks.Task]::WaitAll([Threading.Tasks.Task[]]@($stdout,$stderr),5000)){throw 'Owned public child output drain did not complete.'}
$text=$stdout.Result+"`n"+$stderr.Result;[IO.File]::WriteAllText((Join-Path $root ($Name+'.txt')),$text)
Assert ($process.ExitCode -eq $Expected) "Public $Name exit $($process.ExitCode) expected $Expected : $text"
}finally{
if($started){$exited=$false;try{$exited=$process.HasExited}catch{$script:errors+=$_.Exception.Message};if(-not $exited){try{$process.Kill()}catch{$script:errors+=$_.Exception.Message};try{$exited=$process.WaitForExit(5000)}catch{$script:errors+=$_.Exception.Message}};if(-not $exited){$script:errors+='Owned public child termination unconfirmed'}}
$process.Dispose()
}
}
Initialize-WelaWmiInterop;Initialize-WelaWmiProbeNative
$beforeInventory=Inventory;$beforeServices=Services;$beforeMasks=Masks;$beforePrecedence=Get-WelaRegistryState 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' SCENoApplyLegacyAuditPolicy
$originalParent=Get-WelaWmiNamespaceSnapshot 'root';$originalDefault=Get-WelaWmiNamespaceSnapshot 'root\default';$beforeToken=Get-WelaWmiRecoveryTokenKey
Save 'original-safety.json' ([ordered]@{Inventory=$beforeInventory;Services=$beforeServices;AuditMasks=$beforeMasks;Precedence=$beforePrecedence;Root=$originalParent;Default=$originalDefault;TokenKey=$beforeToken;Engine=$PSVersionTable.PSVersion.ToString()})
try{
$os=Get-CimInstance Win32_OperatingSystem
Assert ($os.ProductType -eq 3 -and $os.BuildNumber -in @('20348','26100')) 'Disposable Server2022/2025 required.'
Assert (@($beforeMasks.PSObject.Properties).Count -eq 59) 'All59 original audit masks are present.'
foreach($case in @('empty','unrelated')){
$name='WelaRecovery_'+[guid]::NewGuid().ToString('N');$namespace='root\'+$name
$factory=New-Object System.Management.ManagementClass -ArgumentList '\\.\root:__Namespace';$instance=$factory.CreateInstance();$instance.Name=$name
$options=New-Object System.Management.PutOptions;$options.Type=[System.Management.PutType]::CreateOnly
$createdPath=$instance.Put($options)
$entry=[pscustomobject]@{Name=$name;Namespace=$namespace;Instance=$instance;Factory=$factory;Removed=$false};$owned+=,$entry
Assert ($createdPath.RelativePath -ceq ('__NAMESPACE.Name="'+$name+'"')) 'Only the exclusively created namespace receives writes.'
$prepared=Get-WelaWmiNamespaceSnapshot $namespace;$data=ConvertFrom-WelaArrivalJson $prepared.DescriptorJson
Assert (@($data.SACL|Where-Object {$null -ne $_}).Count -eq 0) 'Owned namespace begins without existing SACL entries.'
if($case -ceq 'unrelated'){
$other=[pscustomobject]@{Namespace=$namespace;AccessMask=[uint32]2;AceType=2;AceFlags=[uint32]128;Sid='S-1-5-18'}
$null=Set-WelaWmiNamespaceDescriptor $namespace $prepared.DescriptorJson @($other)
$prepared=Get-WelaWmiNamespaceSnapshot $namespace
}
Save ($case+'-prepared.json') $prepared
$script:checkout=Join-Path $root ($case+'-checkout');$null=New-Item -ItemType Directory $script:checkout
foreach($directory in @('config','modules','scripts')){Copy-Item -LiteralPath (Join-Path $repo $directory) -Destination $script:checkout -Recurse}
Copy-Item -LiteralPath "$repo/WELA.ps1" -Destination $script:checkout
# Production retains canonical namespace selection. Only the owned disposable
# copied catalog is redirected, preserving all real public Configure/Recover code.
$catalogPath=Join-Path $script:checkout 'scripts/WmiNamespaceAuditing.ps1';$catalog=[IO.File]::ReadAllText($catalogPath)
Assert ($catalog.Contains("'root\default'")) 'Expected canonical namespace entry exists in owned copied checkout.'
[IO.File]::WriteAllText($catalogPath,$catalog.Replace("'root\default'","'$namespace'"),[Text.UTF8Encoding]::new($false))
Copy-Item -LiteralPath $catalogPath -Destination (Join-Path $root ($case+'-redirected-WmiNamespaceAuditing.ps1'))
$journal=Join-Path $root ($case+'-journal');$results=Join-Path $root ($case+'-original.json')
Public ($case+'-dryrun') @('wmi-auditing','-WmiAction','Configure','-WmiNamespace',$namespace,'-Auto','-DryRun','-BackupPath',($journal+'-dryrun'),'-ResultsPath',($results+'-dryrun'))
Assert (-not(Test-Path ($journal+'-dryrun')) -and (Get-WelaWmiNamespaceSnapshot $namespace).DescriptorJson -ceq $prepared.DescriptorJson) 'Public dry-run writes no namespace SACL or journal.'
Public ($case+'-configure') @('wmi-auditing','-WmiAction','Configure','-WmiNamespace',$namespace,'-Auto','-BackupPath',$journal,'-ResultsPath',$results)
$configured=Get-WelaWmiNamespaceSnapshot $namespace;$original=ConvertFrom-WelaArrivalJson ([IO.File]::ReadAllText($results))
Assert ($original.Results.Count -eq 1 -and $original.Results[0].Status -ceq 'Applied') 'Genuine public Configure journal/result proves the original addition.'
Assert (Test-WelaWmiDescriptorPreserved (ConvertFrom-WelaArrivalJson $prepared.DescriptorJson) (ConvertFrom-WelaArrivalJson $configured.DescriptorJson)) 'Original public append preserves all unrelated descriptor properties and ACEs.'
$planDir=Join-Path $root ($case+'-plan')
Public ($case+'-plan') @('wmi-sacl-recovery','-WmiRecoveryNamespace',$namespace,'-WmiRecoveryJournalPath',"$journal/before.jsonl",'-WmiRecoveryOriginalResultsPath',$results,'-WmiRecoveryOutputPath',$planDir)
$plan=ConvertFrom-WelaArrivalJson ([IO.File]::ReadAllText("$planDir/manifest.json"));$reviewed=ConvertFrom-WelaArrivalJson ([IO.File]::ReadAllText("$planDir/plan.json"))
Assert ($plan.Status -ceq 'ReviewRequired' -and -not $plan.WriteAttempted -and (Get-FileHash "$planDir/plan.json").Hash.ToLowerInvariant() -ceq $plan.PlanHash) 'Native public review is read-only and has an independently checked hash.'
Assert ((Get-WelaWmiNamespaceSnapshot $namespace).DescriptorJson -ceq $configured.DescriptorJson) 'Public Plan leaves the full descriptor unchanged.'
foreach($p in $reviewed.Sources.PSObject.Properties){Assert ((Get-FileHash -LiteralPath (Join-Path $script:checkout $p.Name)).Hash.ToLowerInvariant() -ceq $p.Value) 'Plan binds exact installed copied sources.'}
$recover=@('wmi-sacl-recovery','-WmiRecoveryAction','Recover','-WmiRecoveryPlanPath',"$planDir/plan.json",'-WmiRecoveryPlanHash',$plan.PlanHash)
Public ($case+'-missing-consent') ($recover+@('-WmiRecoveryOutputPath',(Join-Path $root ($case+'-missing-consent')))) 1
Assert ((Get-WelaWmiNamespaceSnapshot $namespace).DescriptorJson -ceq $configured.DescriptorJson) 'Missing explicit audit-reduction consent preserves the native descriptor.'
$recoverDir=Join-Path $root ($case+'-recover')
Public ($case+'-recover') ($recover+@('-WmiRecoveryAllowAuditReduction','-WmiRecoveryOutputPath',$recoverDir))
$recovered=ConvertFrom-WelaArrivalJson ([IO.File]::ReadAllText("$recoverDir/manifest.json"));$after=Get-WelaWmiNamespaceSnapshot $namespace
Assert ($recovered.Status -ceq 'AddedAceRemoved' -and $recovered.WriteAttempted -and $recovered.ReadyRuleCredit -eq 0 -and $recovered.PolicyChanges -eq 0) 'Public recovery confirms one proven removal without policy/event/Sigma credit.'
$expected=Get-WelaWmiRecoveryExpectedDescriptor (ConvertFrom-WelaArrivalJson $configured.DescriptorJson) (Get-WelaWmiRecoveryKey $reviewed.AddedAce)
Assert-WelaWmiRecoveryRemoved $expected (ConvertFrom-WelaArrivalJson $after.DescriptorJson)
Assert ($after.DescriptorJson -ceq $recovered.After.DescriptorJson) 'Independent reopened descriptor matches confirmed native readback.'
if($case -ceq 'unrelated'){Assert (@((ConvertFrom-WelaArrivalJson $after.DescriptorJson).SACL).Count -eq 1) 'Unrelated original audit ACE remains after recovery.'}
else{Assert (@((ConvertFrom-WelaArrivalJson $after.DescriptorJson).SACL|Where-Object {$null -ne $_}).Count -eq 0) 'Sole added audit ACE is actually absent.'}
Public ($case+'-replay') ($recover+@('-WmiRecoveryAllowAuditReduction','-WmiRecoveryOutputPath',(Join-Path $root ($case+'-replay')))) 1
Assert ((Get-WelaWmiNamespaceSnapshot $namespace).DescriptorJson -ceq $after.DescriptorJson) 'Stale completed plan replay makes no descriptor change.'
foreach($manifest in @($plan,$recovered)){foreach($artifact in $manifest.Artifacts){Assert ((Get-FileHash -LiteralPath (Join-Path $manifest.OutputPath $artifact.Name)).Hash.ToLowerInvariant() -ceq $artifact.Sha256) 'Saved plan/recovery artifacts match actual hashes.'}}
Save ($case+'-after.json') $after
Remove-Item -LiteralPath $script:checkout -Recurse -Force
}
}catch{$primary=$_;Write-Host ('Primary WMI recovery fixture failure: '+$_.Exception.Message)}
finally{
foreach($entry in $owned){
try{
if($entry.Name -cnotmatch '^WelaRecovery_[a-f0-9]{32}$' -or $entry.Instance.Name -cne $entry.Name -or $entry.Instance.Path.RelativePath -cne ('__NAMESPACE.Name="'+$entry.Name+'"')){throw 'Owned namespace identity changed; refusing deletion.'}
$children=@(Get-CimInstance -Namespace $entry.Namespace -ClassName __Namespace -ErrorAction Stop)
if($children.Count){throw 'Owned namespace acquired unexpected children; refusing recursive deletion.'}
$entry.Instance.Delete();$entry.Removed=$true
}catch{$errors+=$_.Exception.Message}
finally{try{$entry.Instance.Dispose();$entry.Factory.Dispose()}catch{$errors+=$_.Exception.Message}}
}
$inventoryOk=$false;$rootOk=$false;$defaultOk=$false;$servicesOk=$false;$masksOk=$false;$precedenceOk=$false;$tokenOk=$false
try{$afterInventory=Inventory;$inventoryOk=(Key $afterInventory) -ceq (Key $beforeInventory)}catch{$errors+=$_.Exception.Message}
try{$rootOk=(Get-WelaWmiNamespaceSnapshot 'root').DescriptorJson -ceq $originalParent.DescriptorJson;$defaultOk=(Get-WelaWmiNamespaceSnapshot 'root\default').DescriptorJson -ceq $originalDefault.DescriptorJson}catch{$errors+=$_.Exception.Message}
try{$afterServices=Services;$servicesOk=(Key $afterServices) -ceq (Key $beforeServices)}catch{$errors+=$_.Exception.Message}
try{$afterMasks=Masks;$masksOk=(Key $afterMasks) -ceq (Key $beforeMasks)}catch{$errors+=$_.Exception.Message}
try{$afterPrecedence=Get-WelaRegistryState 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa' SCENoApplyLegacyAuditPolicy;$precedenceOk=(Key $afterPrecedence) -ceq (Key $beforePrecedence)}catch{$errors+=$_.Exception.Message}
try{$afterToken=Get-WelaWmiRecoveryTokenKey;$tokenOk=$afterToken -ceq $beforeToken}catch{$errors+=$_.Exception.Message}
foreach($dir in @((Join-Path $root 'empty-checkout'),(Join-Path $root 'unrelated-checkout'))){try{if(Test-Path -LiteralPath $dir){Remove-Item -LiteralPath $dir -Recurse -Force}}catch{$errors+=$_.Exception.Message}}
$complete=$inventoryOk -and $rootOk -and $defaultOk -and $servicesOk -and $masksOk -and $precedenceOk -and $tokenOk -and @($owned|Where-Object {-not $_.Removed}).Count -eq 0 -and $errors.Count -eq 0
Save 'cleanup.json' ([ordered]@{Complete=[bool]$complete;Assertions=$script:checks;OwnedNamespaces=@($owned|Select-Object Namespace,Removed);RootInventoryRestored=$inventoryOk;RootDescriptorUnchanged=$rootOk;RealDefaultDescriptorUnchanged=$defaultOk;ServicesUnchanged=$servicesOk;AuditMasksCompared=59;AuditMasksUnchanged=$masksOk;PrecedenceUnchanged=$precedenceOk;TokenRestored=$tokenOk;AfterInventory=$afterInventory;AfterServices=$afterServices;AfterMasks=$afterMasks;AfterPrecedence=$afterPrecedence;AfterToken=$afterToken;Errors=$errors;PrimaryFailure=$(if($primary){$primary.Exception.Message}else{$null})})
}
if($primary){throw $primary};Assert $complete 'Independent exact cleanup failed; retain evidence and discard disposable VM.'
Write-Host "PASS: $script:checks native public WMI recovery assertions and exact cleanup. Evidence: $root"