BoltClam 1.0.0: ClamAV desktop protection with Bolt sign-in
Adds the PyQt6 Windows client (Homepage, Scan & results, About & updates, Settings), ClamAV scanning and quarantine, browser-download watch with an exclusive scan gate, Bolt loopback/PKCE sign-in with DPAPI key storage, Gitea release feed with checksum verification, opt-in diagnostics, and Windows/portable build tooling. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
from boltclam import paths
|
||||
from boltclam.config import SettingsStore
|
||||
from boltclam.logging_setup import redact
|
||||
from boltclam.logs import build_bundle, redact_paths, sanitize_text, upload_bundle
|
||||
from boltclam.models import ClamAVInfo, Detection
|
||||
from boltclam.storage import Storage
|
||||
from boltclam.system_info import collect
|
||||
|
||||
|
||||
def test_redaction_covers_tokens_and_emails():
|
||||
text = "key=bolt_live_abcdef password=hunter2 user aaron@example.com"
|
||||
redacted = sanitize_text(text)
|
||||
assert "bolt_live_abcdef" not in redacted
|
||||
assert "hunter2" not in redacted
|
||||
assert "aaron@example.com" not in redacted
|
||||
assert "[email]" in redacted or "[redacted]" in redacted
|
||||
|
||||
|
||||
def test_path_redaction_uses_userprofile(isolated_env):
|
||||
sample = str(Path.home() / "Downloads" / "bad.exe")
|
||||
assert "%USERPROFILE%" in redact_paths(sample)
|
||||
assert "Downloads" in redact_paths(sample)
|
||||
|
||||
|
||||
def test_bundle_contains_redacted_logs_and_scan_summary(isolated_env):
|
||||
settings = SettingsStore().load()
|
||||
storage = Storage()
|
||||
scan_id = storage.create_scan("homes", [str(Path.home() / "Downloads")])
|
||||
detection = Detection(path=str(Path.home() / "Downloads" / "bad.exe"),
|
||||
signature="Win.Test", size=10)
|
||||
detection.id = storage.add_detection(scan_id, detection)
|
||||
storage.finish_scan(scan_id, status="completed", scanned_files=10,
|
||||
infected_files=1, errors=0, duration_seconds=2, cancelled=False)
|
||||
paths.logs_dir().mkdir(parents=True, exist_ok=True)
|
||||
(paths.logs_dir() / "boltclam.log").write_text(
|
||||
f"token=bolt_live_supersecret user aaron@example.com path={Path.home()}/x\n",
|
||||
encoding="utf-8")
|
||||
info = ClamAVInfo(available=True, path=Path("/fake/clamscan"),
|
||||
engine_version="1.4.3", db_version="27452",
|
||||
db_path=Path("/fake/db"), db_date="2026-10-22",
|
||||
db_age_days=1.0)
|
||||
snapshot = collect(settings, info, storage, realtime_running=False, force=True)
|
||||
bundle = build_bundle(settings, info, system_snapshot=snapshot,
|
||||
account={"user": {"email": "aaron@example.com"}},
|
||||
realtime_roots=[str(Path.home() / "Downloads")])
|
||||
assert bundle.is_file()
|
||||
with zipfile.ZipFile(bundle) as archive:
|
||||
names = set(archive.namelist())
|
||||
assert {"manifest.json", "boltclam-logs.txt", "system-summary.json",
|
||||
"README.txt"} <= names
|
||||
logs = archive.read("boltclam-logs.txt").decode()
|
||||
assert "bolt_live_supersecret" not in logs
|
||||
assert "aaron@example.com" not in logs
|
||||
assert "%USERPROFILE%" in logs
|
||||
manifest = json.loads(archive.read("manifest.json"))
|
||||
assert manifest["app"] == "BoltClam"
|
||||
assert manifest["account"]["email"] == "aaron@example.com"
|
||||
summary = json.loads(archive.read("system-summary.json"))
|
||||
assert summary["stats"]["latest_scan"]["id"] == scan_id
|
||||
|
||||
|
||||
class FakeApi:
|
||||
def upload_diagnostics(self, path, metadata=None):
|
||||
return {"id": "42/test.zip", "bytes": Path(path).stat().st_size}
|
||||
|
||||
|
||||
def test_upload_bundle_returns_server_id(isolated_env):
|
||||
settings = SettingsStore().load()
|
||||
storage = Storage()
|
||||
info = ClamAVInfo(available=False, error="not installed")
|
||||
bundle = build_bundle(settings, info)
|
||||
result = upload_bundle(FakeApi(), bundle, settings)
|
||||
assert result["id"] == "42/test.zip"
|
||||
Reference in New Issue
Block a user