Privacy hardening, remote-peer IP masking and review fixes

- Add privacy projection (core/privacy.py), private report storage, bounded
  process capture; omit identities, free text and unapproved paths
- Mask remote peer IPs: only loopback/host/wildcard stay numeric, others are
  reduced to remote_scope private/public (schema + scoring updated)
- Map ss TCP states to canonical names; ASCII-only numeric fields; fix
  "Microsoft Visual C++" product matching (Python and PowerShell)
- Merge 7fed3b9: -Diagnostic switch, serialization exit code 3, PS7 module
  path, UI error detail; keep hardened task/certificate collectors
- Add audit docs, privacy docs and regression tests

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-04 18:50:24 -08:00
parent 7fed3b9ab9
commit 610a3bb447
51 changed files with 2719 additions and 604 deletions

View File

@@ -1,47 +1,30 @@
function Get-SamsaraStorage {
param($Result)
Invoke-SamsaraRead $Result 'Local volumes' {
$Result.data = @(Get-Volume -ErrorAction Stop | ForEach-Object {
[pscustomobject]@{ type = 'Volume'; name = [string]$_.FileSystemLabel
path = if ($_.DriveLetter) { [string]$_.DriveLetter + ':\' } else { [string]$_.Path }
Invoke-SamsaraRead $Result 'Fixed local disk metadata' {
$index = 0
$Result.data = @(Get-CimInstance -ClassName Win32_LogicalDisk -Filter 'DriveType = 3' -Property DeviceID,Size,FreeSpace,FileSystem -ErrorAction Stop | ForEach-Object {
$index++
[pscustomobject]@{ type = 'Volume'; name = 'Volume-' + $index
path = Get-SamsaraApprovedRoot (([string]$_.DeviceID) + '\')
filesystem = [string]$_.FileSystem; capacity_gib = [math]::Round(([double]$_.Size / 1GB), 2)
free_gib = [math]::Round(([double]$_.SizeRemaining / 1GB), 2) }
free_gib = [math]::Round(([double]$_.FreeSpace / 1GB), 2) }
})
}
$Result.limitations += 'Local volume metadata only. Share contents, mounted remote storage, storage-array dependencies, snapshots and backups are not inspected.'
$Result.status = 'partial'
$Result.limitations += 'Fixed drive-letter disks only; labels and child paths not read. Mount-only volumes and external storage dependencies need review.'
}
function Get-SamsaraShares {
param($Result)
Invoke-SamsaraRead $Result 'SMB shares' {
Invoke-SamsaraRead $Result 'Configured SMB share roots' {
$index = 0
$Result.data = @(Get-SmbShare -ErrorAction Stop | ForEach-Object {
[pscustomobject]@{ type = 'SMB Share'; name = [string]$_.Name; path = [string]$_.Path
$index++
$name = if ([string]$_.Name -match '^(ADMIN|IPC|[A-Z])\$$') { ([string]$_.Name).ToUpperInvariant() } else { 'Share-' + $index }
[pscustomobject]@{ type = 'SMB Share'; name = $name; path = Get-SamsaraApprovedRoot ([string]$_.Path)
capacity_gib = $null; free_gib = $null; special = [bool]$_.Special }
})
}
Invoke-SamsaraRead $Result 'SMB open-file activity' {
$openFiles = @(Get-SmbOpenFile -ErrorAction Stop)
$observedAt = Get-SamsaraTimestamp
foreach ($share in $Result.data) {
if ($share.name -match '^(ADMIN|IPC|[A-Z])\$$' -or -not $share.path) { continue }
$prefix = $share.path.TrimEnd([char]'\') + '\'
$matching = @($openFiles | Where-Object {
# Path alone also matches a file opened through C$/D$. Require
# Path = share root + ShareRelativePath to distinguish that case.
$_.Path -and $_.ShareRelativePath -and
([string]$_.Path).Equals(($prefix + ([string]$_.ShareRelativePath).TrimStart([char]'\')), [StringComparison]::OrdinalIgnoreCase)
})
$adminAliases = @($Result.data | Where-Object {
$_.name -match '^(ADMIN|IPC|[A-Z])\$$' -and ([string]$_.path).TrimEnd([char]'\').Equals($share.path.TrimEnd([char]'\'), [StringComparison]::OrdinalIgnoreCase)
})
# Only aggregated, path-correlated activity is exported. Never serialize
# open-file objects, file names, session identities or user names.
$share | Add-Member -NotePropertyName observed_open_files -NotePropertyValue $matching.Count
$clients = @($matching | Select-Object -ExpandProperty ClientComputerName -Unique)
$share | Add-Member -NotePropertyName observed_client_count -NotePropertyValue $clients.Count
$share | Add-Member -NotePropertyName activity_source -NotePropertyValue $(if ($adminAliases.Count) { 'Get-SmbOpenFile (administrative alias ambiguous)' } else { 'Get-SmbOpenFile (share-root-correlated)' })
$share | Add-Member -NotePropertyName activity_observed_at -NotePropertyValue $observedAt
}
}
$Result.limitations += 'Configured SMB shares, including administrative shares, and aggregate open-file counts share-root-correlated to business shares. No file contents, open-file paths, session identities, ACLs or credentials are exported. Zero open files does not prove a share unused. Same-root aliases are not individually distinguishable; an administrative same-root alias is marked ambiguous and never confirms business-share use. All business shares remain one workload group.'
$Result.status = 'partial'
$Result.limitations += 'Configured roots only; exact approved local roots may be retained. No file enumeration, open-file activity, filenames, child paths, sessions or client identities are queried. Active share consumers remain unverified.'
}