Skip to content

fix(kanban): refuse to clean up paths outside scratch root (#28818)#29242

Closed
Jiahui-Gu wants to merge 1 commit into
NousResearch:mainfrom
Jiahui-Gu:fix/kanban-scratch-cleanup-safety-28818
Closed

fix(kanban): refuse to clean up paths outside scratch root (#28818)#29242
Jiahui-Gu wants to merge 1 commit into
NousResearch:mainfrom
Jiahui-Gu:fix/kanban-scratch-cleanup-safety-28818

Conversation

@Jiahui-Gu

Copy link
Copy Markdown
Contributor

Summary

Fixes #28818data-loss bug. hermes_cli/kanban_db.py::_cleanup_workspace ran shutil.rmtree(workspace_path) for any task whose workspace_kind == \"scratch\" (the DB default), but workspace_path is whatever the board/task config says — including a user-supplied real source directory (boards set-default-workdir) or a symlink inside the scratch root that points at ~/src. Either turned task completion into rm -rf on real data.

Fix

_cleanup_workspace (minimal change):

  1. Resolve both the workspace path and workspaces_root() with resolve(strict=False) (collapses symlinks).
  2. Require resolved.is_relative_to(scratch_root) and resolved != scratch_root; otherwise log a warning and return without deleting.
  3. Refuse outright if wp.is_symlink() so a symlinked scratch entry can never escape via shutil.rmtree symlink-follow.
  4. Python <3.9 fallback uses relative_to(...) + ValueError.

The orthogonal hardening (reject scratch-task create-time when workdir is outside workspaces_root) is left for a follow-up — out of scope for a minimal data-loss fix.

Test plan

  • New TestScratchCleanupSafety in tests/hermes_cli/test_kanban_db.py — 4 cases:
    • workspace pointing at a sibling real_source/ dir outside scratch root is preserved
    • symlink inside scratch root pointing at real_source/ does not get followed
    • legitimate scratch subdir is still cleaned up
    • row pointing at the scratch root itself is refused
  • Full file 162/162 pass

🤖 Generated with Claude Code

@alt-glitch alt-glitch added type/security Security vulnerability or hardening P1 High — major feature broken, no workaround comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins labels May 20, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing fix with #28819 — both add containment guards to _cleanup_workspace to prevent shutil.rmtree on paths outside scratch root. Same root cause #28818.

@Jiahui-Gu

Copy link
Copy Markdown
Contributor Author

Thanks @alt-glitch for the cross-reference to #28819.

Both PRs add containment guards to _cleanup_workspace for the same #28818 root cause. Quick diff for maintainer triage:

  • Both gate shutil.rmtree behind a same-root check
  • Implementation details differ (anchor resolution, error vs silent skip on out-of-root paths)

Happy to close in favor of #28819 if its shape is preferred, or to align the implementations if you'd like the more defensive variant here. Either way, the security improvement should land — flagging so maintainers can pick whichever they prefer.

@teknium1

Copy link
Copy Markdown
Contributor

Closing as superseded by #31708 (merged: commits 80ad160 + 23115b5 + ce529d6 on main).

Your containment fix targets the same site with the same intent. We picked @briandevans's #28819 because it covers more managed-scratch roots (env override + per-board workspaces) and rejects sibling metadata subtrees explicitly. Your symlink-unlink branch is a sensible defense — we'll fold that into a follow-up if the broader symlink-protection cluster needs it.

Thanks — concurrent independent discovery on a real P0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/plugins Plugin system and bundled plugins P1 High — major feature broken, no workaround type/security Security vulnerability or hardening

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Kanban scratch workspace cleanup can delete real source directories

4 participants