Merge branch 'feature/worktree-commands-v2' into merge/main-20261107
Brings the host-independent trust tests (4458fcc) that the Nix-based gate container needs.
🎯 Fix: 92 %
💥 Break: 1 %
💸 Cost: 100 %
⏱️ Time: 100 %
🛡️ Security: 100 %
🏆 Score: 91
🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 %
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
a324ed0b65
2 files changed
+25
-9
No files matched your search
@@ -91,7 +91,9 @@ replaced; a
|
|||||||
reported, never run, because an agent may have written it. The pinned program
|
reported, never run, because an agent may have written it. The pinned program
|
||||||
must be an absolute path or a root-owned command on a `PATH` entry that root
|
must be an absolute path or a root-owned command on a `PATH` entry that root
|
||||||
owns and no group or other user can write, up to `/`, so a binary planted in a
|
owns and no group or other user can write, up to `/`, so a binary planted in a
|
||||||
user-writable directory such as a virtualenv never runs. A bare name runs as
|
user-writable directory such as a virtualenv never runs. The Nix store never
|
||||||
|
counts: it is group-writable, and any user can have the daemon build
|
||||||
|
root-owned content there, so pin an absolute path on Nix. A bare name runs as
|
||||||
the resolved file that was checked. Inside a user namespace other than the
|
the resolved file that was checked. Inside a user namespace other than the
|
||||||
initial one, root means the overflow uid, under which the real root's files
|
initial one, root means the overflow uid, under which the real root's files
|
||||||
show there, as do those of every other unmapped owner. Outside such a
|
show there, as do those of every other unmapped owner. Outside such a
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@@ -113,6 +112,13 @@ class TestRootResolved(unittest.TestCase):
|
|||||||
stats["/usr/bin"] = (0, 0o040757)
|
stats["/usr/bin"] = (0, 0o040757)
|
||||||
self.assertIsNone(self._resolve(stats))
|
self.assertIsNone(self._resolve(stats))
|
||||||
|
|
||||||
|
def test_sticky_group_writable_ancestor_like_the_nix_store_is_refused(
|
||||||
|
self,
|
||||||
|
) -> None:
|
||||||
|
stats = self._tree()
|
||||||
|
stats["/usr"] = (0, 0o041775)
|
||||||
|
self.assertIsNone(self._resolve(stats))
|
||||||
|
|
||||||
def test_stat_error_is_refused(self) -> None:
|
def test_stat_error_is_refused(self) -> None:
|
||||||
stats = self._tree()
|
stats = self._tree()
|
||||||
del stats["/usr"]
|
del stats["/usr"]
|
||||||
@@ -131,24 +137,32 @@ class TestRootResolved(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class TestTrustedPath(unittest.TestCase):
|
class TestTrustedPath(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
trusted = [
|
||||||
|
entry
|
||||||
|
for entry in map(trust.root_resolved, os.defpath.split(os.pathsep))
|
||||||
|
if entry and os.path.isdir(entry)
|
||||||
|
]
|
||||||
|
if not trusted:
|
||||||
|
self.skipTest("no os.defpath directory is root-controlled on this host")
|
||||||
|
self.system = trusted[0]
|
||||||
|
|
||||||
def test_symlinked_entry_is_kept_only_resolved(self) -> None:
|
def test_symlinked_entry_is_kept_only_resolved(self) -> None:
|
||||||
system = os.path.dirname(os.path.realpath(shutil.which("true")))
|
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
link = os.path.join(tmp, "bin")
|
link = os.path.join(tmp, "bin")
|
||||||
os.symlink(system, link)
|
os.symlink(self.system, link)
|
||||||
with patch.dict(os.environ, {"PATH": link}):
|
with patch.dict(os.environ, {"PATH": link}):
|
||||||
self.assertEqual(trust.trusted_path(), system)
|
self.assertEqual(trust.trusted_path(), self.system)
|
||||||
|
|
||||||
def test_entry_keeps_the_resolution_it_was_checked_under(self) -> None:
|
def test_entry_keeps_the_resolution_it_was_checked_under(self) -> None:
|
||||||
system = os.path.dirname(os.path.realpath(shutil.which("true")))
|
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
link = os.path.join(tmp, "bin")
|
link = os.path.join(tmp, "bin")
|
||||||
os.symlink(system, link)
|
os.symlink(self.system, link)
|
||||||
with (
|
with (
|
||||||
patch.dict(os.environ, {"PATH": link}),
|
patch.dict(os.environ, {"PATH": link}),
|
||||||
patch.object(trust.os.path, "realpath", side_effect=[system, tmp]),
|
patch.object(trust.os.path, "realpath", side_effect=[self.system, tmp]),
|
||||||
):
|
):
|
||||||
self.assertEqual(trust.trusted_path(), system)
|
self.assertEqual(trust.trusted_path(), self.system)
|
||||||
|
|
||||||
def test_no_root_controlled_entry_is_refused(self) -> None:
|
def test_no_root_controlled_entry_is_refused(self) -> None:
|
||||||
with (
|
with (
|
||||||
|
|||||||
Reference in new issue
Block a user