test_footprint_integrity_security.py python
72 lines 3.2 KB
Raw
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 13 hours ago
1 """Security: the self-integrity gate is fail-closed and leaks no content (§KH3.8)."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6
7 from cli.version_lock import ORIGIN_KIT, FootprintEntry, build_version_lock_from_entries
8 from tools.footprint_integrity import check_footprint_integrity
9
10
11 def _lock(entries: list[FootprintEntry]):
12 return build_version_lock_from_entries(
13 kit_version="0.1.0",
14 config_version=1,
15 entries=entries,
16 installed_at="2026-01-01T00:00:00Z",
17 )
18
19
20 def test_corrupt_lock_fails_closed_not_ok(tmp_path: Path) -> None:
21 overseer = tmp_path / ".overseer"
22 overseer.mkdir(parents=True)
23 (overseer / "version.lock").write_text("{{{not yaml", encoding="utf-8")
24 report = check_footprint_integrity(tmp_path)
25 assert not report.ok
26 assert report.state == "unreadable"
27
28
29 def test_remediation_text_is_static_never_shell_invoked(tmp_path: Path) -> None:
30 lock = _lock([FootprintEntry(path="a.mdc", source="s", sha256="0" * 64, origin=ORIGIN_KIT)])
31 report = check_footprint_integrity(tmp_path, lock=lock)
32 assert report.remediation == "ok sync"
33 # A literal string, not an f-string interpolating any path/content — nothing to inject.
34 assert "{" not in report.remediation
35 assert "$" not in report.remediation
36 assert ";" not in report.remediation
37
38
39 def test_missing_paths_reported_never_leak_file_contents(tmp_path: Path) -> None:
40 """The gate only ever stats paths — it must never read or echo file bytes."""
41 secret_path = ".overseer/policy/secret-looking-name.yaml"
42 lock = _lock([FootprintEntry(path=secret_path, source="s", sha256="0" * 64, origin=ORIGIN_KIT)])
43 report = check_footprint_integrity(tmp_path, lock=lock)
44 assert report.missing == (secret_path,)
45 # The path itself is expected (it's a declared destination, not a secret value);
46 # nothing beyond the path string appears anywhere in the report.
47 assert secret_path in report.message
48 for field_value in (report.state, report.remediation):
49 if field_value is not None:
50 assert "\n" not in field_value or field_value == report.message
51
52
53 def test_unusual_lock_entry_paths_never_crash_or_execute(tmp_path: Path) -> None:
54 """An unusual/malformed lock entry path is only ever passed to a filesystem stat — never
55 executed, interpolated into a shell command, or otherwise treated as anything but a plain
56 path string, matching the existing `_compute_footprint_integrity` precedent in status.py."""
57 lock = _lock(
58 [
59 FootprintEntry(path="../outside-canary.txt", source="s", sha256="0" * 64, origin=ORIGIN_KIT),
60 FootprintEntry(path="a; rm -rf /tmp/x", source="s", sha256="0" * 64, origin=ORIGIN_KIT),
61 ]
62 )
63 report = check_footprint_integrity(tmp_path, lock=lock)
64 assert report.state in {"ok", "missing"}
65
66
67 def test_ok_report_never_lists_any_paths(tmp_path: Path) -> None:
68 (tmp_path / "a.mdc").write_text("x", encoding="utf-8")
69 lock = _lock([FootprintEntry(path="a.mdc", source="s", sha256="0" * 64, origin=ORIGIN_KIT)])
70 report = check_footprint_integrity(tmp_path, lock=lock)
71 assert report.state == "ok"
72 assert report.missing == ()
File History 1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1 docs: MuseHub-first before ISR #74 — staging solidify NEXT Human 13 hours ago