fix(kvb-org-rasci): open the register and its lock without following links
The council root is writable by every agent, and operator.py runs rasci.database() outside the sandbox. A symlinked rasci.json made it read any JSON file the operator can read and write it back into the council as a regular file; a symlinked rasci.lock made it create files at the link target; a FIFO hung every register call. load() now reads through nofollow.read_text and database() locks and writes through nofollow.locked and nofollow.replace. A register that is no object of task objects, or nested past the recursion limit, exits 2 instead of a traceback. nofollow.open_below also refuses a file with more than one link, so a hard link to a file outside the council is refused like a symlink. 🎯 Fix: 96 % 💥 Break: 3 % 💸 Cost: 99 % ⏱️ Time: 95 % 🛡️ Security: 100 % 🏆 Score: 99 🚦 Gate: ✅ 90/5, cost and time <= 100, security 100 % Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
13b360227b
commit
8e180be256
4 files changed
+98
-20
No files matched your search
@@ -100,6 +100,17 @@ class TestNofollow(unittest.TestCase):
|
||||
write(link)
|
||||
self.assertFalse(dangling.exists())
|
||||
|
||||
def test_a_hard_linked_name_is_refused_and_its_target_kept(self):
|
||||
followers = {name: write for name, write in self.writes(self.root).items() if name not in ("replace", "create")}
|
||||
for name, write in followers.items():
|
||||
with self.subTest(write=name):
|
||||
link = self.root / name
|
||||
os.link(self.victim, link)
|
||||
with self.assertRaises(OSError):
|
||||
write(link)
|
||||
self.assertEqual(self.victim.read_text(encoding="utf-8"), "keep")
|
||||
link.unlink()
|
||||
|
||||
def test_a_symlinked_directory_is_refused_and_nothing_lands_in_its_target(self):
|
||||
(self.root / "d").symlink_to(self.victims)
|
||||
(self.victims / "f").write_text("keep", encoding="utf-8")
|
||||
|
||||
Reference in new issue
Block a user