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:
@@ -44,16 +44,6 @@ function ConvertTo-SamsaraJson {
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SamsaraSafeExecutable {
|
||||
param([string]$Value)
|
||||
# Task action arguments, scripts and environment values are deliberately omitted.
|
||||
# Scheduler action values need not be valid filesystem paths. Path.GetFileName
|
||||
# throws on malformed/quoted values in .NET Framework (PowerShell 5.1).
|
||||
$name = (($Value -replace '\\', '/') -split '/')[-1]
|
||||
if ($name -match '^[A-Za-z0-9_. -]+\.(exe|com|cmd|bat|ps1|vbs|js|wsf|msc)$') { return $name }
|
||||
return '[executable name omitted]'
|
||||
}
|
||||
|
||||
function Invoke-SamsaraSection {
|
||||
param([string]$Name, [scriptblock]$Collector)
|
||||
$result = [ordered]@{
|
||||
@@ -84,3 +74,43 @@ function ConvertTo-SamsaraCheck {
|
||||
limitations = @($Section.limitations)
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SamsaraPrivacyConfiguration {
|
||||
if ($null -eq $script:SamsaraPrivacy) {
|
||||
$assets = Join-Path (Split-Path $PSScriptRoot -Parent) 'samsara\assets'
|
||||
$script:SamsaraPrivacy = Get-Content -LiteralPath (Join-Path $assets 'privacy_policy.json') -Raw -ErrorAction Stop | ConvertFrom-Json
|
||||
$script:SamsaraCatalogue = Get-Content -LiteralPath (Join-Path $assets 'privacy_catalogue.json') -Raw -ErrorAction Stop | ConvertFrom-Json
|
||||
if ($script:SamsaraPrivacy.version -ne '1.0') { throw 'Invalid privacy policy.' }
|
||||
}
|
||||
}
|
||||
|
||||
function Get-SamsaraPublicName {
|
||||
param([string]$Kind, [string]$Value, [int]$Index)
|
||||
Get-SamsaraPrivacyConfiguration
|
||||
$normalized = $Value.ToLowerInvariant() -replace '\.(exe|service)$', ''
|
||||
if ($Kind -eq 'services' -and $script:SamsaraPrivacy.approved_service_names -ccontains $Value) { return $Value }
|
||||
if ($Kind -eq 'products') {
|
||||
if ($script:SamsaraPrivacy.approved_software_names -ccontains $Value) { return $Value }
|
||||
foreach ($product in $script:SamsaraCatalogue.products) {
|
||||
if ($Value -match ('^' + [regex]::Escape($product) + '(?![A-Za-z0-9])')) { return $product }
|
||||
}
|
||||
} elseif ($script:SamsaraCatalogue.$Kind -contains $normalized) { return $normalized }
|
||||
if ($Kind -eq 'services') {
|
||||
foreach ($family in $script:SamsaraCatalogue.families.PSObject.Properties) {
|
||||
foreach ($prefix in $family.Value.prefixes) {
|
||||
if ($normalized.StartsWith($prefix, [StringComparison]::Ordinal)) { return $family.Value.representative }
|
||||
}
|
||||
}
|
||||
}
|
||||
return $Kind + '-' + $Index
|
||||
}
|
||||
|
||||
function Get-SamsaraApprovedRoot {
|
||||
param([string]$Value)
|
||||
Get-SamsaraPrivacyConfiguration
|
||||
if ($Value -notmatch '^[A-Za-z]:\\' -or $Value -match '(^|[\\/])\.\.([\\/]|$)' -or $Value -match '[\x00-\x1f]') { return 'Omitted by privacy policy' }
|
||||
foreach ($root in $script:SamsaraPrivacy.approved_share_roots) {
|
||||
if ($root -match '^[A-Za-z]:\\' -and $Value.TrimEnd([char]'\').Equals(([string]$root).TrimEnd([char]'\'), [StringComparison]::OrdinalIgnoreCase)) { return $Value }
|
||||
}
|
||||
return 'Omitted by privacy policy'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user