From 49a46a7d1c953eb927b887fe0441ac990973894c Mon Sep 17 00:00:00 2001 From: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> Date: Sun, 5 Jul 2026 03:57:19 -0700 Subject: [PATCH] fix: create fallback state file with owner-only 0600 permissions --- app/state_store.py | 6 +++++- app/tests/test_state_store.py | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/state_store.py b/app/state_store.py index 11bb5bb..c2a69f7 100644 --- a/app/state_store.py +++ b/app/state_store.py @@ -148,7 +148,11 @@ class AtomicJsonStore: raise def _direct_write(self, payload: dict[str, Any]) -> None: - with open(self.path, "w", encoding="utf-8") as f: + # Create with 0o600 so the fallback keeps the owner-only permissions the + # atomic path gets from mkstemp; state files can contain URLs and + # per-download option overrides that must not leak on shared mounts. + fd = os.open(self.path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) + with os.fdopen(fd, "w", encoding="utf-8") as f: self._write_payload(payload, f) f.flush() self._best_effort_fsync(f.fileno()) diff --git a/app/tests/test_state_store.py b/app/tests/test_state_store.py index 0189808..9309f4f 100644 --- a/app/tests/test_state_store.py +++ b/app/tests/test_state_store.py @@ -36,6 +36,8 @@ class StateStoreTests(unittest.TestCase): self.assertTrue(os.path.exists(path)) self.assertTrue(any(path in message for message in logs.output)) + # Fallback keeps owner-only permissions, matching the atomic path. + self.assertEqual(os.stat(path).st_mode & 0o777, 0o600) payload = store.load() self.assertEqual(payload["items"], [{"key": "a"}]) @@ -64,7 +66,10 @@ class StateStoreTests(unittest.TestCase): "state_store.tempfile.mkstemp", side_effect=PermissionError(1, "Operation not permitted"), ): - with patch("builtins.open", side_effect=PermissionError(13, "Permission denied")): + with patch( + "state_store.os.open", + side_effect=PermissionError(13, "Permission denied"), + ): with self.assertRaises(PermissionError) as ctx: store.save({"items": [{"key": "a"}]})