| """Tests for file write safety and HERMES_WRITE_SAFE_ROOT sandboxing. |
| |
| Based on PR #1085 by ismoilh (salvaged). |
| """ |
|
|
| import os |
| from pathlib import Path |
|
|
| import pytest |
|
|
| from tools.file_operations import _is_write_denied |
|
|
|
|
| class TestStaticDenyList: |
| """Basic sanity checks for the static write deny list.""" |
|
|
| def test_temp_file_not_denied_by_default(self, tmp_path: Path): |
| target = tmp_path / "regular.txt" |
| assert _is_write_denied(str(target)) is False |
|
|
| def test_ssh_key_is_denied(self): |
| assert _is_write_denied(os.path.expanduser("~/.ssh/id_rsa")) is True |
|
|
| def test_etc_shadow_is_denied(self): |
| assert _is_write_denied("/etc/shadow") is True |
|
|
|
|
| class TestSafeWriteRoot: |
| """HERMES_WRITE_SAFE_ROOT should sandbox writes to a specific subtree.""" |
|
|
| def test_writes_inside_safe_root_are_allowed(self, tmp_path: Path, monkeypatch): |
| safe_root = tmp_path / "workspace" |
| child = safe_root / "subdir" / "file.txt" |
| os.makedirs(child.parent, exist_ok=True) |
|
|
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", str(safe_root)) |
| assert _is_write_denied(str(child)) is False |
|
|
| def test_writes_to_safe_root_itself_are_allowed(self, tmp_path: Path, monkeypatch): |
| safe_root = tmp_path / "workspace" |
| os.makedirs(safe_root, exist_ok=True) |
|
|
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", str(safe_root)) |
| assert _is_write_denied(str(safe_root)) is False |
|
|
| def test_writes_outside_safe_root_are_denied(self, tmp_path: Path, monkeypatch): |
| safe_root = tmp_path / "workspace" |
| outside = tmp_path / "other" / "file.txt" |
| os.makedirs(safe_root, exist_ok=True) |
| os.makedirs(outside.parent, exist_ok=True) |
|
|
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", str(safe_root)) |
| assert _is_write_denied(str(outside)) is True |
|
|
| def test_safe_root_env_ignores_empty_value(self, tmp_path: Path, monkeypatch): |
| target = tmp_path / "regular.txt" |
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", "") |
| assert _is_write_denied(str(target)) is False |
|
|
| def test_safe_root_unset_allows_all(self, tmp_path: Path, monkeypatch): |
| target = tmp_path / "regular.txt" |
| monkeypatch.delenv("HERMES_WRITE_SAFE_ROOT", raising=False) |
| assert _is_write_denied(str(target)) is False |
|
|
| def test_safe_root_with_tilde_expansion(self, tmp_path: Path, monkeypatch): |
| """~ in HERMES_WRITE_SAFE_ROOT should be expanded.""" |
| |
| safe_root = tmp_path / "workspace" |
| inside = safe_root / "file.txt" |
| os.makedirs(safe_root, exist_ok=True) |
|
|
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", str(safe_root)) |
| assert _is_write_denied(str(inside)) is False |
|
|
| def test_safe_root_does_not_override_static_deny(self, tmp_path: Path, monkeypatch): |
| """Even if a static-denied path is inside the safe root, it's still denied.""" |
| |
| monkeypatch.setenv("HERMES_WRITE_SAFE_ROOT", os.path.expanduser("~")) |
| assert _is_write_denied(os.path.expanduser("~/.ssh/id_rsa")) is True |
|
|
|
|
| if __name__ == "__main__": |
| pytest.main([__file__, "-v"]) |
|
|