# Read-only, write-path and least-privilege verification **Method:** static source trace only, 2026-10-30. No operations listed below were executed against an assessed host. Labels describe actual invoked APIs and selected properties, not an assumption based on function names. Native provider/cache/logging effects remain **Unverified**. ## Definitions and conclusion - **R:** an explicit metadata/configuration read with no source-requested target mutation. - **O:** user-requested report/diagnostic output write. Allowed by the requested audit model only when the destination is approved; the app does not enforce that approval. - **T:** temporary/cache/resource lifecycle write; not a server configuration change, but incompatible with a literal zero-write claim. - **P:** in-process state change or collector-process creation/termination; not a service/task/registry configuration change. - **U:** native/external side effects not established by static inspection. **Configuration read-only intent: Pass, narrowly scoped to the reviewed first-party commands. Fully read-only/zero-state-change assurance: Unverified, and a literal no-filesystem-write claim is contradicted by T/O paths.** Because Windows collection is local, execution host and assessed server are the same machine. Calling a file write “local” does not make it separate infrastructure. No confirmed intentional persistent service/task/registry/certificate modification was identified. ## Windows command/API register | File / function / source lines | Invocation and execution condition | Class | Assessed-state effect / caveat | | --- | --- | --- | --- | | `powershell/Get-ServerSystem.ps1:4`, `Get-SamsaraSystem` | `[Environment]::MachineName` during system section | R | Local identity read; not network discovery. | | `powershell/Get-ServerSystem.ps1:11-21` | `Get-CimInstance Win32_OperatingSystem` with explicit properties | R/U | Read caption/build/product type/boot. No `Invoke-CimMethod`. Provider/OS audit/cache effects unverified. | | `powershell/Get-ServerSystem.ps1:24-26` | `Get-CimInstance Win32_ComputerSystem -Property Domain,PartOfDomain` | R/U | Local domain-membership metadata, no AD configuration or remoting parameters. | | `powershell/Get-ServerSystem.ps1:29-31` | `Get-CimInstance Win32_NetworkAdapterConfiguration -Filter 'IPEnabled = True'` | R/U | Addresses/descriptions only; no adapter methods or setters. | | `powershell/Get-ServerRoles.ps1:4-7`, `Get-SamsaraRoles` | `Get-WindowsFeature`, installed filter | R/U | No feature installation/removal. ServerManager servicing/log/cache behavior must be measured, not presumed absent. | | `powershell/Get-ServerServices.ps1:5-8`, `Get-SamsaraServices` | `Get-CimInstance Win32_Service` explicit metadata properties | R/U | No service methods, configuration, start/stop/restart calls. PathName not requested. | | `powershell/Get-ServerNetwork.ps1:5`, `Get-SamsaraNetwork` | `Get-Process` then Id/ProcessName projection | R/U | No process command lines, process injection or termination; process enumeration can race exits. | | `powershell/Get-ServerNetwork.ps1:8-13` | `Get-NetTCPConnection` | R/U | Reads TCP table; no socket connection/listen/probe is initiated by source. Cmdlet has broader capability, but no remote session parameter is supplied. | | `powershell/Get-ServerTasks.ps1:4-17`, `Get-SamsaraTasks` | `Get-ScheduledTask`; inspect settings/principal/actions/triggers | R/U | No register/unregister/enable/disable/start/set task. Retrieves definitions, not clinical data by intent; privacy implications remain. | | `powershell/Get-ServerSoftware.ps1:22-32`, `Get-SamsaraSoftware` | `RegistryKey.OpenBaseKey(HKLM, Registry64/Registry32)`, `OpenSubKey(...,$false)` | R | Child keys explicitly opened non-writable. No SetValue/CreateSubKey/DeleteSubKey. Default value-expansion behavior is a privacy caveat, not registry mutation. | | `powershell/Get-ServerSoftware.ps1:3-15`, `Read-SamsaraSoftwareEntries` | GetSubKeyNames/OpenSubKey(false)/GetValue; Dispose handles | R/P | Read four named values; close handles. No installer invocation and no `Win32_Product`. Handle disposal does not delete keys. | | `powershell/Get-ServerStorage.ps1:4-9`, `Get-SamsaraStorage` | `Get-Volume` metadata/capacity | R/U | No volume/mount/partition resize or format. Storage-provider/SAN/cache effects are not verified. | | `powershell/Get-ServerStorage.ps1:17-20`, `Get-SamsaraShares` | `Get-SmbShare` | R/U | No share/ACL creation/removal/change; only configuration metadata. | | `powershell/Get-ServerStorage.ps1:23-43` | `Get-SmbOpenFile`; match paths and compute counts | R/U | Reads open-file metadata; does not call Close/ForceClose/Open on client files or read file contents. Broad PHI-capable metadata acquisition still occurs. | | `powershell/Get-ServerCertificates.ps1:5-13`, `Get-SamsaraCertificates` | `Get-ChildItem Cert:\LocalMachine` and returned stores | R/U | No Import/Export-PfxCertificate/Remove-Item or key/store setters. Only selected public metadata is accessed by source; provider behavior not instrumented. | | `powershell/Get-ServerInventory.ps1:9-10` | Assign child process PSModulePath; set Console.OutputEncoding using `New-Object UTF8Encoding` | P | Process environment/encoding change, not registry/system configuration. Direct invocation also changes these within the hosting PowerShell process's session scope; no persistent environment setter. | | `powershell/Get-ServerInventory.ps1:19-23` | GetCurrent WindowsIdentity, construct WindowsPrincipal, IsInRole; Dispose | R/P | Inspects existing token, no UAC launch, LogonUser, credential acquisition or privilege enablement. Disposes an identity handle. | | `powershell/Get-ServerInventory.ps1:15-17` | Dot-source fixed module filenames under PSScriptRoot | P/U | Executes trusted-on-deployment code; no authentication/hash validation of that code in source. A substituted script is not constrained by metadata-read intentions. | | `powershell/Inventory.Common.ps1:20-26`, `:37-55` | Invoke a scriptblock chosen by fixed collector map | P | Not user command interpolation. Its safety depends on reviewed code/deployment integrity. | | `powershell/Get-ServerStorage.ps1:39-43` | `Add-Member` on collected PSCustomObjects | P | Mutates in-memory result objects, not SMB shares or infrastructure. | | `powershell/Inventory.Common.ps1:4-18`, `:58-65`; driver `:33`, `:53-56` | Build safe diagnostics, ConvertTo-Json, stdout/stderr, exit | P/O/U | Serialized stdout is data output; parent directs it to temp file. Direct-host transcripts/redirects may persist it; no app-controlled logging policy. | **Negative scan, bounded conclusion:** no source call to `Set-ItemProperty`, `Set-Content` against assessed configuration, `Set-Service`, `Start-Service`, `Stop-Service`, `Restart-Service`, `Register-ScheduledTask`, `Set-ScheduledTask`, `Remove-Item` against stores, `Enable-PSRemoting`, `Set-ExecutionPolicy`, `Invoke-CimMethod`, `Invoke-WebRequest`, `Invoke-RestMethod`, `Invoke-Command` or session creation was found in the production collectors. `New-Object` and `Add-Member` hits above are memory operations, not evidence of persistent infrastructure writes. A scan is not proof of native provider behavior or protection against a tampered checkout. ## Python execution and all first-party write/state-change paths | File / function / lines | What can change | Condition, impact and safeguards | | --- | --- | --- | | `samsara/collectors/windows.py:35-48`, `powershell_executable` | R: GetSystemDirectoryW, file-existence checks | Validates Windows/64-bit Python and derives system PowerShell path instead of PATH/SystemRoot. No installation. Loaded executable/native signatures not checked by app. | | `samsara/collectors/windows.py:51-64`, `run_section` | P/T: copy environment, create TemporaryFile, launch PowerShell | Every local Windows section. Fixed argument list, fixed section enum, absolute driver, NoProfile/NonInteractive, shell=False, limited PSModulePath. Full other environment inherited. Temp data written before projection. | | `samsara/collectors/windows.py:69-92` | T/P: stdout writes, kill collector process, wait/reap, close/delete temp resource | Polls timeout/cancellation/output size. No target service PID is used for termination; kill acts on the `Popen` handle created by this function. Does not establish that provider services/caches are unaffected. Limits can overshoot between polls. | | `samsara/collectors/windows.py:178-189`, `main` | O: create JSON file, write full inventory | Explicit `--output`; `open(...,'x')` rejects an existing file. No approved-root/ACL/network-path enforcement. Does not create parent directories itself. | | `samsara/collectors/linux.py:20-53`, `run_command` | P/T: create temp output, launch fixed utility, kill/wait, cleanup | Local Linux checks. Selects executable from system directories and supplies minimal environment, shell=False. Public helper accepts an argument list, but production callers supply fixed commands; no UI command text is executed. Symlink/binary integrity is deployment responsibility. | | `samsara/collectors/linux.py:198-211`, `main` | O: exclusive JSON file creation/write | User-requested CLI output with same destination-policy gap. | | `samsara/reporting/export.py:15-16`, `export_json` | O: create or truncate JSON output | GUI/API caller supplies path; follows ordinary OS path resolution. No file extension, approved-root, ACL, no-follow or encryption enforcement in this function. | | `samsara/reporting/export.py:19-29`, `inventory_artifact` | O/R: create sidecar with `xb`, write bytes, or read existing sidecar for comparison | Automatic on HTML export, not an independent raw-export consent. Refuses a differing existing artifact. Existing-file read has no size/no-follow restriction. Hash checks content equality, not publisher authenticity or privacy. | | `samsara/reporting/export.py:39-41`, `:86`, `export_html` | O: sidecar then create/truncate HTML | Report destination user-selected. Writes are non-transactional; a failure after sidecar creation can leave that file behind. HTML can overwrite an existing path; no symlink/reparse or approved-root policy. | | `tools/validate_windows_host.py:20-31`, `:43-45`, `main` | O: mkdir parents, JSON/HTML/sidecar, summary file; terminal output | Manual validation invocation on a supported host. Directory existence checked before long collection then mkdir(exist_ok=False); ancestor links/network paths remain possible. Summary excludes direct identifiers but still requires classification. | | `samsara/ui/branding.py:9-17`, `configure_taskbar_identity` | P: SetCurrentProcessExplicitAppUserModelID | Windows GUI startup. Changes process/shell identity only; no source request to write registry/shortcuts. Native shell side effects not measured. | | `samsara/main.py:10-20`, UI callbacks `samsara/ui/window.py:361-408` | P/U: Qt objects, threads/event loop, queued data, history, dialogs | GUI startup/Analyze actions. `app.exec()` is an event loop, not Python `exec`. Qt signal `.connect` calls are callbacks, not network connects. Native plugin/cache/portal behavior unverified. | | `samsara/ui/window.py:401-479` | P: retain data/history, build widgets, deleteLater | Session results retained without a bounded retention/privacy-clear control. deleteLater is widget lifecycle, not file deletion or evidence of secure memory erasure. | | `samsara/core/startup.py:7-20` | R/U: inspect display variables, dynamically load cursor library | May print an installation suggestion. Does **not** execute sudo/apt. Native library initialization/search-path behavior not verified here. | | Python imports/runtime, no explicit first-party line invoking write | T/U: possible bytecode/native/font/module-analysis caches, logs/dumps/pagefile | Ordinary app launches are not configured with `-B`/a no-cache policy. Whether these writes occur on a given host is unverified. Source only cannot promise zero OS writes. | | README setup commands (`README.md:8-13`, `:42-45`, `:56-60`, `:67-70`) | Manual environment/package creation/downloads, mkdir, direct WriteAllText | These are instructions, not automatic application behavior. `[IO.File]::WriteAllText` can overwrite; pip/venv install modifies the host if an operator runs it. Never silently include setup in a read-only production assessment claim. | No first-party production `chmod`, ACL setter, registry setter, system service/task/certificate modifier, arbitrary shell execution, automatic software installer or credential store was identified. All file writes above remain significant because approved output directories are not actually enforced. ## Linux utility/read register | Source | Invocation / read | Classification and caveat | | --- | --- | --- | | `samsara/collectors/linux.py:106`, `:131-145` | socket.gethostname; `/etc/os-release`, `/proc/stat`; `ip -j address show` | R; no explicit DNS or socket connection. Utility/OS side effects unverified. | | `samsara/collectors/linux.py:147-155` | `systemctl list-units --all --type=service/timer --no-legend --plain --no-pager`; `list-unit-files ...` | R/U; local systemd IPC, no start/stop/enable or task execution. | | `samsara/collectors/linux_schedules.py:77-95` | `systemctl show` selected properties with validated timer names after `--` | R/U; names limited to 200; no arbitrary shell interpolation. | | `samsara/collectors/linux_schedules.py:46-74` | enumerate `/etc/cron.d`, read regular non-symlink files and `/etc/crontab` | R; reads whole configuration text up to bounded length. Preliminary symlink check can race replacement; not atomic no-follow. | | `samsara/collectors/linux.py:162-176` | `ss -H -n -t -a -p`; `rpm -qa --qf ...` or `dpkg-query -W -f=...` | R/U; package queries, not installation. Numeric ss output avoids explicit name resolution. Native utilities' caches/locking not traced. | | `samsara/collectors/linux.py:177-186` | `/proc/self/mountinfo` read and string decoding | R; code intentionally does not stat/traverse mounted remote filesystems for capacity. Still collects potentially sensitive mount names/paths. | | `samsara/collectors/importer.py:10-22`; `models/inventory.py:10-18`; `analyzers/policy.py:13-25`; `collectors/demo.py:9-13` | JSON/schema/policy/demo file reads | R; arbitrary selected paths may be network-backed. Policy metadata reads are not schema privacy approval. Current schema has no remote `$ref`. | ## Development/test operations (not executed) | File / lines | Side effects if tests are run | | --- | --- | | `tests/test_core.py:37`; `tests/test_import.py:17-20` | TemporaryDirectory creation, synthetic report/JSON writes and automatic deletion. | | `tests/test_linux.py:36-65` | Calls collector with mocked runner, but direct OS/proc/cron reads remain reachable; not a completely synthetic-host test. | | `tests/test_linux.py:78-89` | Temporary reports; launches the real system `sleep` executable to test timeout/cancellation and kills/reaps it. Does not restart assessed services. | | `tests/test_powershell.py:9-16` | Finds a PowerShell executable through PATH and executes the test script; captures stdout/stderr and may print diagnostics on assertion failure. Test-only behavior has different executable resolution from production. | | `tests/powershell/Test-Collectors.ps1:5-20`, `:68-83` | Parses/dot-sources source; mocks provider functions, creates fake registry objects and modifies them with Add-Member. No live registry mutation is requested by these mocks. This does not certify production provider behavior. | | `tests/test_scoring.py:174-214` | Temp report/sidecar/JSON writes, intentional synthetic sidecar overwrite for collision test, cleanup. | | `tests/test_ui.py:2`, `:79-84`, `:138-162` | Sets process offscreen environment, starts Qt, writes synthetic temp exports/policy, cleans up. Native desktop runtime may still initialize libraries. | | `tests/test_windows.py:125-133`, `:179-219` | Temporary export artifacts and fake stdout writes. Process lifecycle mocks mutate fake objects; production helper still creates temp files in these tests. | ## Least-privilege assessment The code **does not require Domain Administrator**, request credentials, call `runas`/ShellExecute elevation, enable token privileges or configure remoting. It reads the existing token and conservatively marks selected non-elevated checks partial (`powershell/Get-ServerInventory.ps1:19-23`; `Inventory.Common.ps1:50-53`). This is an observation flag, not proof of required or sufficient permissions. | Scope | Expected access characteristic; exact production permission **Unverified** | Recommended account approach | | --- | --- | --- | | OS/build/basic domain and adapters | Many local CIM properties commonly readable by standard users; local WMI namespace/host policy may restrict them | Start with standard/delegated read access; verify required property set. | | Services, TCP/process names | Basic enumeration may work without elevation; protected objects can be hidden | Grant only necessary enumeration rights; preserve partial states and avoid broad diagnostic privileges. | | Roles/features | ServerManager availability/servicing policies may require greater local access | Verify separately; make optional rather than silently elevating. | | Scheduled tasks | Visibility/read depends on each task's security descriptor | Delegate read on approved task folders, not task execution/modification. | | Software HKLM | Read access to both views/entries needed; custom ACLs may deny | Read-only registry rights, no installer or write permissions. | | Volumes/shares/open files | Storage and especially SMB open-file enumeration may need elevated/delegated server permissions | Approve privacy scope first; disable open-file query when not permitted. Do not grant blanket admin solely to remove a partial status. | | Public certificate metadata | Store enumeration/public read may be possible; store-specific ACLs vary | Public-store access only; no private-key ACL grants. | A dedicated restricted assessment account can help if its scope, interactive access, output location, logging and lifecycle are approved. Determine delegation in an isolated lab, not by copying broad administrator membership. In-process metadata privacy, external logging and deployment integrity still matter even under least privilege. ## Required future verification Only after CHS authorization: use an isolated, synthetic-data Windows lab, a signed exact release, standard-user and narrowly delegated tokens. Capture registry/service/task/certificate/configuration state before/after, enumerate filesystem/process/network changes and distinguish allowed report/temp locations from forbidden writes. Inspect PowerShell/module-analysis/transcript/EDR behavior and native cache paths. Use deliberately synthetic free-text canaries and do not disable enterprise logging. No such verification was performed in this audit; successful static scans alone cannot close the read-only assurance gap. Ordinary metadata reads may also cause host-managed access-time, antivirus, cache or audit activity. Whether those writes happen, where they are stored and whether they carry collected data depend on the actual filesystem/provider/host policy; no source-only conclusion here certifies their absence. No application or setup command was executed to test those effects.