Skip to content

fix(kanban): guard _cleanup_workspace against paths outside workspaces_root#30718

Closed
SimoKiihamaki wants to merge 1 commit into
NousResearch:mainfrom
SimoKiihamaki:fix/30151-kanban-workspace-cleanup-safety
Closed

fix(kanban): guard _cleanup_workspace against paths outside workspaces_root#30718
SimoKiihamaki wants to merge 1 commit into
NousResearch:mainfrom
SimoKiihamaki:fix/30151-kanban-workspace-cleanup-safety

Conversation

@SimoKiihamaki

Copy link
Copy Markdown
Contributor

Fixes #30151

Problem

_cleanup_workspace() called shutil.rmtree() on any path in workspace_path without verifying it was under the Kanban workspaces root. If default_workdir pointed to a real directory, completing a scratch task would recursively delete it.

Fix

Added path validation: workspace cleanup now resolves the workspace path and verifies it is under workspaces_root() before allowing deletion. Paths outside the root are refused with a warning log. This guards against:

  • default_workdir pointing to a user directory
  • Symlinks that escape the workspaces root
  • Relative path traversal (../../)

Testing

  • Workspace inside workspaces_root: deleted normally
  • Workspace outside workspaces_root: refused with warning
  • Symlink escaping: refused
  • Path traversal attempt: refused
  • Nonexistent task: no-op
  • Non-scratch workspace (worktree): not deleted

Copilot AI review requested due to automatic review settings May 23, 2026 03:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a safety guard to _cleanup_workspace so scratch workspace deletion is restricted to paths under workspaces_root, preventing accidental data loss when workspace_path points outside the kanban workspaces directory. Symlinks and relative traversal are resolved before the check.

Changes:

  • Introduces _is_safe_workspace_path helper that compares resolved paths against the resolved workspaces root.
  • Updates _cleanup_workspace to refuse deletion of paths outside workspaces_root, logging a warning and still cleaning up the tmux session.
  • Adds a comprehensive test module covering normal cleanup, outside-root paths, symlink escapes, traversal attempts, non-scratch kinds, and the helper itself.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
hermes_cli/kanban_db.py Adds resolved-path safety guard before scratch workspace deletion and the _is_safe_workspace_path helper.
tests/hermes_cli/test_kanban_workspace_cleanup.py New tests verifying the safety guard across inside/outside, symlink, traversal, non-scratch, and missing-task scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hermes_cli/kanban_db.py
pass # best-effort — never block completion


def _is_safe_workspace_path(workspace_path: Path, workspaces_root: Path) -> bool:
Comment on lines +78 to +79
def test_symlink_escaping_workspace_is_not_deleted(self, kanban_home, tmp_path):
"""A symlink inside workspaces_root pointing outside must not be followed for deletion."""
Comment thread hermes_cli/kanban_db.py
Comment on lines +2932 to +2934
wp = Path(path).resolve()
root = workspaces_root().resolve()
if not _is_safe_workspace_path(wp, root):
@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 labels May 23, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Note: This is a competing fix for #28818 alongside #28819 and #29242. Also references #30151 (confirmed duplicate of #28818). Please coordinate with the other PRs to avoid redundant merges.

@teknium1

Copy link
Copy Markdown
Contributor

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

Your containment-via-workspaces_root() approach is the same shape as @briandevans's salvaged fix. We picked #28819 because it submitted first AND covers more roots (env override, per-board sub-roots) with more thorough tests (kanban metadata sibling rejection, workspaces-root-itself rejection). Same outcome, broader coverage.

Thanks for the catch on #28818 — independent confirmation of the data-loss vector helped prioritize this.

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 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.

Hermes Kanban “Scratch Workspace” Cleanup Silently Deleted My Entire Projects Directory

4 participants