From 9911b3d195e168ff4c9976e45ab069c9693f6871 Mon Sep 17 00:00:00 2001 From: erlandl4g <76598482+erlandl4g@users.noreply.github.com> Date: Mon, 20 Jul 2026 08:56:22 +0300 Subject: [PATCH] test: sandbox HOME in test_claude_md.py so uninstall tests cannot delete the real user skill claude_uninstall() removes the USER-scope skill tree (~/.claude/skills/ graphify) since #1121, but this file's uninstall tests predate that and called it with no Path.home isolation. Running the suite on a dev machine deleted the developer's real installed skill; where that path is a symlink into a git checkout (Skills claude_config/skills/graphify), it silently deleted tracked files (2026-07-19 22:01 UTC nightly-audit incident). Autouse fixture redirects both pathlib.Path.home and HOME into tmp_path so every current and future test in this file is home-isolated, including subprocess-based helpers. Also clears CLAUDE_CONFIG_DIR, the second env escape hatch install.py's claude-platform resolver checks before Path.home() (caught in independent audit). --- tests/test_claude_md.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/test_claude_md.py b/tests/test_claude_md.py index cac7940834..89dc5514fc 100644 --- a/tests/test_claude_md.py +++ b/tests/test_claude_md.py @@ -4,6 +4,31 @@ from graphify.__main__ import claude_install, claude_uninstall, _CLAUDE_MD_MARKER, _CLAUDE_MD_SECTION +@pytest.fixture(autouse=True) +def _sandbox_home(tmp_path, monkeypatch): + """Redirect the user home into tmp_path for every test in this file. + + claude_uninstall() removes the USER-scope skill tree at + ~/.claude/skills/graphify (issue #1121), so any test that calls it without + home isolation deletes the developer's real installed skill. On machines + where that path is a symlink into a git checkout, an unsandboxed run + silently deletes tracked files (this happened: 2026-07-19, a nightly-audit + full-suite run emptied the live install through exactly that symlink). + HOME is patched too so subprocess-based helpers inherit the sandbox. + + CLAUDE_CONFIG_DIR is also cleared: install.py's claude-platform + destination resolver checks that env var before Path.home(), so a + developer/CI environment with CLAUDE_CONFIG_DIR set would otherwise + bypass the sandbox above and hit the same real-deletion bug again. + """ + home = tmp_path / "sandbox-home" + home.mkdir() + monkeypatch.setenv("HOME", str(home)) + monkeypatch.delenv("CLAUDE_CONFIG_DIR", raising=False) + monkeypatch.setattr(Path, "home", classmethod(lambda cls: home)) + return home + + # --------------------------------------------------------------------------- # install # ---------------------------------------------------------------------------