[BUG] Cowork sandbox: unlink(2) returns EPERM on owned files, breaks .git lock cleanup
Subject
Cowork sandbox: unlink(2) returns EPERM on files the sandbox user owns with rw------- mode, breaking .git/*.lock cleanup
Summary
Inside a Cowork sandbox session, unlink(2) fails with EPERM ("Operation not permitted") on regular files that the calling sandbox user owns with mode rw-------. Truncation (echo > file), chmod, and content writes all succeed; only the unlink-class operations (rm, unlink, mv over existing destination, find -delete) fail. Standard POSIX permission semantics permit unlink in this state; the cause appears to be environmental (mount options, LSM profile, container security layer, or similar layer above POSIX), not a permissions misconfiguration on the file or directory itself.
The most operationally painful consequence is that git cannot clean up its transient .git/*.lock files. Every commit succeeds at writing the object data but leaves orphaned lock files, blocking the next git operation in the same session until an external actor (host shell) deletes them.
Environment
- Cowork sandbox (Anthropic-managed; whatever the current production build is at the time of this report — session-id / image-id available on request if Anthropic's intake form requests it).
- The host project is a normal git repository (
git version 2.x, standard layout, no submodules, no LFS, no special filesystem in the repo path). - The repository is mounted into the sandbox at a stable path (Anthropic-determined; from inside the sandbox it appears as a regular directory).
Symptom
Verbatim git commit output from inside the Cowork sandbox (representative, across many sessions):
warning: unable to unlink '.git/objects/{NN}/tmp_obj_{XXX}': Operation not permitted
warning: unable to unlink '.git/HEAD.lock': Operation not permitted
warning: unable to unlink '.git/objects/maintenance.lock': Operation not permitted
[branch sha] commit message
The commit lands (object data is written, ref is updated, working tree is consistent). The warning-listed lock files persist on disk.
Post-commit lock-file inventory (typical):
$ find .git -name "*.lock" -o -name "tmp_*"
.git/HEAD.lock
.git/index.lock
.git/objects/maintenance.lock
.git/objects/{NN}/tmp_obj_{XXX}
.git/refs/heads/{branch}.lock # appears when refs are updated
.git/worktrees/{wt}/index.lock # appears when committing from a worktree
The next git operation in the same Cowork session that touches any of these resources fails (the .git/index.lock blocks any operation that modifies the index; .git/HEAD.lock blocks ref updates; etc.).
Minimal reproducer
Run inside a Cowork sandbox, in any git repository the sandbox can access:
# 1. Confirm file ownership and mode look writable + unlinkable.
touch /tmp/reproducer-file
ls -la /tmp/reproducer-file
id
# 2. Truncation and chmod succeed.
echo "content" > /tmp/reproducer-file && echo "write OK"
chmod 600 /tmp/reproducer-file && echo "chmod OK"
# 3. Unlink fails with EPERM.
rm /tmp/reproducer-file
# Expected: silent success.
# Actual: rm: cannot remove '/tmp/reproducer-file': Operation not permitted
# 4. Strace narrows it to the unlinkat syscall.
strace -e trace=unlinkat rm /tmp/reproducer-file 2>&1 | head -5
# Expected: unlinkat(...) = 0
# Actual: unlinkat(...) = -1 EPERM (Operation not permitted)
The strace step is optional; the first three steps reproduce the symptom and rule out POSIX-level misconfiguration.
What we've ruled out
- File ownership / mode: the calling sandbox user owns the file; mode is
rw-------. POSIX permits the owner to unlink files in a directory they have write+execute on. (We confirmed write+execute on the parent directory; truncation through the same path succeeds, which requires the same directory traversal.) - Git is healthy: same repository, same commits, identical operations from the host shell and from Claude Code's terminal succeed without warnings and leave no orphan locks. The failure mode is sandbox-environment-specific, not git-specific.
- A single operation type: not a one-off race. The behavior is consistent across every session and every commit.
- Not a sticky-bit / chattr-immutable issue at first glance:
lsattrandls -lof the affected files don't show anything unusual, but we haven't done a deep filesystem-attribute audit — Anthropic's internal tooling is better-positioned for that.
Operational impact
- Per-session recurring friction. Every Cowork-side commit cycle leaves orphan locks. The host-shell recovery is
find ~/path/to/repo/.git -name "*.lock" -print -deletebefore the next Cowork-side git operation. This is not a one-time setup cost; it recurs every cycle. - The
git worktree addworkaround helps but is partial. Creating a worktree at/tmp/<host-repo>-{branch}-worktreeand working from it lets Cowork commit to a feature branch without needinggit checkoutat the Cowork mount (which would otherwise fail trying to unlink working-tree files during the checkout swap). The unlink-EPERM on.git/*.lockcleanup still applies via the worktree, but at least the checkout problem is sidestepped. The worktree workaround does not covergit stash,git rebase,git reset --hard, orgit push(push has a separate cause — see below). - Outbound network is also blocked (separate issue, mentioned for completeness):
git pushfrom inside the Cowork sandbox fails withConnection closed by UNKNOWN port 65535, suggesting the sandbox has no outbound reachability to the host project's git remote. The host shell handlesgit push. We don't expect this in scope for the unlink-EPERM report, but flagging since it's the same operational surface.
What we'd like to understand
- Is the unlink-EPERM behavior intentional and expected as part of the sandbox's security posture (e.g., to prevent the sandbox from deleting files written by other Anthropic processes), or is it an unintended side-effect of the security layer?
- If intentional, what's the recommended workflow for git operations from inside the sandbox? Is there a sanctioned way to run
git commitsuch that lock-file cleanup succeeds? (We haven't found one in our exploration.) - If unintended, is this on the roadmap to address, or would a fix-request from us help prioritize it? We're happy to provide additional reproduction data, sandbox session IDs, or run targeted diagnostic commands if Anthropic engineers want to attach a probe.
- Is there a documented list of sandbox-environmental quirks Cowork users should expect? Documenting this one upstream would save other users the same diagnostic cycle.
Related upstream issues
This report describes the Cowork-managed Linux sandbox manifestation of what appears to be the same root-cause family as two existing reports:
- #55206 (Cowork on Windows; bash sandbox can create files on mounted host folder but unlink is denied)
- #52322 (sandbox.filesystem.allowWrite does not permit unlink / rm on macOS)
Filing this as a separate report since the originating environment is the Anthropic-managed Cowork Linux sandbox rather than user-host Windows or macOS bash sandboxes, but the underlying unlink-class denial pattern is identical. If Anthropic engineers conclude these all share a single fix, please close this report in favor of whichever upstream issue is the canonical reference.
Contact
GitHub issue author (filing via Claude Code on operator's behalf — Cowork's network isolation prevents direct filing from the sandbox).
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗