Files
TheMajesticMagicianandClaude Code addd00364d 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>
2026-10-25 16:21:14 -06:00

80 lines
3.4 KiB
Python

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"