Skip to content

tasks: record.worktree is used as a cwd without containment validation #73

Description

@naashw

The destructive side is safe: removeTaskWorktree(cwd, taskId, …) recomputes the path from taskWorktreePath(cwd, taskId) (task-worktree.ts:546) and never reads record.worktree, and taskId is filtered by isTaskId before any join (tasks-store.ts:206, same in removeTaskDir).

The read/execute side is not. In the contract, worktree is only a length-bounded string — packages/contract/src/tasks.ts:844:

worktree: str(r.worktree, TASK_PATH_MAX),   // TASK_PATH_MAX = 500, no shape constraint

That string is then used as-is as a cwd:

  • task-runner.ts:1421git status
  • task-runner.ts:1427git add -A
  • task-runner.ts:1430 — commit
  • task-runner.ts:2241 — the agent's cwd
  • task-review.ts:359, task-checks.ts:862, task-checks.ts:1026, task-retention.ts:165

There is no startsWith(project.path) and no relative() check on any of these. The only path-escape guard in the codebase is container-git.ts:63, which validates the --git-dir link — unrelated.

Scenario: a task.json that is corrupted or hand-edited so that "worktree" points elsewhere (say /home/x/other-repo) → on the next turn ensureWorktree sees existsSync(record.worktree) as true and skips rematerialisation (task-runner.ts:1852), then the agent runs and git add -A && git commit lands in the other repository.

Low likelihood (it takes a corrupted or edited store), which is why this is minor — but the blast radius is someone else's repo, and the fix is small.

Suggested direction

Validate record.worktree before using it as a cwd: check containment in project.path with relative(), the way container-git.ts:63 already does for the git link. On failure, treat it as "rematerialise" rather than "execute".

Found while auditing a competitor harness (internal Ruflo audit): their worktree coordinator validates registry paths against escape on every read.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingseverity:minorMinor severity review finding

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions