Validate packet capture outcomes and narrow cleanup inventory
Windows tests / test-and-build (push) Canceled after 0s

This commit is contained in:
0x000 committed 2026-09-26 21:24:03 -04:00
1 parent b9a3308214
commit 65f302279d
9 files changed
+110 -24

No files matched your search

+15 -6
View File
@@ -12,17 +12,26 @@ $stateRoot=Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'MsP
if($Mode -eq 'Plan'){$x=Get-WindNetworkPlan -Profile $Profile -RollbackMinutes $RollbackMinutes;if($Json){$x|ConvertTo-Json -Depth 8}else{$x.Items|Format-Table -Wrap};return}
if($Mode -eq 'Validate'){$x=Get-WindNetworkValidation;if($Json){$x|ConvertTo-Json -Depth 8}else{$x|Format-List};return}
if($Mode -eq 'CaptureStart'){
Assert-WindMutationAllowed;if(-not (Get-Command pktmon.exe -ErrorAction SilentlyContinue)){throw 'pktmon.exe is unavailable.'}
if(-not $CaptureDirectory){$CaptureDirectory=Join-Path $stateRoot ('capture-'+(Get-Date -Format 'yyyyMMdd-HHmmss'))}
if(-not $CaptureDirectory){$CaptureDirectory=Join-Path $stateRoot ('capture-'+[guid]::NewGuid().ToString('N'))}
$CaptureDirectory=Resolve-WindCaptureDirectory -Path $CaptureDirectory -StateRoot $stateRoot
$etl=Join-Path $CaptureDirectory 'capture.etl';if(Test-Path -LiteralPath $etl){throw 'Capture output already exists. Choose a new capture directory.'}
if(-not $PSCmdlet.ShouldProcess($CaptureDirectory,'Start packet capture')){return}
Assert-WindMutationAllowed
[IO.Directory]::CreateDirectory($CaptureDirectory)|Out-Null
$etl=Join-Path $CaptureDirectory 'capture.etl';& pktmon.exe start --capture --comp nics --pkt-size 0 --file-name $etl|Out-Host
Invoke-WindPacketMonitor -ArgumentList @('start','--capture','--comp','nics','--pkt-size','0','--file-name',$etl)
[pscustomobject]@{Status='Running';Directory=$CaptureDirectory;Warning='Capture can contain private addresses and DNS names. Stop and delete or export it explicitly.'}|ConvertTo-Json
return
}
if($Mode -eq 'CaptureStop'){
if(-not $CaptureDirectory){throw 'CaptureStop requires -CaptureDirectory.'};$full=[IO.Path]::GetFullPath($CaptureDirectory)
if(-not $full.StartsWith([IO.Path]::GetFullPath($stateRoot)+'\',[StringComparison]::OrdinalIgnoreCase)){throw 'Capture directory must be inside the ms-private local state directory.'}
& pktmon.exe stop|Out-Host;$etl=Join-Path $full 'capture.etl';$pcap=Join-Path $full 'capture.pcapng';if(Test-Path $etl){& pktmon.exe etl2pcap $etl --out $pcap|Out-Host}
if(-not $CaptureDirectory){throw 'CaptureStop requires -CaptureDirectory.'};$full=Resolve-WindCaptureDirectory -Path $CaptureDirectory -StateRoot $stateRoot
if(-not $PSCmdlet.ShouldProcess($full,'Stop packet capture and convert to PCAPNG')){return}
Assert-WindMutationAllowed
$etl=Join-Path $full 'capture.etl';$pcap=Join-Path $full 'capture.pcapng'
if(-not(Test-Path -LiteralPath $etl -PathType Leaf)){throw 'Capture ETL file is missing; no capture was stopped.'}
if(Test-Path -LiteralPath $pcap){throw 'Converted capture already exists; preserve or move it before retrying conversion.'}
Invoke-WindPacketMonitor -ArgumentList @('stop')
Invoke-WindPacketMonitor -ArgumentList @('etl2pcap',$etl,'--out',$pcap)
if(-not(Test-Path -LiteralPath $pcap -PathType Leaf)){throw 'Packet capture conversion returned success without creating the PCAPNG file.'}
Save-WindJournal -Journal (Get-WindNetworkValidation) -Path (Join-Path $full 'connections.json')
Write-Output "Capture stopped: $full";return
}
+2 -2
View File
@@ -179,7 +179,7 @@ Read the [complete tool breakdown](docs/TOOL-BREAKDOWN.md), [current roadmap](do
## Development and release status
The current source includes unreleased cleanup preview, stale-file and dependency-matching fixes after v0.0.5. Windows PowerShell 5.1 passes the expanded 128 checks. The new cleanup test suite encountered an antivirus block in PowerShell 7; see [validation status](docs/VALIDATION.md). The downloadable v0.0.5 executable does not contain these unreleased changes.
The current source includes unreleased cleanup preview, stale-file, dependency-matching and packet-capture fixes after v0.0.5. Windows PowerShell 5.1 passes the expanded 142 checks. PowerShell 7 encounters an antivirus block in production cleanup catalog and target validation; see [validation status](docs/VALIDATION.md). The downloadable v0.0.5 executable does not contain these unreleased changes.
```powershell
.\tests\Run-All.ps1
@@ -187,6 +187,6 @@ The current source includes unreleased cleanup preview, stale-file and dependenc
.\Build-Release.ps1
```
Tests use synthetic registry/app/network/service/account backends, read-only security inventory and temporary workspace files. CI is configured to run 128 PowerShell checks on Windows PowerShell 5.1 and PowerShell 7, plus ten native launcher checks, PE inspection and the one-file publish. Full live uninstall/sign-out/reboot/update/network/device validation on the supported OS matrix remains required before advertising a production-validated release. See [validation](docs/VALIDATION.md) and [contributing](CONTRIBUTING.md).
Tests use synthetic registry/app/network/service/account backends, read-only security inventory and temporary workspace files. CI is configured to run 142 PowerShell checks on Windows PowerShell 5.1 and PowerShell 7, plus ten native launcher checks, PE inspection and the one-file publish. Full live uninstall/sign-out/reboot/update/network/device validation on the supported OS matrix remains required before advertising a production-validated release. See [validation](docs/VALIDATION.md) and [contributing](CONTRIBUTING.md).
`Build-Executable.ps1` creates the self-contained x64 executable and checksum. `Build-Release.ps1` writes a source ZIP and checksum, and `Build-AmePlaybook.ps1` creates the separate AME wrapper when 7-Zip is installed. Builders exclude local reports, refuse to overwrite an existing artifact and do not sign or publish it.
+1 -1
View File
@@ -1,6 +1,6 @@
# Delivery status — 2026-09-26
Unreleased changes after v0.0.5: cleanup previews now return before report creation or clipboard clearing; cleanup preserves files whose recorded size or modification time changed after planning; operation dependencies use the same case-insensitive matching during validation and execution. Seven disposable-file/clipboard-mock regressions and one dependency regression were added. Windows PowerShell 5.1 passed all component suites (128 checks). PowerShell 7 blocked the new cleanup test's replacement catalog with an antivirus response; no matching recent Defender detection was available. This compatibility failure remains open and no replacement executable is published for these changes.
Unreleased changes after v0.0.5: cleanup previews now return before report creation or clipboard clearing; cleanup preserves files whose recorded size or modification time changed after planning; operation dependencies use the same case-insensitive matching during validation and execution. Packet capture now checks native exit codes, honors previews, validates local paths consistently, refuses existing capture outputs and verifies conversion output. Windows PowerShell 5.1 passed all component suites (142 checks). Fourteen capture checks and 48 feature checks pass in PowerShell 7. Cleanup testing in PowerShell 7 is still blocked by an antivirus response in production cleanup catalog and target validation, even after removing the test's private-function replacement. Defender and Bitdefender are both registered on this host; the responsible product is not established. No replacement executable is published while this compatibility failure remains open.
The update architecture and implementation pass was completed on 2026-09-20. The product is named ms-private. Local OS inventory, offline bundle verification, the graphical and terminal wizards, app/debloat flows, Microsoft app-account purge, network enforcement and capture, reversible privacy-service shutdown, Recall, exact sensors, privacy-artifact cleanup, lock handling, security status and AME packaging are implemented or prepared as described below. No real package download, app removal, account purge, policy write, service mutation, firewall change, device disable, cleanup or Recall deletion was performed.
+5 -1
View File
@@ -2,10 +2,14 @@
## Completed checks
Unreleased audit, 2026-09-26: seven new cleanup regressions pass in Windows PowerShell 5.1, covering a side-effect-free preview, unchanged-file deletion, timestamp and length changes, locked files, invalid timestamps and the real cleanup entry script with a mocked clipboard. The operation runner also tests differently capitalized dependency names. The Windows PowerShell 5.1 component suites total 128 passing checks. PowerShell 7 reported an antivirus block in the replacement cleanup catalog; that new suite is not validated in that engine. No security exclusions or bypasses were added. Changed-file detection uses size and modification time; it does not detect identical metadata or eliminate the filesystem race between checking and deleting a file.
Unreleased audit, 2026-09-26: seven cleanup regressions pass in Windows PowerShell 5.1, covering a side-effect-free preview, unchanged-file deletion, timestamp and length changes, locked files, invalid timestamps and the real cleanup entry script with a mocked clipboard. The file tests use the production allowlist and plans containing only disposable files. The operation runner also tests differently capitalized dependency names. Fourteen packet-capture checks pass in both engines, covering path boundaries, file ancestors, argument preservation, native-command failures, absent exit codes and previews through the real entry script. The Windows PowerShell 5.1 component suites total 142 passing checks.
PowerShell 7 still reports `ScriptContainedMaliciousContent` in production `Get-WindBrowserCacheCatalog` enumeration and `Invoke-WindCleanup` target validation. The block reproduced after removing the original private-function test replacement, so the earlier test-mock-only diagnosis was incomplete. Both Defender and Bitdefender are registered on the host; available Defender events did not identify the source. No security exclusions or bypasses were added. This remains a release blocker. Changed-file detection uses size and modification time; it does not detect identical metadata or eliminate the filesystem race between checking and deleting a file. Capture path checks likewise do not eliminate concurrent filesystem replacement; the global Pktmon session still requires live ownership/interruption testing.
All 48 feature tests also pass in PowerShell 7. The previous v0.0.5 Gitea job ended as `Canceled after 0s`; it provides no remote test evidence. The local validation results above remain distinct from server CI status.
Cleanup now enumerates browser profiles only when BrowserCache is selected. Packet-monitor invocation was also checked against the real `pktmon help` command; this is a read-only native-command smoke test, not evidence of successful live capture or conversion.
Release-candidate update, 2026-09-24: 120 tests pass in each of Windows PowerShell 5.1 and PowerShell 7 (25 policy/transaction, 29 app/menu, 19 offline-bundle, 47 feature/package/security/service/account/preset/operation-runner). The policy tests include current-user registry scope, Home direct-control selection and managed-edition exclusion, and Enterprise-only selection. The app tests include aggressive all-removable-app and explicit Store selection, safe skipping of ambiguous desktop registrations, protection of security/dependency applications, completeness of FreshInstall/Medium/Strong/Maximum and the non-destructive EstablishedSafe preset, the reported JSON catalog failure and journal callback scope failure, browser-before-removal sequencing, installer errors, stale inventory, partial failure, bundle deduplication, group selection, keyboard navigation, filtering and terminal layout limits. Feature tests cover real populated and empty operation-runner reports, captured GUI child-script invocation and deferred atomic JSON writers across nested module boundaries, cleanup report finalization, invoker path-traversal refusal, fresh/established/unknown install-age decisions, continued execution of independent groups after a failure, dependency skipping, preset schema refusal, shared Recall apply/skip/conflict decisions, atomic JSON replacement, malformed or duplicate policy/service/account/network catalogs, protected update-endpoint refusal, untrusted registry-hive refusal, network journal recovery, cleanup-root and protected-log refusal, recovery-journal exclusion, browser-cache scope, protected-service exclusion, service disable/restore, forged service-plan rejection, exact account-package reset, credential allowlisting, report redaction, VeraCrypt volume validation, versioned secret-free security audit behavior and AME manifest structure. Native arrow/Space/Enter/Esc browser selection was also exercised in a real Windows PowerShell console. Live host inventory, service planning and account planning were read-only. No real uninstall, account purge, policy or service write, reboot, firewall change, capture, device disable, Recall deletion or update installation was performed.
The .NET launcher has ten passing tests for valid archive acceptance, installed payload and manifest verification, repair after modified files, rejection and repair of undeclared installed files, manifest path traversal refusal, bad-hash refusal and undeclared archive-entry refusal. `Build-Executable.ps1` must also produce exactly one x64 self-contained executable plus its checksum. Its managed PE inspection verifies AMD64 and GUI headers, the embedded `requireAdministrator` manifest, version, checksum and signature state. Before publishing, launch the GUI in a clean VM, alter and add runtime files to confirm repair, and test a Program Files access failure.
+4 -3
View File
@@ -26,6 +26,7 @@ function Get-WindBrowserCacheCatalog {
}
function Get-WindPrivacyCleanupCatalog {
param([bool]$IncludeBrowserCache=$true)
$local=[Environment]::GetFolderPath('LocalApplicationData');$roaming=[Environment]::GetFolderPath('ApplicationData');$program=[Environment]::GetFolderPath('CommonApplicationData')
foreach($root in Get-WindCleanupRoots){[pscustomobject]@{Category='Temp';Root=$root;Patterns=@('*');Recurse=$true;Scheduled=$true;Description='Old files in allowlisted Windows temporary directories'}}
foreach($root in @((Join-Path $local 'Microsoft\Windows\WER'),(Join-Path $program 'Microsoft\Windows\WER\ReportArchive'),(Join-Path $program 'Microsoft\Windows\WER\ReportQueue'),(Join-Path $program 'Microsoft\Windows\WER\Temp'))){[pscustomobject]@{Category='CrashReports';Root=$root;Patterns=@('*');Recurse=$true;Scheduled=$false;Description='Queued and archived Windows Error Reporting data, which can include dumps and user content'}}
@@ -33,7 +34,7 @@ function Get-WindPrivacyCleanupCatalog {
[pscustomobject]@{Category='RecentItems';Root=(Join-Path $roaming 'Microsoft\Windows\Recent');Patterns=@('*.lnk','*.automaticDestinations-ms','*.customDestinations-ms');Recurse=$true;Scheduled=$false;Description='Current-user Recent Items and Jump Lists'}
[pscustomobject]@{Category='ThumbnailCache';Root=(Join-Path $local 'Microsoft\Windows\Explorer');Patterns=@('thumbcache_*.db','iconcache_*.db');Recurse=$false;Scheduled=$false;Description='Current-user thumbnail and icon caches; files in use are skipped'}
[pscustomobject]@{Category='PowerShellHistory';Root=(Join-Path $roaming 'Microsoft\Windows\PowerShell\PSReadLine');Patterns=@('*_history.txt');Recurse=$false;Scheduled=$false;Description='Current-user PowerShell interactive command history'}
foreach($target in Get-WindBrowserCacheCatalog){$target}
if($IncludeBrowserCache){foreach($target in Get-WindBrowserCacheCatalog){$target}}
foreach($root in @((Join-Path $local 'MsPrivate\apps'),(Join-Path $local 'MsPrivate\cleanup'))){[pscustomobject]@{Category='WindReports';Root=$root;Patterns=@('*.json');Recurse=$true;Scheduled=$true;Description='Expired ms-private operation reports; policy, hardware, Recall and network recovery journals are excluded'}}
[pscustomobject]@{Category='WindReports';Root=(Join-Path $local 'MsPrivate\network');Patterns=@('capture.etl','capture.pcapng','connections.json');Recurse=$true;Scheduled=$true;Description='Expired ms-private packet captures and connection snapshots; firewall recovery journals are excluded'}
}
@@ -56,7 +57,7 @@ function Test-WindCleanupPathSafe {
function Get-WindCleanupPlan {
param([ValidateRange(0,365)][int]$AgeDays=7,[ValidateSet('Temp','CrashReports','RecentItems','ThumbnailCache','PowerShellHistory','BrowserCache','WindReports')][string[]]$Category=@('Temp'),[string[]]$Root,[datetime]$Now=(Get-Date))
$cutoff=$Now.AddDays(-$AgeDays);$catalog=@(Get-WindPrivacyCleanupCatalog|Where-Object{$Category-contains$_.Category})
$cutoff=$Now.AddDays(-$AgeDays);$catalog=@(Get-WindPrivacyCleanupCatalog -IncludeBrowserCache ($Category-contains'BrowserCache')|Where-Object{$Category-contains$_.Category})
if($PSBoundParameters.ContainsKey('Root')){
if(@($Category|Select-Object -Unique).Count-ne 1-or$Category[0]-ne'Temp'){throw '-Root is available only for the Temp category.'}
$allowed=@(Get-WindCleanupRoots|ForEach-Object{[IO.Path]::GetFullPath($_).TrimEnd('\')});$catalog=@($Root|ForEach-Object{$full=[IO.Path]::GetFullPath($_).TrimEnd('\');if($allowed-notcontains$full){throw "Cleanup root is not allowlisted: $full"};[pscustomobject]@{Category='Temp';Root=$full;Patterns=@('*');Recurse=$true}})
@@ -86,7 +87,7 @@ function Get-WindCleanupPlan {
function Invoke-WindCleanup {
[CmdletBinding(SupportsShouldProcess)]param([Parameter(Mandatory)]$Plan,[Parameter(Mandatory)][string]$ReportPath)
if($Plan.Schema-ne 2-or$Plan.AgeDays-lt 0){throw 'Invalid cleanup plan.'};$valid=@('Temp','CrashReports','RecentItems','ThumbnailCache','PowerShellHistory','BrowserCache','WindReports');if(@($Plan.Categories|Where-Object{$_-notin$valid}).Count){throw 'Cleanup plan contains an unknown category.'}
$catalog=@(Get-WindPrivacyCleanupCatalog|Where-Object{$Plan.Categories-contains$_.Category});$cutoff=[datetime]::Parse($Plan.CutoffUtc).ToUniversalTime()
$catalog=@(Get-WindPrivacyCleanupCatalog -IncludeBrowserCache ($Plan.Categories-contains'BrowserCache')|Where-Object{$Plan.Categories-contains$_.Category});$cutoff=[datetime]::Parse($Plan.CutoffUtc).ToUniversalTime()
$report=[pscustomobject]@{Schema=2;Kind='WindCleanup';CreatedUtc=[DateTime]::UtcNow.ToString('o');Categories=@($Plan.Categories);Status='Running';Deleted=0;Skipped=0;FreedBytes=[long]0;Entries=@()}
if(-not$PSCmdlet.ShouldProcess('Selected cleanup files','Delete planned privacy artifacts and write cleanup report')){$report.Status='Preview';return $report}
$save=New-MsPrivateJsonWriter -Path $ReportPath -Depth 7;&$save $report
+34 -1
View File
@@ -167,4 +167,37 @@ function Get-WindNetworkValidation {
}
}
Export-ModuleMember -Function Get-WindNetworkCatalog,Get-WindNetworkCapabilities,Get-WindNetworkPlan,New-WindNetworkBackend,Invoke-WindNetworkApply,Restore-WindNetwork,Confirm-WindNetwork,Get-WindNetworkValidation,Assert-WindNetworkJournal
function Resolve-WindCaptureDirectory {
param([Parameter(Mandatory)][string]$Path,[Parameter(Mandatory)][string]$StateRoot)
if($Path-notmatch'^[A-Za-z]:[\\/]'){throw 'Capture directory must be an absolute local path.'}
$root=[IO.Path]::GetFullPath($StateRoot).TrimEnd('\')
$full=[IO.Path]::GetFullPath($Path).TrimEnd('\')
if(-not$full.StartsWith($root+'\',[StringComparison]::OrdinalIgnoreCase)-or$full.Substring(2).Contains(':')){throw 'Capture directory must be inside the ms-private local state directory.'}
$cursor=$full
while($cursor){
if(Test-Path -LiteralPath $cursor){
$item=Get-Item -LiteralPath $cursor -Force -ErrorAction Stop
if(-not$item.PSIsContainer-or($item.Attributes-band[IO.FileAttributes]::ReparsePoint)){throw 'Capture path crosses a file or reparse point.'}
}
$next=[IO.Path]::GetDirectoryName($cursor);if($next-eq$cursor){break};$cursor=$next
}
$full
}
function Invoke-WindPacketMonitor {
param(
[Parameter(Mandatory)][string[]]$ArgumentList,
[scriptblock]$Runner={
param($NativeArguments)
$executable=Join-Path $env:SystemRoot 'System32\pktmon.exe'
if(-not(Test-Path -LiteralPath $executable -PathType Leaf)){throw 'pktmon.exe is unavailable.'}
& $executable @NativeArguments|Out-Host
$LASTEXITCODE
}
)
$result=@(& $Runner $ArgumentList)
if($result.Count-ne1-or$result[0]-isnot[int]){throw 'Packet monitor did not return a valid exit code.'}
if($result[0]-ne0){throw "pktmon $($ArgumentList[0]) failed with exit code $($result[0])."}
}
Export-ModuleMember -Function Get-WindNetworkCatalog,Get-WindNetworkCapabilities,Get-WindNetworkPlan,New-WindNetworkBackend,Invoke-WindNetworkApply,Restore-WindNetwork,Confirm-WindNetwork,Get-WindNetworkValidation,Assert-WindNetworkJournal,Resolve-WindCaptureDirectory,Invoke-WindPacketMonitor
+1 -1
View File
@@ -8,5 +8,5 @@ foreach ($file in $files) {
[System.Management.Automation.Language.Parser]::ParseFile($file.FullName,[ref]$tokens,[ref]$errors) | Out-Null
if ($errors.Count) {throw ($errors | Out-String)}
}
foreach ($suite in @('Run-Tests.ps1','Run-AppTests.ps1','Run-OfflineUpdateTests.ps1','Run-FeatureTests.ps1','Run-CleanupTests.ps1')) {& (Join-Path $PSScriptRoot $suite)}
foreach ($suite in @('Run-Tests.ps1','Run-AppTests.ps1','Run-OfflineUpdateTests.ps1','Run-FeatureTests.ps1','Run-CleanupTests.ps1','Run-CaptureTests.ps1')) {& (Join-Path $PSScriptRoot $suite)}
Write-Output 'All checks passed. No live policy or application mutations were performed.'
+41
View File
@@ -0,0 +1,41 @@
#Requires -Version 5.1
Set-StrictMode -Version Latest
$ErrorActionPreference='Stop'
$root=[IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
Import-Module (Join-Path $root 'src/Wind.Network.psm1') -Force
$script:passed=0
function Assert-Capture([bool]$Condition,[string]$Message){if(-not$Condition){throw $Message};$script:passed++}
$state=Join-Path ([IO.Path]::GetTempPath()) ('ms-private-capture-test-'+[guid]::NewGuid().ToString('N'))
try{
$candidate=Join-Path $state 'capture-one'
$resolved=Resolve-WindCaptureDirectory -Path $candidate -StateRoot $state
Assert-Capture ($resolved-eq$candidate-and-not(Test-Path -LiteralPath $candidate)) 'Capture resolution created a directory or changed the target.'
foreach($invalid in @($state,($state+'-sibling\capture'),(Join-Path $state '..\outside'),'relative\capture','C:relative','\relative','\\server\share',($candidate+':stream'))){
$threw=$false;try{Resolve-WindCaptureDirectory -Path $invalid -StateRoot $state|Out-Null}catch{$threw=$true}
Assert-Capture $threw "Unsafe capture path accepted: $invalid"
}
[IO.Directory]::CreateDirectory($state)|Out-Null
$file=Join-Path $state 'file';[IO.File]::WriteAllText($file,'test')
$threw=$false;try{Resolve-WindCaptureDirectory -Path (Join-Path $file 'child') -StateRoot $state|Out-Null}catch{$threw=$true}
Assert-Capture $threw 'Capture path crossed an existing file.'
$calls=[Collections.Generic.List[string]]::new()
$runner={param($NativeArguments)$calls.Add(($NativeArguments-join'|'));0}.GetNewClosure()
Invoke-WindPacketMonitor -ArgumentList @('start','--file-name','path with spaces\capture.etl') -Runner $runner
Assert-Capture ($calls.Count-eq1-and$calls[0]-eq'start|--file-name|path with spaces\capture.etl') 'Packet monitor changed native argument boundaries.'
$threw=$false;try{Invoke-WindPacketMonitor -ArgumentList @('start') -Runner {23}}catch{$threw=$_.Exception.Message-match'exit code 23'}
Assert-Capture $threw 'Packet monitor failure was reported as success.'
$threw=$false;try{Invoke-WindPacketMonitor -ArgumentList @('stop') -Runner {}}catch{$threw=$true}
Assert-Capture $threw 'Missing packet monitor exit code was reported as success.'
# Real entry points must return before privilege checks, directory creation or native commands.
$preview=Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) ('MsPrivate\network\preview-test-'+[guid]::NewGuid().ToString('N'))
& (Join-Path $root 'Network.ps1') -Mode CaptureStart -CaptureDirectory $preview -WhatIf
& (Join-Path $root 'Network.ps1') -Mode CaptureStop -CaptureDirectory $preview -WhatIf
Assert-Capture (-not(Test-Path -LiteralPath $preview)) 'Capture preview created state on disk.'
}finally{
$full=[IO.Path]::GetFullPath($state);$temp=[IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd('\')+'\'
if(-not$full.StartsWith($temp,[StringComparison]::OrdinalIgnoreCase)){throw 'Unsafe test cleanup path.'}
if([IO.Directory]::Exists($full)){[IO.Directory]::Delete($full,$true)}
}
Write-Output "$script:passed capture tests passed. No packet capture or firewall change was performed."
+7 -9
View File
@@ -8,19 +8,17 @@ $script:passed=0
function Assert-Cleanup([bool]$Condition,[string]$Message){if(-not$Condition){throw $Message};$script:passed++}
try{
$files=Join-Path $scratch 'files';[IO.Directory]::CreateDirectory($files)|Out-Null
# Replace only the catalog in this module instance: all deletions stay in this test's directory.
& $module {
param($TestRoot)
$script:cleanupTestRoot=$TestRoot
function script:Get-WindPrivacyCleanupCatalog {
[pscustomobject]@{Category='Temp';Root=$script:cleanupTestRoot;Patterns=@('*');Recurse=$true}
}
} $files
# Use the production allowlist and an exact one-file plan; never scan or select other Temp files.
$tempRoot=[IO.Path]::GetFullPath([IO.Path]::GetTempPath()).TrimEnd('\')
$file=Join-Path $files 'sample.txt';$report=Join-Path $scratch 'report.json'
function New-TestCleanupPlan {
[IO.File]::WriteAllText($file,'original')
[IO.File]::SetLastWriteTimeUtc($file,[DateTime]::UtcNow.AddDays(-30))
Get-WindCleanupPlan -AgeDays 7 -Category Temp
$item=Get-Item -LiteralPath $file
[pscustomobject]@{
Schema=2;AgeDays=7;CutoffUtc=[DateTime]::UtcNow.AddDays(-7).ToString('o');Categories=@('Temp')
Files=@([pscustomobject]@{Path=$item.FullName;Root=$tempRoot;Category='Temp';Length=$item.Length;LastWriteUtc=$item.LastWriteTimeUtc.ToString('o')})
}
}
$plan=New-TestCleanupPlan