3"""Adversarial runtime cases for the privileged raw-digest file reader."""
5from __future__
import annotations
13from collections.abc
import Callable, Mapping
14from pathlib
import Path, PurePosixPath
16import hil_convergence_safety_image_lock_digest
as digest
17import hil_convergence_safety_raw_digest_fixtures
as raw_digest_fixtures
19Case = tuple[str, bool]
21_LABEL_BY_PATH = {path: label
for path, _pin, label, _mode
in digest.target_specs()}
22_MAIN_LABEL = _LABEL_BY_PATH[digest.DEVCONTAINER_IMAGE_PATH]
23_RAW_FILE_LABEL = f
"raw digest authority file: {digest.DEVCONTAINER_IMAGE_PATH}"
27def _path_name(pin_name: str) -> str:
28 """Return the direct path authority corresponding to one digest pin."""
29 return pin_name.removesuffix(
"_RAW_SHA256") +
"_PATH"
32def _payloads(inputs: Mapping[str, str]) -> dict[str, bytes]:
33 """Return exact fixture bytes for every bound surface."""
35 path: inputs[key].encode(
"utf-8")
for path, key
in raw_digest_fixtures.INPUT_BY_PATH.items()
40 payloads: Mapping[str, bytes], path_overrides: Mapping[str, str] |
None =
None
41) -> dict[str, object]:
42 """Build exact test authorities without executing candidate source."""
43 values = digest.authority_values()
44 for path, pin_name, _label, _mode
in digest.target_specs():
45 effective = path
if path_overrides
is None else path_overrides.get(path, path)
46 values[_path_name(pin_name)] = effective
47 values[pin_name] = hashlib.sha256(payloads[path]).hexdigest()
51def _write_fixture(root: Path, payloads: Mapping[str, bytes], values: Mapping[str, object]) ->
None:
52 """Write a root-owned-by-caller fixture with exact portable modes."""
53 root.mkdir(mode=0o755)
55 by_pin = {pin: original
for original, pin, _label, _mode
in digest.target_specs()}
56 for effective, pin_name, _label, mode
in digest.target_specs(values):
57 original = by_pin[pin_name]
58 pure = PurePosixPath(effective)
59 if pure.is_absolute()
or ".." in pure.parts:
61 target = root / effective
62 target.parent.mkdir(mode=0o755, parents=
True, exist_ok=
True)
63 ancestor = target.parent
64 while ancestor != root:
66 ancestor = ancestor.parent
67 target.write_bytes(payloads[original])
72 inputs: Mapping[str, str],
73 operation: Callable[[Path, dict[str, bytes], dict[str, object]], bool],
75 path_overrides: Mapping[str, str] |
None =
None,
77 """Run one isolated case and recover renamed roots before cleanup."""
78 container = Path(tempfile.mkdtemp(prefix=
"ra8-raw-digest-"))
79 root = container /
"repo"
80 payloads = _payloads(inputs)
81 values = _values(payloads, path_overrides)
83 _write_fixture(root, payloads, values)
84 return operation(root, payloads, values)
86 saved = container /
"repo.saved"
88 if root.exists()
or root.is_symlink():
89 if root.is_dir()
and not root.is_symlink():
94 shutil.rmtree(container)
97def _exact_error(errors: list[str], text: str) -> bool:
98 """Require one byte-exact stable diagnostic."""
99 return errors == [text]
102def _source_tuple(inputs: Mapping[str, str]) -> tuple[str, ...]:
103 """Return all bound sources in production target order."""
105 inputs[raw_digest_fixtures.INPUT_BY_PATH[path]]
106 for path, _pin, _label, _mode
in digest.target_specs()
108 return tuple(ordered)
111def _baseline_case(inputs: Mapping[str, str]) -> bool:
112 """Require the exact complete fixture to pass without diagnostics."""
113 return _with_fixture(
115 lambda root, _payloads_arg, values:
not digest.audit_live_errors(root, values),
119def _surface_digest_case(inputs: Mapping[str, str], target_path: str) -> bool:
120 """Require a byte change on each bound surface to fire once."""
122 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
123 target = root / target_path
124 target.write_bytes(target.read_bytes() + b
"\n")
125 errors = digest.audit_live_errors(root, values)
128 f
"{_LABEL_BY_PATH[target_path]}: raw bytes differ from exact audited digest",
131 return _with_fixture(inputs, operation)
134def _unsafe_relative_case(inputs: Mapping[str, str], unsafe: str) -> bool:
135 """Require absolute and parent-traversing target authorities to fail."""
136 original = digest.DEVCONTAINER_IMAGE_PATH
138 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
139 errors = digest.audit_live_errors(root, values)
141 f
"{_MAIN_LABEL}: bound path must be a fixed normalized relative path"
142 if unsafe.startswith(
"/")
or ".." in PurePosixPath(unsafe).parts
143 else f
"{_MAIN_LABEL}: bound path differs from fixed repository authority"
145 return _exact_error(errors, diagnostic)
147 return _with_fixture(inputs, operation, path_overrides={original: unsafe})
150def _final_path_case(inputs: Mapping[str, str], kind: str) -> bool:
151 """Require final symlink, hardlink, directory, FIFO, and missing refusal."""
152 target_path = digest.DEVCONTAINER_IMAGE_PATH
154 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
155 target = root / target_path
156 saved = target.with_name(
"saved-authority")
158 if kind ==
"symlink":
159 target.symlink_to(saved.name)
160 elif kind ==
"hardlink":
161 target.hardlink_to(saved)
162 elif kind ==
"directory":
165 os.mkfifo(target, 0o755)
166 elif kind !=
"missing":
167 raise ValueError(kind)
168 started = time.monotonic()
169 errors = digest.audit_live_errors(root, values)
170 elapsed = time.monotonic() - started
172 f
"{_MAIN_LABEL}: cannot inspect or open bound bytes safely: {errno.ENOENT}"
174 else f
"{_MAIN_LABEL}: bound path is absent, linked, or non-regular"
176 return elapsed < 1.0
and _exact_error(errors, diagnostic)
178 return _with_fixture(inputs, operation)
181def _parent_symlink_case(inputs: Mapping[str, str]) -> bool:
182 """Require a no-follow refusal when an intermediate directory is linked."""
183 original = digest.DEVCONTAINER_IMAGE_PATH
184 attacked =
"scripts/raw-audit/ci/devcontainer_image.sh"
186 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
187 parent = (root / attacked).parent
188 saved = parent.with_name(
"ci.saved")
190 parent.symlink_to(saved.name)
191 hooks = digest.RawReadTestHooks(allow_alternate_fixed_paths=
True)
192 errors = digest.audit_live_errors(root, values, hooks=hooks)
195 "raw digest authority directory: "
196 f
"{attacked}: bound path is absent, linked, or non-regular",
199 return _with_fixture(inputs, operation, path_overrides={original: attacked})
202def _root_symlink_case(inputs: Mapping[str, str]) -> bool:
203 """Require the repository root itself to be an unlinked directory."""
205 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
206 link = root.with_name(
"repo-link")
207 link.symlink_to(root.name)
208 errors = digest.audit_live_errors(link, values)
209 return _exact_error(errors,
"raw digest authority root: repository root is not a directory")
211 return _with_fixture(inputs, operation)
214def _root_replacement_case(inputs: Mapping[str, str]) -> bool:
215 """Require a post-open root replacement to fail without reading it."""
217 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
218 saved = root.with_name(
"repo.saved")
220 def replace(opened_root: Path, _fd: int) ->
None:
221 opened_root.rename(saved)
222 opened_root.mkdir(mode=0o755)
224 hooks = digest.RawReadTestHooks(after_root_open=replace)
225 errors = digest.audit_live_errors(root, values, hooks=hooks)
228 "raw digest authority root: path changed during retained-root audit",
231 return _with_fixture(inputs, operation)
234def _parent_replacement_case(inputs: Mapping[str, str]) -> bool:
235 """Require a post-open parent replacement to fail the identity rewalk."""
236 original = digest.DEVCONTAINER_IMAGE_PATH
237 attacked =
"scripts/raw-audit/ci/devcontainer_image.sh"
239 def operation(root: Path, payloads: dict[str, bytes], values: dict[str, object]) -> bool:
242 def replace(relative: str, _fd: int) ->
None:
244 if relative != attacked
or changed:
247 parent = (root / attacked).parent
248 saved = parent.with_name(
"ci.saved")
250 parent.mkdir(mode=0o755)
251 replacement = parent / Path(attacked).name
252 replacement.write_bytes(payloads[original])
253 replacement.chmod(0o755)
255 hooks = digest.RawReadTestHooks(
256 allow_alternate_fixed_paths=
True,
257 after_file_open=replace,
259 errors = digest.audit_live_errors(root, values, hooks=hooks)
260 return changed
and _exact_error(
262 f
"raw digest authority file: {attacked}: parent changed during raw-byte read",
265 return _with_fixture(inputs, operation, path_overrides={original: attacked})
268def _capability_case(inputs: Mapping[str, str], name: str) -> bool:
269 """Require each unavailable platform primitive to fail before opening."""
271 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
272 hooks = digest.RawReadTestHooks(missing_capability=name)
273 errors = digest.audit_live_errors(root, values, hooks=hooks)
276 f
"raw digest authority: required platform capability is unavailable: {name}",
279 return _with_fixture(inputs, operation)
282def _authority_case(inputs: Mapping[str, str], kind: str) -> bool:
283 """Require owner, group, and exact-mode mismatches to fail closed."""
285 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
286 root_stat = root.stat()
287 authority = digest.RawReadAuthority(
288 root_uid=root_stat.st_uid,
289 root_gid=root_stat.st_gid,
290 file_uid=root_stat.st_uid + (1
if kind ==
"owner" else 0),
291 file_gid=root_stat.st_gid + (1
if kind ==
"group" else 0),
294 (root / digest.DEVCONTAINER_IMAGE_PATH).chmod(0o775)
295 errors = digest.audit_live_errors(root, values, authority=authority)
297 "owner":
"bound path owner differs from repository authority",
298 "group":
"bound path group differs from repository authority",
299 "mode":
"bound path mode differs from exact audited mode",
301 if kind
in {
"owner",
"group"}:
303 f
"{label}: {diagnostic}" for _path, _pin, label, _mode
in digest.target_specs()
305 return errors == expected
306 return _exact_error(errors, f
"{_MAIN_LABEL}: {diagnostic}")
308 return _with_fixture(inputs, operation)
311def _oversize_case(inputs: Mapping[str, str]) -> bool:
312 """Require the fixed maximum to stop an oversized regular file."""
313 target_path = digest.DEVCONTAINER_IMAGE_PATH
315 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
316 oversized = b
"x" * (digest.maximum_authority_bytes() + 1)
317 (root / target_path).write_bytes(oversized)
318 values[
"DEVCONTAINER_IMAGE_RAW_SHA256"] = hashlib.sha256(oversized).hexdigest()
319 errors = digest.audit_live_errors(root, values)
320 return _exact_error(errors, f
"{_RAW_FILE_LABEL}: bound file exceeds maximum audited size")
322 return _with_fixture(inputs, operation)
325def _race_diagnostic_matches(kind: str, errors: list[str]) -> bool:
326 """Require one exact legitimate diagnostic for a file-race attack."""
328 "shrink": f
"{_RAW_FILE_LABEL}: bound file shrank during bounded raw-byte read",
329 "extra": f
"{_RAW_FILE_LABEL}: bound file has bytes beyond its audited pre-read size",
330 "growth": f
"{_MAIN_LABEL}: bound file metadata changed during bounded raw-byte read",
331 "timestamp": f
"{_MAIN_LABEL}: bound file metadata changed during bounded raw-byte read",
333 if kind !=
"rebound":
334 return _exact_error(errors, expected[kind])
336 (f
"{_RAW_FILE_LABEL}: path changed during raw-byte read",),
337 (f
"{_RAW_FILE_LABEL}: parent changed during raw-byte read",),
339 return tuple(errors)
in legitimate
342def _file_race_case(inputs: Mapping[str, str], kind: str) -> bool:
343 """Require shrink, extra growth, timestamp, and path-rebound detection."""
344 target_path = digest.DEVCONTAINER_IMAGE_PATH
346 def operation(root: Path, payloads: dict[str, bytes], values: dict[str, object]) -> bool:
348 target = root / target_path
350 def after_open(relative: str, _fd: int) ->
None:
352 if relative != target_path
or changed
or kind
not in {
"shrink",
"extra"}:
356 target.write_bytes(payloads[target_path][:1])
358 with target.open(
"ab")
as stream:
361 def after_read(relative: str, _fd: int) ->
None:
363 if relative != target_path
or changed
or kind
not in {
"growth",
"timestamp"}:
367 with target.open(
"ab")
as stream:
370 current = target.stat()
371 os.utime(target, ns=(current.st_atime_ns, current.st_mtime_ns + 1_000_000))
373 def rebound(relative: str) ->
None:
375 if relative != target_path
or changed
or kind !=
"rebound":
378 saved = target.with_name(
"original-authority")
380 target.write_bytes(payloads[target_path])
383 hooks = digest.RawReadTestHooks(
384 after_file_open=after_open,
385 after_read=after_read,
386 before_post_rewalk=rebound,
388 errors = digest.audit_live_errors(root, values, hooks=hooks)
389 return changed
and _race_diagnostic_matches(kind, errors)
391 return _with_fixture(inputs, operation)
394def _fd_set() -> set[int] | None:
395 """Return the Linux descriptor set when procfs is available."""
396 proc = Path(
"/proc/self/fd")
397 if not proc.is_dir():
399 return {int(entry.name)
for entry
in proc.iterdir()
if entry.name.isdigit()}
402def _descriptor_case(inputs: Mapping[str, str], mode: str) -> bool:
403 """Require exhaustive normal closes and a fail-closed close diagnostic."""
405 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
407 close_failure = mode ==
"close-failure"
408 errors: list[str] = []
410 for _attempt
in range(_FAILURE_ATTEMPTS):
411 raised_this_audit =
False
413 def fail_after_close(_fd: int) ->
None:
414 nonlocal raised_count, raised_this_audit
415 if not raised_this_audit:
416 raised_this_audit =
True
418 raise RuntimeError(raw_digest_fixtures.PRE_CLOSE_FAILURE)
421 digest.RawReadTestHooks(after_close_fd=fail_after_close)
if close_failure
else None
423 errors = digest.audit_live_errors(root, values, hooks=hooks)
425 residue_free = before
is None or before == after
428 raised_count == _FAILURE_ATTEMPTS
432 f
"{_RAW_FILE_LABEL}: descriptor-close hook failed",
435 return residue_free
and not errors
437 return _with_fixture(inputs, operation)
440def _ambiguous_close_attempt(
442 values: dict[str, object],
444 """Prove a post-close FD reuse is never closed by stale ledger authority."""
449 def reuse_then_fail(released: int) ->
None:
450 nonlocal replacement, reused
453 replacement = os.open(os.devnull, os.O_RDONLY | os.O_CLOEXEC)
454 if replacement != released:
455 message =
"released descriptor number was not reused"
456 raise RuntimeError(message)
458 message =
"injected post-close failure"
459 raise OSError(errno.EIO, message)
461 hooks = digest.RawReadTestHooks(after_close_fd=reuse_then_fail)
463 errors = digest.audit_live_errors(root, values, hooks=hooks)
464 replacement_live = replacement >= 0
and os.fstat(replacement)
is not None
465 expected = f
"{_RAW_FILE_LABEL}: descriptor-close hook failed"
466 return reused
and replacement_live
and _exact_error(errors, expected)
469 os.close(replacement)
471 if before
is not None and after != before:
472 message =
"ambiguous close fixture leaked a descriptor"
473 raise RuntimeError(message)
476def _ambiguous_close_case(inputs: Mapping[str, str]) -> bool:
477 """Repeat the reused-FD proof across independent fixture roots."""
481 lambda root, _payloads_arg, values: _ambiguous_close_attempt(root, values),
483 for _attempt
in range(_FAILURE_ATTEMPTS)
487def _root_hook_failure_case(inputs: Mapping[str, str]) -> bool:
488 """Require root-open hook exceptions to close the retained descriptor."""
490 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
493 def fail_after_root_open(_root: Path, _fd: int) ->
None:
494 raise RuntimeError(raw_digest_fixtures.ROOT_OPEN_FAILURE)
496 hooks = digest.RawReadTestHooks(after_root_open=fail_after_root_open)
497 errors: list[str] = []
498 for _attempt
in range(_FAILURE_ATTEMPTS):
499 errors = digest.audit_live_errors(root, values, hooks=hooks)
501 return (before
is None or before == after)
and _exact_error(
503 "raw digest authority root: cannot inspect or open safely: hook",
506 return _with_fixture(inputs, operation)
509def _directory_authority_case(inputs: Mapping[str, str], kind: str) -> bool:
510 """Require safe root and exact intermediate-directory metadata."""
512 def operation(root: Path, _payloads_arg: dict[str, bytes], values: dict[str, object]) -> bool:
515 "root-owner-permission": 0o400,
516 "root-private-mode": 0o700,
517 "root-group-private-mode": 0o750,
518 "root-readonly-mode": 0o555,
520 if kind
in root_modes:
521 root.chmod(root_modes[kind])
523 errors = digest.audit_live_errors(root, values)
526 if kind
in {
"root-mode",
"root-owner-permission"}:
529 "raw digest authority root: "
530 "repository root mode is not safe for the audited authority",
533 (root /
"scripts").chmod(0o750)
535 f
"raw digest authority directory: {path}: "
536 "bound path mode differs from exact audited mode"
537 for path, _pin, _label, _mode
in digest.target_specs()
539 return digest.audit_live_errors(root, values) == expected
541 return _with_fixture(inputs, operation)
544def _implementation_cases(inputs: Mapping[str, str]) -> list[Case]:
545 """Prove each live reader control is load-bearing without pin changes."""
546 authority_source = inputs[
"image_lock_digest"]
547 controls = digest.implementation_controls()
548 mutations = digest.implementation_mutations(authority_source)
551 "raw digest implementation controls are uniquely present",
552 not digest.implementation_errors(authority_source)
553 and len(mutations) == len(controls)
554 and len({control.label
for control
in controls}) == len(controls),
557 sources = _source_tuple(inputs)
560 f
"raw digest control mutation fires: {label}",
561 digest.source_errors(sources, mutant) == [expected],
563 for label, mutant, expected
in mutations
568def _path_cases(inputs: Mapping[str, str]) -> list[Case]:
569 """Return fixed-path, type, parent, and root attack cases."""
572 f
"raw digest unsafe relative target refused: {unsafe}",
573 _unsafe_relative_case(inputs, unsafe),
576 "/outside/devcontainer_image.sh",
577 "scripts/../devcontainer_image.sh",
582 "raw digest normalized but noncanonical target refused",
583 _unsafe_relative_case(
585 "scripts/ci/other_authority.sh",
590 (f
"raw digest final {kind} refused without blocking", _final_path_case(inputs, kind))
591 for kind
in (
"symlink",
"hardlink",
"directory",
"fifo",
"missing")
595 (
"raw digest linked parent refused", _parent_symlink_case(inputs)),
596 (
"raw digest linked root refused", _root_symlink_case(inputs)),
597 (
"raw digest replaced parent detected", _parent_replacement_case(inputs)),
598 (
"raw digest replaced root detected", _root_replacement_case(inputs)),
604def _capability_cases(inputs: Mapping[str, str]) -> list[Case]:
605 """Return platform-capability and metadata-authority cases."""
613 "stat_follow_symlinks",
617 (f
"raw digest missing capability refused: {name}", _capability_case(inputs, name))
618 for name
in capabilities
621 (f
"raw digest {kind} authority mismatch refused", _authority_case(inputs, kind))
622 for kind
in (
"owner",
"group",
"mode")
629 f
"raw digest {kind} authority policy holds",
630 _directory_authority_case(inputs, kind),
634 "root-owner-permission",
636 "root-group-private-mode",
637 "root-readonly-mode",
641 results.append((
"raw digest oversize authority refused", _oversize_case(inputs)))
645def _race_and_close_cases(inputs: Mapping[str, str]) -> list[Case]:
646 """Return bounded-read race and exhaustive-close cases."""
648 (f
"raw digest {kind} race detected", _file_race_case(inputs, kind))
649 for kind
in (
"shrink",
"extra",
"growth",
"timestamp")
654 "raw digest rebound race repeatedly detects one exact identity change",
655 all(_file_race_case(inputs,
"rebound")
for _attempt
in range(_FAILURE_ATTEMPTS)),
658 "raw digest descriptor audit leaves no residue",
659 _descriptor_case(inputs,
"normal"),
662 "raw digest close failure is diagnosed without residue",
663 _descriptor_case(inputs,
"close-failure"),
666 "raw digest root hook failure is diagnosed without residue",
667 _root_hook_failure_case(inputs),
670 "raw digest ambiguous close cannot consume reused descriptor",
671 _ambiguous_close_case(inputs),
678def cases(inputs: Mapping[str, str]) -> list[Case]:
679 """Return complete two-sided cases for the live raw-digest reader."""
680 results: list[Case] = [
681 (
"raw digest exact complete-surface baseline passes", _baseline_case(inputs))
685 f
"raw digest byte mutation fires: {path}",
686 _surface_digest_case(inputs, path),
688 for path
in raw_digest_fixtures.INPUT_BY_PATH
692 + _path_cases(inputs)
693 + _capability_cases(inputs)
694 + _race_and_close_cases(inputs)
695 + _implementation_cases(inputs)