agent: fix readiness authority-git mode mischeck (group-shared repo)
ServerOwnedEvidenceSource.assert_ready() applied the evidence-root strict
group/world-writable check to the authority Git directory too. A valid
setgid/group-shared authority repository (core.sharedRepository=group,
02775) permanently failed readiness with COLLECTOR_EVIDENCE_ROOT_MODE_DENIED.
Fix: authority Git requires only exists + directory + non-symlink; the strict
st_mode & 0o022 and owner checks apply to the evidence root only. Builder
readiness remains infrastructure-only (independent of recipe evidence);
BuildTrustedCandidateV1 stays evidence-gated and fail-closed.
Add regression proving a group-shared 02775 authority is accepted while a
group/world-writable evidence root is still rejected.
Base: 8bf363143e (exact)
Files: 2 (modified), +36/-11
Patch SHA-256: 5335025a9b193a50ad08c45e41ca6e8c7abdc77defec90c348f5149a0fe13b44
This commit is contained in:
@@ -367,15 +367,15 @@ class ServerOwnedEvidenceSource:
|
||||
raise BuilderError(code) from exc
|
||||
if not stat.S_ISDIR(metadata.st_mode) or path.is_symlink():
|
||||
raise BuilderError(code)
|
||||
if os.name != "nt" and metadata.st_mode & 0o022:
|
||||
raise BuilderError("COLLECTOR_EVIDENCE_ROOT_MODE_DENIED")
|
||||
if (
|
||||
path == self._evidence_root
|
||||
and os.name != "nt"
|
||||
and self._expected_owner_uid is not None
|
||||
and metadata.st_uid != self._expected_owner_uid
|
||||
):
|
||||
raise BuilderError("COLLECTOR_EVIDENCE_ROOT_OWNER_DENIED")
|
||||
if path == self._evidence_root:
|
||||
if os.name != "nt" and metadata.st_mode & 0o022:
|
||||
raise BuilderError("COLLECTOR_EVIDENCE_ROOT_MODE_DENIED")
|
||||
if (
|
||||
os.name != "nt"
|
||||
and self._expected_owner_uid is not None
|
||||
and metadata.st_uid != self._expected_owner_uid
|
||||
):
|
||||
raise BuilderError("COLLECTOR_EVIDENCE_ROOT_OWNER_DENIED")
|
||||
|
||||
def _digest(self, path: Path) -> str:
|
||||
digest = hashlib.sha256()
|
||||
|
||||
@@ -323,9 +323,11 @@ def test_readiness_is_independent_from_recipe_evidence_but_build_remains_fail_cl
|
||||
policy = load_builder_policy(POLICY_PATH)
|
||||
config = TrustedCandidateBuilderConfig.from_policy(policy)
|
||||
evidence_root = tmp_path / "evidence"
|
||||
evidence_root.mkdir(mode=0o700)
|
||||
evidence_root.mkdir()
|
||||
evidence_root.chmod(0o700)
|
||||
authority_git = tmp_path / "repo.git"
|
||||
authority_git.mkdir(mode=0o700)
|
||||
authority_git.mkdir()
|
||||
authority_git.chmod(0o2775)
|
||||
|
||||
source = ServerOwnedEvidenceSource(
|
||||
config,
|
||||
@@ -358,6 +360,29 @@ def test_readiness_is_independent_from_recipe_evidence_but_build_remains_fail_cl
|
||||
server.handle_request(build, connection=object())
|
||||
|
||||
|
||||
def test_readiness_keeps_evidence_root_permissions_strict_with_group_shared_authority(tmp_path) -> None:
|
||||
config = TrustedCandidateBuilderConfig.from_policy(load_builder_policy(POLICY_PATH))
|
||||
evidence_root = tmp_path / "evidence"
|
||||
evidence_root.mkdir()
|
||||
evidence_root.chmod(0o720)
|
||||
authority_git = tmp_path / "repo.git"
|
||||
authority_git.mkdir()
|
||||
authority_git.chmod(0o2775)
|
||||
|
||||
source = ServerOwnedEvidenceSource(
|
||||
config,
|
||||
authority_git,
|
||||
evidence_root,
|
||||
expected_owner_uid=None,
|
||||
git_runner=lambda *_args, **_kwargs: SimpleNamespace(
|
||||
stdout="a" * 40 + "\n", returncode=0
|
||||
),
|
||||
)
|
||||
|
||||
with pytest.raises(BuilderError, match="COLLECTOR_EVIDENCE_ROOT_MODE_DENIED"):
|
||||
source.assert_ready()
|
||||
|
||||
|
||||
def test_unix_client_applies_bounded_timeout_and_fails_closed(monkeypatch) -> None:
|
||||
observed = {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user