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:
TheMajesticMagician
2026-10-25 16:21:14 -06:00
co-authored by Claude Code
commit addd00364d
76 changed files with 12503 additions and 0 deletions
+157
View File
@@ -0,0 +1,157 @@
from __future__ import annotations
import os
import stat
import time
from pathlib import Path
import pytest
from boltclam.clamav import (
ClamAVService,
build_freshclam_args,
build_scan_args,
database_age,
database_files,
find_clamscan,
parse_clamscan_line,
parse_extra_options,
parse_version_output,
scan_targets,
)
def _script(path: Path, body: str = "") -> Path:
path.write_text("#!/bin/sh\n" + body, encoding="utf-8")
path.chmod(path.stat().st_mode | stat.S_IXUSR)
return path
def test_parse_version_output():
assert parse_version_output("ClamAV 1.4.3/27452/Wed Oct 22 07:17:23 2026") == (
"1.4.3", "27452", "Wed Oct 22 07:17:23 2026")
assert parse_version_output("ClamAV 1.4.0") == ("1.4.0", "", "")
assert parse_version_output("nonsense") == ("", "", "")
def test_parse_extra_options_handles_windows_quotes():
options = parse_extra_options(
'--max-filesize=200M --exclude-dir="C:\\Program Files\\Skip" '
'--database="C:\\My DB"')
assert options == [
"--max-filesize=200M",
"--exclude-dir=C:\\Program Files\\Skip",
"--database=C:\\My DB",
]
def test_parse_extra_options_refuses_destructive_flags():
for text in ("--remove=yes", "--move=C:\\Quarantine", "--copy=/tmp"):
with pytest.raises(ValueError):
parse_extra_options(text)
def test_parse_extra_options_rejects_malformed_quoting():
with pytest.raises(ValueError):
parse_extra_options('--exclude-dir="unterminated')
def test_build_scan_args_uses_managed_database_and_excludes(tmp_path):
db = tmp_path / "db"
db.mkdir()
(db / "main.cvd").write_bytes(b"x")
quarantine = tmp_path / "quarantine"
temp = tmp_path / "temp"
args = build_scan_args(
Path("/usr/bin/clamscan"), [tmp_path / "target"],
database_dir=db, quarantine_dir=quarantine, temp_dir=temp,
extra_options=["--max-filesize=200M"])
assert args[0].endswith("clamscan")
assert "--recursive=yes" in args
assert "--infected" in args
assert f"--database={db}" in args
assert any(arg.startswith("--exclude-dir=") for arg in args)
assert "--max-filesize=200M" in args
assert args[-1] == str(tmp_path / "target")
def test_build_scan_args_omits_database_when_no_signatures(tmp_path):
args = build_scan_args(Path("/usr/bin/clamscan"), [tmp_path])
assert not any(arg.startswith("--database=") for arg in args)
def test_parse_clamscan_line_detection_windows_path():
event = parse_clamscan_line(
r"C:\Users\aaron\Downloads\invoice.pdf.exe: Win.Trojan.Agent-123 FOUND")
assert event == {
"kind": "detection",
"path": r"C:\Users\aaron\Downloads\invoice.pdf.exe",
"signature": "Win.Trojan.Agent-123",
}
def test_parse_clamscan_line_summary_progress_and_errors():
assert parse_clamscan_line("Scanned files: 18234")["key"] == "scanned_files"
assert parse_clamscan_line("Scanned files: 18234")["value"] == "18234"
assert parse_clamscan_line("Engine version: 1.4.3")["value"] == "1.4.3"
assert parse_clamscan_line("Scanning /home/a/file")["kind"] == "progress"
assert parse_clamscan_line("/home/a/file: Access denied")["kind"] == "error"
assert parse_clamscan_line("/home/a/file: Size limit exceeded")["kind"] == "skipped"
assert parse_clamscan_line("") is None
def test_scan_targets_deduplicates_injected_profiles(tmp_path):
one = tmp_path / "one"
two = tmp_path / "two"
one.mkdir()
two.mkdir()
targets = scan_targets("homes", profiles=[one, two, one, Path("/does/not/exist")])
assert targets == [one.resolve(), two.resolve()]
def test_scan_targets_full_uses_injected_drives(tmp_path):
drive = tmp_path / "drive"
drive.mkdir()
assert scan_targets("full", drives=[drive]) == [drive.resolve()]
def test_database_detection_and_age(tmp_path):
db = tmp_path / "db"
db.mkdir()
assert database_files(db) == []
main = db / "main.cvd"
main.write_bytes(b"signatures")
old = time.time() - 3 * 86400
os.utime(main, (old, old))
assert database_files(db) == [main]
date, age = database_age(db)
assert date
assert 2.8 < age < 3.2
def test_clamav_service_reads_a_fake_engine(tmp_path):
fake = _script(tmp_path / "clamscan", 'echo "ClamAV 1.4.3/27452/Wed Oct 22 07:17:23 2026"\n')
service = ClamAVService(str(fake))
info = service.info(force=True)
assert info.available is True
assert info.engine_version == "1.4.3"
assert info.db_version == "27452"
assert info.path == fake
assert service.info(force=True).summary.startswith("1.4.3")
def test_find_clamscan_accepts_a_file_or_directory(tmp_path):
fake = _script(tmp_path / "clamscan")
found, error = find_clamscan(str(fake))
assert found == fake and error == ""
found, error = find_clamscan(str(tmp_path))
assert found == fake and error == ""
missing, error = find_clamscan(str(tmp_path / "missing"))
assert missing is None and "does not exist" in error
def test_freshclam_arguments_target_managed_database(tmp_path):
args = build_freshclam_args(Path("/usr/bin/freshclam"), tmp_path / "db")
assert "--foreground" in args
assert "--stdout" in args
assert f"--datadir={tmp_path / 'db'}" in args