More TOCTOU, update to tests for jinjaturtle
Some checks failed
CI / test (push) Successful in 48s
CI / test (almalinux, docker.io/library/almalinux:9, python3.11) (push) Failing after 2m32s
CI / test (debian, docker.io/library/debian:13, python3) (push) Failing after 3m0s
Lint / test (push) Successful in 44s

This commit is contained in:
Miguel Jacq 2026-06-29 14:30:07 +10:00
parent 56ae883948
commit 3c1e08bdde
Signed by: mig5
GPG key ID: 03906B4110AAD3B8
9 changed files with 116 additions and 17 deletions

View file

@ -4,7 +4,7 @@ import hashlib
import os
from pathlib import Path
from enroll.fsutil import file_md5, stat_triplet
from enroll.fsutil import file_md5, stat_dir_triplet, stat_triplet
def test_file_md5_matches_hashlib(tmp_path: Path):
@ -74,3 +74,46 @@ def test_open_no_follow_path_refuses_symlinked_leaf(tmp_path: Path):
raise AssertionError("expected OSError for symlinked leaf")
except OSError as e:
assert e.errno == errno.ELOOP
def test_stat_dir_triplet_reports_directory_mode_without_following(tmp_path: Path):
d = tmp_path / "dir"
d.mkdir()
os.chmod(d, 0o750)
owner, group, mode = stat_dir_triplet(str(d))
assert mode == "0750"
assert owner
assert group
def test_stat_dir_triplet_refuses_symlinked_parent(tmp_path: Path):
import errno
real = tmp_path / "real"
real.mkdir()
child = real / "child"
child.mkdir()
link = tmp_path / "link"
link.symlink_to(real, target_is_directory=True)
try:
stat_dir_triplet(str(link / "child"))
raise AssertionError("expected OSError for symlinked parent")
except OSError as e:
assert e.errno == errno.ELOOP
def test_stat_dir_triplet_refuses_final_symlink(tmp_path: Path):
import errno
real = tmp_path / "real"
real.mkdir()
link = tmp_path / "link"
link.symlink_to(real, target_is_directory=True)
try:
stat_dir_triplet(str(link))
raise AssertionError("expected OSError for symlinked leaf")
except OSError as e:
assert e.errno == errno.ELOOP

View file

@ -256,6 +256,7 @@ def test_harvest_dedup_manual_packages_and_builds_etc_custom(
return ("root", "root", "0644")
monkeypatch.setattr(harvest, "stat_triplet", fake_stat_triplet)
monkeypatch.setattr(harvest, "stat_dir_triplet", fake_stat_triplet)
monkeypatch.setattr(capture, "stat_triplet", fake_stat_triplet)
# Avoid needing source files on disk by implementing our own bundle copier
@ -400,6 +401,7 @@ def test_shared_cron_snippet_prefers_matching_role_over_lexicographic(
monkeypatch.setattr(harvest, "get_backend", lambda info=None: backend)
monkeypatch.setattr(harvest, "stat_triplet", lambda p: ("root", "root", "0644"))
monkeypatch.setattr(harvest, "stat_dir_triplet", lambda p: ("root", "root", "0755"))
monkeypatch.setattr(capture, "stat_triplet", lambda p: ("root", "root", "0644"))
monkeypatch.setattr(harvest, "collect_non_system_users", lambda: [])

View file

@ -285,7 +285,7 @@ def test_extra_paths_collector_records_dirs_files_notes_and_excludes(
)
return True
monkeypatch.setattr(paths.h, "stat_triplet", fake_stat_triplet)
monkeypatch.setattr(paths.h, "stat_dir_triplet", fake_stat_triplet)
monkeypatch.setattr(paths, "capture_file", lambda *a, **kw: fake_capture_file(**kw))
ctx = _context(
@ -321,7 +321,7 @@ def test_extra_paths_collector_skips_already_captured_files(monkeypatch, tmp_pat
file_path.write_text("ok", encoding="utf-8")
calls: list[str] = []
monkeypatch.setattr(paths.h, "stat_triplet", lambda p: ("root", "root", "0755"))
monkeypatch.setattr(paths.h, "stat_dir_triplet", lambda p: ("root", "root", "0755"))
monkeypatch.setattr(
paths, "capture_file", lambda *a, **kw: calls.append(kw["abs_path"]) or True
)

View file

@ -39,8 +39,12 @@ def test_deny_reason_dir_behaviour(tmp_path: Path):
link = tmp_path / "link"
link.symlink_to(d)
parent_link = tmp_path / "parent_link"
parent_link.symlink_to(tmp_path, target_is_directory=True)
assert pol.deny_reason_dir(str(d)) is None
assert pol.deny_reason_dir(str(link)) == "symlink"
assert pol.deny_reason_dir(str(parent_link / "dir")) == "symlink"
assert pol.deny_reason_dir(str(f)) == "not_directory"
# Denied by glob.