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:
@@ -1,3 +1,7 @@
|
||||
# Current security behavior
|
||||
|
||||
The privacy hardening in [PRIVACY_HARDENING.md](PRIVACY_HARDENING.md) supersedes the earlier collector/export descriptions below. Default collection omits accounts, task commands and triggers, certificate enumeration, SMB open-file activity and cron commands. Imports, UI, analysis and reports use `core/privacy.py`; exports use `core/storage.py`. Reports no longer preserve raw inventory or create raw sidecars. `core/process.py` uses bounded memory instead of temporary stdout files. Pin changes do not replace native Windows/supply-chain validation. Earlier architecture notes follow as implementation history.
|
||||
|
||||
# Developer guide
|
||||
|
||||
Use Python 3.11+ and requirements.txt. Run `python -m samsara.main` from the repository root. The desktop requires a Qt-capable graphical session; tests run offscreen.
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Privacy hardening changes current collector coverage and output requirements. Read [PRIVACY_HARDENING.md](PRIVACY_HARDENING.md) first: certificates, task action/trigger data, cron commands and SMB open-file queries are disabled by default; the Windows output root requires protected ACLs. Current Windows runtime validation remains pending. Historical platform notes below do not override these restrictions.
|
||||
|
||||
# Platform support
|
||||
|
||||
Samsara targets retirement assessment of Windows Server 2016/2019/2022/2025 and enterprise Linux. Collector availability and tested platform support are different claims.
|
||||
|
||||
202
docs/PRIVACY_HARDENING.md
Normal file
202
docs/PRIVACY_HARDENING.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# Privacy hardening and production acceptance
|
||||
|
||||
This document describes implemented controls, not a HIPAA compliance determination.
|
||||
The documents in `audit/` remain the historical audit of the earlier source snapshot.
|
||||
Do not replace their findings with an unsupported claim that all issues are resolved.
|
||||
|
||||
## What changed
|
||||
|
||||
- A new `core/privacy.py` builds an explicit field projection before results reach Qt,
|
||||
analysis/history, imports, HTML, JSON, and local CLI output. Export recomputes
|
||||
findings from minimized inventory; old findings and a privacy marker cannot bypass
|
||||
the filter. Unexpected schema fields are rejected at import; legacy command fields
|
||||
are accepted only to discard them. Timestamps are checked without optional plugins.
|
||||
- Host/domain/adapter identities, accounts, display descriptions, custom service,
|
||||
software and task names, certificate identities and unapproved paths are omitted
|
||||
or replaced with assessment-local numbered labels. Known application families,
|
||||
OS family/version/build, role identifiers, states, PIDs, ports, numeric IPs,
|
||||
storage capacities, row counts, timestamps and categorical errors remain useful.
|
||||
Unknown software is not automatically interpreted as inactive or harmless.
|
||||
- Windows queries no longer request service account/display-name fields. Task CIM
|
||||
queries request only TaskName, TaskPath and State; actions, arguments, principals,
|
||||
triggers and task XML are not requested. Disk queries omit volume labels.
|
||||
Registry reads disable environment expansion and omit publisher/install-date text.
|
||||
The PowerShell modules project names and paths before emitting JSON.
|
||||
- Certificate enumeration and SMB open-file/session enumeration are disabled.
|
||||
Certificates are explicitly `not_collected`; tasks, storage and shares have
|
||||
partial scope. Share consumers and schedule timing must be verified separately.
|
||||
Existing imported aggregate share counts can still support a finding, but their
|
||||
provenance is unverified. They do not cause the new collector to enumerate files.
|
||||
- Linux default collection no longer reads cron command files or detailed systemd
|
||||
timer properties. Timer state remains available; commands and timings need a
|
||||
separate approved scheduler review. Existing schedule parsers are retained for
|
||||
synthetic tests, but are not called by the default collection workflow.
|
||||
- Supervised collector stdout uses bounded memory pipes instead of inventory
|
||||
temporary files. Stderr is discarded. Windows child environment has an explicit
|
||||
small allowlist instead of copying all environment variables. Timeouts,
|
||||
cancellation and overflow terminate/reap the owned process.
|
||||
- Reports contain minimized data only. HTML does not create raw sidecars. Output
|
||||
is exclusive (no overwrite), restricted to the configured local report root, and
|
||||
checks common network mounts, symlinks and Windows reparse points. POSIX root
|
||||
mode is 0700 and files 0600. Windows roots require a protected DACL allowing only
|
||||
the owner, SYSTEM and Administrators; child ACLs are checked before payload write.
|
||||
No automatic privilege elevation or existing ACL changes are performed.
|
||||
- History retains at most ten assessments by default, and has a clear action.
|
||||
Clearing references is not secure memory erasure. Existing exported files are not
|
||||
automatically deleted. Scoring-policy titles are canonicalized to prevent a
|
||||
second free-text report channel.
|
||||
- Requirements now use the Widgets-capable `PySide6_Essentials`, rather than the
|
||||
umbrella package that pulls in WebEngine, PDF and Addons. Direct versions are
|
||||
pinned; observed development transitive constraints are recorded separately.
|
||||
|
||||
- Remote peer IP addresses are masked: only loopback, this host's own and wildcard
|
||||
addresses stay numeric; every other peer is reduced to `remote_scope` `private` or
|
||||
`public`, because client IPs on patient-facing servers can be identifiers. Local
|
||||
listener addresses and the host's own IPs are still retained.
|
||||
|
||||
## Configure approved metadata and report storage
|
||||
|
||||
Deployment administrators review and protect these bundled files against untrusted
|
||||
changes: `samsara/assets/privacy_policy.json` and `privacy_catalogue.json`. The
|
||||
catalogue is a finite vocabulary of infrastructure names, not executable code.
|
||||
Keep the checkout, Python environment and scripts protected by deployment controls.
|
||||
An attacker who can replace application code/policy is outside this boundary.
|
||||
|
||||
The policy defaults to no approved names/paths and an application-local `reports`
|
||||
folder. This is a laboratory default, not a CHS-approved production location. Set
|
||||
`report_directory` to an approved **absolute local** directory for deployment.
|
||||
Only files directly inside it can be saved; choose a new `.html` or `.json` filename.
|
||||
Do not put the directory under OneDrive, another sync client, a network mount or an
|
||||
unreviewed backup policy. Encrypted local storage and access/retention policy remain
|
||||
organizational requirements.
|
||||
|
||||
For example, a reviewed Windows configuration may include:
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"report_directory": "C:\\SamsaraReports",
|
||||
"approved_hostnames": [],
|
||||
"approved_share_roots": ["D:\\DepartmentShares"],
|
||||
"approved_service_names": [],
|
||||
"approved_software_names": [],
|
||||
"max_session_assessments": 10
|
||||
}
|
||||
```
|
||||
|
||||
This preserves **only the exact configured root** `D:\DepartmentShares`. It does
|
||||
not authorize any child path, filename or file-content scan. Empty allowlists are
|
||||
preferred. Add an exact hostname/custom service/software name only after privacy
|
||||
review establishes it is approved infrastructure metadata. There is no automatic
|
||||
patient-name detector: neither a path nor a free-text name can be proven safe from
|
||||
its format. Known product names are canonicalized without retaining custom suffixes.
|
||||
|
||||
On Linux, the configured root is created with mode 0700 if its parent already
|
||||
exists. An existing root with group/other permissions is rejected. Fix permissions
|
||||
on the report directory only after checking that it is the intended directory.
|
||||
|
||||
On Windows, provision a **new** local folder before exporting. The following is a
|
||||
manual setup example to be reviewed under the organization's normal approval
|
||||
process, not an action the collector performs on assessed infrastructure:
|
||||
|
||||
```powershell
|
||||
$reportRoot = 'C:\SamsaraReports'
|
||||
if (Test-Path -LiteralPath $reportRoot) { throw 'Choose a new report directory.' }
|
||||
$null = New-Item -ItemType Directory -Path $reportRoot
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
try {
|
||||
$acl = New-Object Security.AccessControl.DirectorySecurity
|
||||
$acl.SetOwner($identity.User)
|
||||
$acl.SetAccessRuleProtection($true, $false)
|
||||
foreach ($sid in @($identity.User, [Security.Principal.SecurityIdentifier]::new('S-1-5-18'), [Security.Principal.SecurityIdentifier]::new('S-1-5-32-544'))) {
|
||||
$rule = [Security.AccessControl.FileSystemAccessRule]::new($sid, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
|
||||
$acl.AddAccessRule($rule)
|
||||
}
|
||||
Set-Acl -LiteralPath $reportRoot -AclObject $acl
|
||||
} finally { $identity.Dispose() }
|
||||
```
|
||||
|
||||
These commands change the chosen **local output folder's** ACL and must not be run
|
||||
against data shares. Configure the matching path in the policy. The ctypes ACL
|
||||
reader and inheritance behavior are implemented but **not tested on Windows here**.
|
||||
Before production, verify both allowed and denied cases, inherited file ACLs,
|
||||
standard-user access, reparse/mapped-drive rejection and directory replacement
|
||||
races on each intended Windows execution environment. Export fails closed when it
|
||||
cannot establish the configured checks; absence of an exception is not a complete
|
||||
filesystem-security attestation.
|
||||
|
||||
## Limits and unresolved production blockers
|
||||
|
||||
1. **No PHI-free guarantee.** Names/paths returned by CIM, Get-SmbShare, process
|
||||
listings and registry values can enter collector memory before reduction.
|
||||
Legacy JSON is parsed in memory before filtering. Explicit properties reduce
|
||||
requested fields but provider internals are unverified. Approved names/roots
|
||||
and retained numeric IPs can themselves be sensitive in organizational context.
|
||||
2. **No absolute read-only OS guarantee.** Application collection commands request
|
||||
reads, not infrastructure changes. Native providers/OS can write audit logs,
|
||||
caches or other incidental state. Python bytecode, OS paging/crash dumps, Qt and
|
||||
endpoint tools are outside the no-inventory-spool control. A bounded buffer is
|
||||
not secure memory. Disable/restrict crash dumps and use encrypted storage under
|
||||
organizational policy, rather than claiming that data never touch disk.
|
||||
3. **No complete egress guarantee.** There is no first-party upload, telemetry or
|
||||
remote collector. Filesystem checks reject common remote paths but cannot prove
|
||||
a disk has no cloud-sync/backup/virtualized backend. Native Windows providers,
|
||||
revocation behavior, domain services and OS integrations need monitored host
|
||||
validation. Use enterprise egress policy and approved local output storage.
|
||||
4. **Runtime validation outstanding.** No Windows execution host or PowerShell
|
||||
runtime was available. Revised CIM projections, least-privilege visibility,
|
||||
native synthetic tests and output ACL enforcement must pass on approved lab
|
||||
hosts. Do not substitute synthetic Python results for that evidence.
|
||||
5. **Supply chain approval outstanding.** No vulnerability database queries,
|
||||
package installations/updates or external transmissions were performed. Direct
|
||||
pins/observed constraints are not a hash-verified platform lockfile, complete
|
||||
native SBOM, signed release or CVE clearance. Existing development environments
|
||||
may still contain the former Qt umbrella/Addons packages; changing requirements
|
||||
does not uninstall them. Build clean environments through approved provisioning.
|
||||
6. **Organizational review outstanding.** CHS security/privacy approval, least-
|
||||
privilege grants, retention/deletion policy, approved metadata, endpoint and
|
||||
backup controls, incident response and HIPAA determination remain external
|
||||
acceptance gates. A low retirement score always needs historical validation,
|
||||
application ownership and administrator approval.
|
||||
|
||||
Do not import known patient-bearing legacy inventories into this tool merely to
|
||||
redact them. Have the data owner handle those artifacts using approved procedures.
|
||||
Old reports/sidecars/bundles are not scrubbed or removed by this change. The
|
||||
historical `Samsara.bundle`, if present, may predate these controls; distribute a
|
||||
reviewed build of the current source rather than an older archive.
|
||||
|
||||
## Verification and later authorized supply-chain checks
|
||||
|
||||
Run synthetic/offscreen tests from the repository root:
|
||||
|
||||
```bash
|
||||
QT_QPA_PLATFORM=offscreen .venv/bin/python -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
On an authorized Windows **lab** Server with an approved report directory:
|
||||
|
||||
```bat
|
||||
.venv\Scripts\python.exe -m unittest discover -s tests -v
|
||||
.venv\Scripts\python.exe tools\validate_windows_host.py --output-dir C:\SamsaraReports
|
||||
```
|
||||
|
||||
The second command performs a real assessment of the execution host; it is not a
|
||||
synthetic test. No real Windows host has been assessed during this change.
|
||||
|
||||
After obtaining approval for tooling/downloads and advisory-database access, in a
|
||||
separate release environment use, for example:
|
||||
|
||||
```bash
|
||||
python -m piptools compile --generate-hashes --output-file requirements.lock requirements.txt
|
||||
python -m pip install --require-hashes -r requirements.lock
|
||||
python -m pip_audit -r requirements.lock --format json --output vulnerability-results.json
|
||||
cyclonedx-py environment --output-format JSON --output-file sbom.cdx.json
|
||||
```
|
||||
|
||||
Repeat lock generation/clean installs for each target Python/OS/architecture.
|
||||
Inventory Qt native libraries/plugins and PowerShell/OS modules as well; a Python
|
||||
package SBOM alone is incomplete. SBOM/advisory checks can expose package metadata
|
||||
externally: do not run them against production inventory or without authorization.
|
||||
Triage findings against actual packages, keep advisory timestamps, sign the
|
||||
reviewed distribution, and retain acceptance evidence. These commands have not
|
||||
been run as part of the hardening work.
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
The previous engine added points for every running service, installed role, listener, connection and administrative share. A routine Windows snapshot could accumulate thousands of raw points and saturate at Critical. Model v2 removes that inventory-counting behavior. Collection schema remains v1; assessment metadata is versioned separately as `model_version: 2.0`.
|
||||
|
||||
Re-analyze a previous JSON report through **Analyze → Saved inventory file**. Its raw inventory and collection time are retained; the old assessment is ignored and a v2 assessment is calculated with the selected policy. No new Windows access is needed to re-score existing evidence. Imported data remain explicitly unverified. Old HTML scores do not change; generate a new report. Scores from v1 and v2 are not directly comparable.
|
||||
Re-analyze a previous JSON report through **Analyze → Saved inventory file**. Its inventory is minimized under the privacy policy and its collection time retained; the old assessment is ignored and a v2 assessment is calculated with the selected policy. No new Windows access is needed to re-score existing evidence. Imported data remain explicitly unverified. Old HTML scores do not change; generate a new report. Scores from v1 and v2 are not directly comparable.
|
||||
|
||||
## Evidence classifications
|
||||
|
||||
@@ -58,8 +58,4 @@ Historical monitoring over a representative business cycle, infrequent workloads
|
||||
|
||||
## Reporting and validation
|
||||
|
||||
HTML leads with actionable workload groups, scoring rationale, confidence and missing checks. Routine inventory is summarized in zero-point context groups rather than repeated as medium-risk dependencies. A content-addressed `.inventory-<hash>.json` sidecar preserves every collected inventory row; its SHA-256 and link are in the report. Keep it with the HTML. JSON assessment export also retains full inventory, model/policy and detailed observations. Existing different sidecars are never overwritten.
|
||||
|
||||
Regression fixtures cover a clean Windows Server, an inactive former game server, active SQL, active IIS, a domain controller, business file-share use and incomplete collection. An additional regression reconstructs the reported 1,565-point pattern (86 services, 19 connections, 14 features, 23 listeners, three admin shares and two failed checks): v2 gives zero workload risk and reduced confidence, while retaining all observations. This is a synthetic reproduction of the supplied counts, not a replay of an unavailable original inventory file.
|
||||
|
||||
These tests do not certify business dependency discovery. Re-score the real test server's saved JSON, review results with its owner, and validate any new SMB activity fields on Windows. Native PowerShell tests remain skipped in the Linux development environment.
|
||||
HTML leads with actionable workload groups, scoring rationale, confidence and missing checks. Routine inventory is summarized in zero-point context groups rather than repeated as medium-risk dependencies. HTML no longer creates raw inventory sidecars. JSON contains only privacy-minimized evidence, model/policy and observations recomputed from that evidence. This changes the earlier raw-preservation behavior deliberately. Existing raw artifacts are not deleted or scrubbed; handle them under organizational retention/privacy policy. See [privacy hardening](PRIVACY_HARDENING.md).
|
||||
|
||||
52
docs/SECURITY_REMEDIATION_STATUS.md
Normal file
52
docs/SECURITY_REMEDIATION_STATUS.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Security remediation status — 2026-10-30
|
||||
|
||||
This is an implementation follow-up to the unchanged historical `audit/` documents.
|
||||
It is not a new comprehensive audit, vulnerability scan or production approval.
|
||||
|
||||
| Audit finding | Implemented change | Remaining acceptance requirement |
|
||||
| --- | --- | --- |
|
||||
| S01 — PHI-capable free text | Explicit projection, opaque labels/canonical products, exact reviewed allowlists before UI/history/export; stale findings discarded | CHS approves retained fields/roots/IPs; metadata can enter source/import memory; no PHI-free assurance |
|
||||
| S02 — Broad provider objects | No default certificates/open files; task fields narrowed; service account/descriptions and disk labels no longer requested | Windows CIM/provider behavior and permissions must be lab-tested; provider internals not established |
|
||||
| S03 — Raw retention | No raw sidecar; JSON minimized; bounded session history and clear action | Review legacy artifacts, retention/deletion, memory dumps, encrypted storage and endpoint backups |
|
||||
| S04 — Output boundaries | Configured private local root, no overwrite, mode 0700/0600, Windows DACL gate, remote/link rejection | Windows ACL/race tests; CHS-approved root/backup/sync policy; unusual backing storage remains unverified |
|
||||
| S05 — Temporary stdout | Bounded in-memory pipe, sanitized failure codes, discard stderr, terminate/reap owned process | OS swap/dumps/cache/log policy and native-child behavior review; memory is not secure-erased |
|
||||
| S06 — Environment/registry | Small child environment allowlist; registry DoNotExpandEnvironmentNames; no stored credentials | Trusted interpreter/runtime deployment, inherited indispensable environment and native module behavior review |
|
||||
| S07 — Supply chain | Minimal Qt Essentials; direct version pins and observed transitive constraints | Hash/platform locks, complete native SBOM, authorized advisory scan and signed reproducible release still outstanding |
|
||||
| S08 — Contracts | Closed nested schema, bounded rows/strings/depth, independent timestamp validation, repeated export projection | Fuzzing/resource stress and untrusted file race review; legacy input still read before reduction |
|
||||
| S09 — Egress | No first-party upload added; reject common remote import/output paths before filesystem probes | Monitored Windows/native egress tests, enterprise firewall and approved storage controls |
|
||||
| S10 — Read-only/least privilege | Collection remains read/query operations; no elevation/remoting/configuration added; output writes isolated | Native read side effects, standard-user filtering, each supported Server OS, CHS least-privilege approval |
|
||||
|
||||
## Test evidence
|
||||
|
||||
`QT_QPA_PLATFORM=offscreen .venv/bin/python -m unittest discover -s tests -v`
|
||||
discovered 71 tests on the Linux development host: 70 passed and one native
|
||||
PowerShell test was skipped. Python, synthetic regression, GUI and report tests
|
||||
passed. Native PowerShell AST/mocked collector tests are skipped because no PowerShell
|
||||
runtime exists here. No real Windows collection, installation/update, vulnerability
|
||||
lookup, production access or network transmission was performed.
|
||||
|
||||
New regression cases verify canary removal across major free-text surfaces and old
|
||||
findings, schema/marker bypass rejection, exact-root approval excluding descendants,
|
||||
private/exclusive output, memory capture limits and cleanup, and bounded/cleared UI
|
||||
history. Seven workload scenarios retain scores 0/0/70/70/95/80/0 after projection.
|
||||
The 80-point file-server case uses **imported synthetic historical aggregates**;
|
||||
the new live default collector does not query SMB open-file activity and cannot
|
||||
create that evidence itself.
|
||||
|
||||
## Release gates
|
||||
|
||||
1. Review the actual release provenance. The workspace has no usable `.git` checkout;
|
||||
the historical bundle is not updated by these source edits. Earlier upstream
|
||||
`7fed3b9` cannot be verified as included without an authorized source reconciliation.
|
||||
2. Obtain native Windows lab results, including revised task-CIM queries, registry
|
||||
read-only behavior, service/role projection, cancellation and output permissions.
|
||||
3. Build clean target environments with verified dependencies, hash locks, native
|
||||
SBOM, advisory results and release signing. Existing broad Qt installations are
|
||||
not changed by editing requirements.
|
||||
4. CHS security/privacy owners approve the reduced dataset and document residual
|
||||
PHI possibilities, dedicated least-privilege access, encryption/storage, egress,
|
||||
retention, audit logging and incident response. HIPAA status is an organizational
|
||||
determination, not an application-generated pass/fail badge.
|
||||
|
||||
No source fix alone clears these gates. See [the deployment guide](PRIVACY_HARDENING.md)
|
||||
for exact configuration, manual output-folder provisioning and authorized lab checks.
|
||||
@@ -1,3 +1,8 @@
|
||||
> **Superseded in part:** the privacy hardening (see `PRIVACY_HARDENING.md`) disables certificate
|
||||
> enumeration and narrows task collection to name/path/state. The task and certificate
|
||||
> collector behavior described below no longer applies; the diagnostic switch, exit-code 3
|
||||
> serialization handling and PowerShell 7 module path remain in effect.
|
||||
|
||||
# Windows collector reliability validation — 2026-10-30
|
||||
|
||||
## Root causes
|
||||
|
||||
Reference in New Issue
Block a user