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,53 +1,31 @@
|
||||
"""Offline intake shared by Windows and Linux desktops. No code is executed."""
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
from pathlib import Path
|
||||
|
||||
from samsara.models.inventory import validate_inventory, restrict_inventory_fields
|
||||
from samsara.core.privacy import minimize_inventory
|
||||
from samsara.core.storage import require_local_path
|
||||
from samsara.models.inventory import validate_inventory
|
||||
|
||||
MAX_IMPORT_BYTES = 10 * 1024 * 1024
|
||||
|
||||
|
||||
def load_inventory(path):
|
||||
with Path(path).open('rb') as source:
|
||||
local = require_local_path(path)
|
||||
flags=os.O_RDONLY|getattr(os,'O_NOFOLLOW',0)|getattr(os,'O_NONBLOCK',0)|getattr(os,'O_BINARY',0)
|
||||
with os.fdopen(os.open(local,flags),'rb') as source:
|
||||
if not stat.S_ISREG(os.fstat(source.fileno()).st_mode):
|
||||
raise ValueError('Only regular local inventory files may be imported.')
|
||||
raw = source.read(MAX_IMPORT_BYTES + 1)
|
||||
if len(raw) > MAX_IMPORT_BYTES:
|
||||
raise ValueError('Inventory exceeds the 10 MiB import limit.')
|
||||
try:
|
||||
data = json.loads(raw.decode('utf-8-sig'))
|
||||
except (ValueError, UnicodeError):
|
||||
except (ValueError, UnicodeError, RecursionError):
|
||||
raise ValueError('The selected file is not valid UTF-8 inventory JSON.') from None
|
||||
# A report wrapper is accepted, but its precomputed assessment is never trusted.
|
||||
if isinstance(data, dict) and 'inventory_result' in data:
|
||||
data = data['inventory_result']
|
||||
validate_inventory(data)
|
||||
# Keep diagnostic contents out of logs and exported reports. Diagnostics may
|
||||
# contain command lines or credentials from external collection tools.
|
||||
safe_errors = {
|
||||
'access_denied': 'Current account could not read this scope.',
|
||||
'command_unavailable': 'Required command was unavailable.',
|
||||
'timeout': 'Section time limit exceeded.',
|
||||
'overall_timeout': 'Overall collection time limit exceeded.',
|
||||
'output_limit': 'Collection output limit exceeded.',
|
||||
'powershell_failed': 'PowerShell could not execute the collector.',
|
||||
'invalid_output': 'Invalid section output.',
|
||||
'collection_failed': 'A local query failed.'
|
||||
}
|
||||
checks = {}
|
||||
for name, check in data['checks'].items():
|
||||
clean = {'status': check['status'], 'message':
|
||||
'Imported check status. Source assertions are unverified; raw diagnostics excluded.'}
|
||||
for field in ('started_at', 'completed_at'):
|
||||
if field in check:
|
||||
clean[field] = check[field]
|
||||
if 'errors' in check:
|
||||
clean['errors'] = []
|
||||
for error in check['errors']:
|
||||
code = error['code'] if error['code'] in safe_errors else 'collection_failed'
|
||||
clean['errors'].append({'code': code, 'scope': 'Imported check', 'message': safe_errors[code]})
|
||||
if 'permission_limitations' in check:
|
||||
clean['permission_limitations'] = ['Collector reported limited read access; details excluded.'] if check['permission_limitations'] else []
|
||||
if 'limitations' in check:
|
||||
clean['limitations'] = ['Collector reported scope limitations; consult the inventory owner.'] if check['limitations'] else []
|
||||
checks[name] = clean
|
||||
data['checks'] = checks
|
||||
return restrict_inventory_fields(data)
|
||||
return validate_inventory(minimize_inventory(data))
|
||||
|
||||
Reference in New Issue
Block a user