Sandbox filesystem allowlist doesn't resolve symlinks, causing "Operation not permitted" for Bash tools

Resolved 💬 3 comments Opened Feb 7, 2026 by karptonite Closed Mar 8, 2026

Bug Description

When Claude Code's working directory contains symlinked subdirectories, the sandbox filesystem write allowlist uses the symlink paths. However, Bash commands (git, prettier, node, etc.) resolve symlinks to their real paths before performing file operations. The resolved real paths aren't in the allowlist, so the sandbox blocks the writes with "Operation not permitted".

This forces users to either disable the sandbox entirely (dangerouslyDisableSandbox: true) or stop using symlinks — neither of which is ideal.

Environment

  • OS: macOS 15 (Darwin 25.2.0)
  • Claude Code version: 2.1.34
  • Shell: zsh

Steps to Reproduce

  1. Create a workspace directory with symlinks to repos:

``
~/workspace/
├── CLAUDE.md
├── backend/ → symlink to ~/repos/backend/
└── frontend/ → symlink to ~/repos/frontend/
``

  1. Launch Claude Code from ~/workspace/ with sandbox enabled
  1. Ask Claude to run any Bash command that writes to a file inside a symlinked directory, e.g.:

``bash
cd frontend && npx prettier --write src/app/component.ts
``

Expected Behavior

The sandbox should resolve symlinks when building the write allowlist (or when checking paths against it), so that writes to real paths covered by symlinked allowlist entries are permitted.

Actual Behavior

The sandbox allowlist contains ~/workspace/frontend/ but the Bash command resolves the symlink and writes to ~/repos/frontend/src/app/component.ts. Since ~/repos/frontend/ is not in the allowlist, the operation fails with "Operation not permitted".

This affects any tool that resolves symlinks internally, including:

  • git (commit, checkout, stash — all resolve to real paths)
  • npx prettier --write
  • Any Node.js/PHP tool that uses fs.realpath or equivalent

Workaround

Launch Claude Code from the directory containing the real (non-symlinked) repos instead. This avoids the symlink resolution mismatch entirely, but loses the ability to use a dedicated workspace directory.

Alternatively, set dangerouslyDisableSandbox: true, which defeats the purpose of sandboxing.

Related

  • #17732 — CLAUDE.md parent traversal also doesn't preserve symlink paths (same root cause: symlinks resolved too early)
  • #16507 — Glob tool doesn't follow symlinks

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗