ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
hook_git_policy_selftest.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# SPDX-License-Identifier: MIT
3# Copyright (c) 2026 Brighton Sikarskie
4"""Hostile HOME Git-policy regressions for the immutable pre-commit owner."""
5
6from __future__ import annotations
7
8import subprocess
9from collections.abc import Callable
10from pathlib import Path
11from typing import Any
12
13from scripts.dev.git_environment import trusted_git_executable
14
15
16class HostileGitPolicyError(RuntimeError):
17 """The hook executed inherited Git policy or lost its refusal path."""
18
19
20def _fail(message: str) -> None:
21 raise HostileGitPolicyError(message)
22
23
24def _write(path: Path, text: str, *, executable: bool = False) -> None:
25 path.parent.mkdir(parents=True, exist_ok=True)
26 path.write_text(text, encoding="utf-8")
27 if executable:
28 path.chmod(0o755)
29
30
31def _hostile_home_policy(
32 base: Path, transport_environment: Callable[[Path, Path], dict[str, str]]
33) -> tuple[dict[str, str], tuple[Path, ...]]:
34 """Create ordinary HOME policy covering filters, templates, and fsmonitor."""
35 home = base / "hostile-home"
36 template = home / "template/hooks"
37 template.mkdir(parents=True)
38 markers = tuple(base / name for name in ("filter.ran", "template.ran", "fsmonitor.ran"))
39 filter_helper = home / "filter.sh"
40 fsmonitor_helper = home / "fsmonitor.sh"
41 _write(filter_helper, f"#!/bin/sh\nprintf x >>{markers[0]}\ncat\n", executable=True)
42 _write(
43 template / "reference-transaction",
44 f"#!/bin/sh\nprintf x >>{markers[1]}\ncat >/dev/null\n",
45 executable=True,
46 )
47 _write(
48 fsmonitor_helper,
49 f"#!/bin/sh\nprintf x >>{markers[2]}\nprintf '\n'\n",
50 executable=True,
51 )
52 attributes = home / "attributes"
53 _write(attributes, "* filter=evil\n")
54 _write(
55 home / ".gitconfig",
56 "[core]\n"
57 f"\tattributesFile = {attributes}\n\tfsmonitor = {fsmonitor_helper}\n"
58 f"[init]\n\ttemplateDir = {template.parent}\n"
59 f'[filter "evil"]\n\tclean = {filter_helper}\n'
60 f"\tsmudge = {filter_helper}\n\trequired = true\n",
61 )
62 environment = transport_environment(base, base)
63 for name in tuple(environment):
64 if name.startswith("GIT_CONFIG_") or name == "GIT_ATTR_NOSYSTEM":
65 environment.pop(name)
66 environment.update(HOME=str(home), XDG_CONFIG_HOME=str(home / "xdg"))
67 return environment, markers
68
69
70def _prove_hostile_home_is_live(
71 base: Path, environment: dict[str, str], markers: tuple[Path, ...]
72) -> None:
73 """Prove every planted ordinary HOME helper executes without the repair."""
74 root = base / "unprotected-home-probe"
75 root.mkdir()
76 _write(root / "probe.txt", "probe\n")
77 commands = (
78 ("init", "--quiet"),
79 ("add", "probe.txt"),
80 ("status", "--porcelain"),
81 (
82 "-c",
83 "user.email=selftest@invalid",
84 "-c",
85 "user.name=selftest",
86 "commit",
87 "--quiet",
88 "-m",
89 "probe",
90 ),
91 )
92 for args in commands:
93 proc = subprocess.run( # noqa: S603 -- fixed Git executable and hostile fixture argv
94 [trusted_git_executable(), "-C", str(root), *args],
95 env=environment,
96 capture_output=True,
97 check=False,
98 )
99 if proc.returncode != 0:
100 _fail(f"hostile HOME probe did not execute {args[-1]}: {proc.stderr!r}")
101 if any(not marker.exists() for marker in markers):
102 _fail("hostile HOME probe did not activate filter, template, and fsmonitor")
103 for marker in markers:
104 marker.unlink()
105
106
107def _install_core_wrappers(directory: Path) -> None:
108 """Install source/PATH core-utility attacks used by the real owner test."""
109 for name in ("cp", "mkdir", "mktemp", "ln", "readlink", "rm"):
110 _write(
111 directory / name,
112 "#!/bin/bash -p\n"
113 'printf "ran\\n" >"${RA8_PATH_MARKER_DIR:?}/${RA8_PATH_MARKER_PREFIX:?}.${0##*/}"\n'
114 "exit 73\n",
115 executable=True,
116 )
117
118
119def _prove_core_wrappers_live(directory: Path, marker_dir: Path, prefix: str) -> None:
120 """Prove the hostile PATH would select every planted wrapper."""
121 expected_return = 73
122 for name in ("cp", "mkdir", "mktemp", "ln", "readlink", "rm"):
123 environment = {
124 "PATH": f"{directory}:/usr/bin:/bin",
125 "RA8_PATH_MARKER_DIR": str(marker_dir),
126 "RA8_PATH_MARKER_PREFIX": prefix,
127 }
128 result = subprocess.run( # noqa: S603 -- must-fire private PATH fixture
129 ["/bin/bash", "-p", "-c", name],
130 env=environment,
131 capture_output=True,
132 check=False,
133 )
134 marker = marker_dir / f"{prefix}.{name}"
135 if result.returncode != expected_return or not marker.is_file():
136 _fail(f"hostile core-utility control did not execute {prefix}/{name}")
137 marker.unlink()
138
139
140def _hostile_owner_path_case(
141 base: Path,
142 callbacks: tuple[Callable[..., Any], ...],
143) -> None:
144 """Prove source-local and arbitrary PATH core utilities cannot become owner tools."""
145 make_fixture, _git, source_state, run_owner, transport_environment = callbacks
146 root, temp_root = base / "hostile-owner-path", base / "hostile-owner-path-tmp"
147 arbitrary = base / "arbitrary-path"
148 marker_dir = base / "path-markers"
149 root.mkdir()
150 temp_root.mkdir()
151 arbitrary.mkdir()
152 marker_dir.mkdir()
153 make_fixture(root, "success", "failure")
154 source_bin = root / ".venv/bin"
155 source_bin.mkdir(parents=True, exist_ok=True)
156 _install_core_wrappers(source_bin)
157 _install_core_wrappers(arbitrary)
158 _prove_core_wrappers_live(source_bin, marker_dir, "source")
159 _prove_core_wrappers_live(arbitrary, marker_dir, "arbitrary")
160 before = source_state(root)
161 environment = transport_environment(base, root)
162 environment.update(
163 PATH=f"{source_bin}:{arbitrary}:{environment.get('PATH', '')}",
164 RA8_PATH_MARKER_DIR=str(marker_dir),
165 RA8_PATH_MARKER_PREFIX="attack",
166 )
167 result = run_owner(root, temp_root, environment)
168 if result.returncode:
169 _fail(f"owner core-utility isolation case failed: {result.stderr}")
170 if tuple(marker_dir.iterdir()):
171 _fail("immutable owner executed a source-local or arbitrary PATH core utility")
172 if source_state(root) != before or tuple(temp_root.iterdir()):
173 _fail("owner core-utility isolation changed source state or left residue")
174
175
176def run_hostile_owner_cases(
177 base: Path,
178 callbacks: tuple[Callable[..., Any], ...],
179) -> None:
180 """Prove the real owner ignores HOME policy and rejects staged drivers."""
181 make_fixture, git, source_state, run_owner, transport_environment = callbacks
182 _hostile_owner_path_case(base, callbacks)
183 environment, markers = _hostile_home_policy(base, transport_environment)
184 _prove_hostile_home_is_live(base, environment, markers)
185 for name, hostile_attributes, expected in (
186 ("hostile-home-success", False, 0),
187 ("hostile-candidate-attribute", True, 1),
188 ):
189 root, temp_root = base / name, base / f"{name}-tmp"
190 root.mkdir()
191 temp_root.mkdir()
192 make_fixture(root, "success", "failure")
193 (root / ".venv/bin").mkdir(parents=True)
194 case_environment = {**environment, "RA8_SELFTEST_VENV_BIN": str(root / ".venv/bin")}
195 if hostile_attributes:
196 _write(root / ".gitattributes", "* filter=evil\n")
197 git(root, "add", ".gitattributes")
198 before = source_state(root)
199 result = run_owner(root, temp_root, case_environment)
200 if result.returncode != expected:
201 detail = result.stderr or result.stdout
202 _fail(f"{name}: expected {expected}, got {result.returncode}: {detail}")
203 executed = tuple(marker.name for marker in markers if marker.exists())
204 if executed:
205 _fail(f"{name}: owner executed ordinary HOME Git policy: {executed}")
206 if source_state(root) != before or tuple(temp_root.iterdir()):
207 _fail(f"{name}: owner changed source state or left residue")