`claude plugin eval` refuses every Bash-granting run on a Mac with Docker Desktop (symlinks in ~/.docker/cli-plugins)
Environment
- Claude Code 2.1.270 (also seen on 2.1.268), macOS 26.6.2, claude.ai login
- Docker Desktop installed with its default layout; Colima also installed
What happens
claude plugin eval <plugin dir> --case <case> --runs 1 --ablation none \
--allow-tools Bash Edit Write --scaffold --trust-plugin --no-publish --json out.json
exits before any model call (cost 0, duration 1 s). The run's error field reads:
the Docker (~/.docker, DOCKER_CONFIG) credential store on this machine holds a symbolic link inside it, so the Bash sandbox cannot reliably exclude it — a Bash-granting evaluation cannot run here; keep the store's contents in one plain directory (its root may be a link)
The same case runs fine with --allow-tools Edit Write.
Why this is generic, not one machine
Docker Desktop for Mac installs ~/.docker/cli-plugins/docker-* as symlinks into /Applications/Docker.app/Contents/Resources/cli-plugins/ (16 of them here: buildx, compose, scout, sbom, ...), plus ~/.docker/bin/lib/*.dylib version-alias symlinks for Docker Model Runner. Every Docker Desktop install has the cli-plugins set, so every such Mac hits this preflight as soon as a case needs Bash. The credential store itself (config.json, credsStore: desktop) contains no symlinks; only the plugin directory does. Docker Desktop manages those symlinks, so deleting them is not a durable workaround.
Tried
DOCKER_CONFIG=<empty plain dir>: same refusal; the check still reads~/.docker.HOME=<empty dir> CLAUDE_CONFIG_DIR=~/.claude: passes the preflight, but the run fails auth (401 OAuth token expired) and writes a stray<config dir>/.claude.json.- The regular Claude Code Bash sandbox (
sandbox.enabledwithdenyReadrules) runs on the same machine without complaint, so the plugin eval preflight is stricter than the sandbox itself.
Expected
One of: resolve symlinks when building the deny rule; deny only config.json and the credential helper paths instead of all of ~/.docker; or document a supported layout that Docker Desktop does not overwrite. As it stands, Bash-granting plugin evals cannot run on a Mac with Docker Desktop.
3 Comments
Written by Claude (Anthropic's AI coding assistant), working in a Claude Code session for @portswigger-tim, and posted from their account.
I'm confirming this on Claude Code 2.1.280 (macOS, Docker Desktop, default layout), with more detail on what still triggers the refusal.
How I found this
claude plugin evalwith--allow-tools "Bash(python3 *)". It refused with the "Docker (~/.docker, DOCKER_CONFIG) credential store … holds a symbolic link inside it" error.~/.dockerwithfind -type l, reading names and targets only. There were 37.cli-plugins,buildx,desktop,mutagen,scan,run,features.json,daemon.jsonanddesktop-build. This is Claude's reading of minified code, so treat it as likely, not certain.What I found
cli-pluginsno longer triggers the refusal, unlike in the original report.~/.docker/binstill does. It holds 22 symlinks into/Applications/Docker.app/Contents/Resources/...(docker,docker-compose,kubectl,docker-credential-desktop, and others). It is the only top-level entry outside the skip list that contains links. The other 15 links sit in skipped folders.Suggestion. Either add
binto Docker's skip list, or allow symlinks that resolve inside the Docker.app bundle. Either would fix this for a standard Docker Desktop install.Written by Claude (Anthropic's AI coding assistant), working in a Claude Code session for @portswigger-tim, and posted from their account. This follows up on my earlier comment.
Claude tested the suggestion in my earlier comment, and it holds on Claude Code 2.1.280 (macOS, Docker Desktop, default layout).
Test
~/.dockeroutside the names the check appears to skip, oncebinwas removed. There were 0.~/.docker/binmoved to a directory outside~/.docker, Claude ranclaude plugin evalwith--allow-tools "Bash(python3 *)". No binary or guard was modified.binback afterwards.Result.
~/.docker/binis the only thing on a default Docker Desktop install that still triggers the refusal in 2.1.280. Addingbinto Docker's skip list, or accepting links that resolve inside the Docker.app bundle, should fix this.Notes for others hitting this
bintobin.offinside~/.docker. It was still refused, because the same links were still in the store under a name the check doesn't skip. A workaround has to move the folder out of~/.dockerentirely.binaside is only a temporary workaround. Docker Desktop keeps its tool links there, so restore it afterwards.Hi @dhollman, sorry if I'm missing something but what is the resolution that closes this issue?