claude-code icon indicating copy to clipboard operation
claude-code copied to clipboard

[DOCS] Sandbox Edit permissions for bash write access not clearly documented

Open Moredread opened this issue 2 months ago • 4 comments

Documentation Type

Unclear/confusing documentation

Documentation Location

https://docs.claude.com/en/docs/claude-code/settings#sandbox-settings

Section/Topic

Sandbox filesystem permissions - Edit and Bash allow rules

Current Documentation

From https://docs.claude.com/en/docs/claude-code/settings#sandbox-settings, under "Sandbox settings":

"Edit allow rules permit file writes (in addition to the defaults, e.g. the current working directory)"

From https://docs.claude.com/en/docs/claude-code/sandboxing, in the "Default behavior" section:

"Filesystem restrictions are configurable: Define custom allowed and denied paths through settings"

Neither page explicitly states that Edit() rules control bash filesystem writes.

What's Wrong or Missing?

The documentation never explicitly states that Edit() allow rules extend filesystem write permissions for bash commands running in the sandbox. This creates severe confusion:

  1. Users assume Write() permissions would control filesystem writes (they only control the Write tool)
  2. The statement "Edit allow rules permit file writes" is ambiguous - it's unclear if this applies to:
    • The Edit tool only, OR
    • All bash filesystem write operations in the sandbox
  3. There's no clear example showing how to allow bash commands to write outside the working directory in sandboxed mode
  4. The relationship between permission rules (Edit/Write/Read) and sandbox filesystem access is never clarified
  5. Users attempting to solve this problem find conflicting information online mixing non-sandboxed and sandboxed permission systems

Suggested Improvement

Add a dedicated section to the Sandboxing documentation (https://docs.claude.com/en/docs/claude-code/sandboxing), after the "Default behavior" section and before "Network restrictions":

Extending Bash Write Permissions in Sandbox Mode

By default, bash commands in the sandbox can only write to the current working directory. Any bash operation that writes files (including echo >, touch, mkdir, cp, or tools like just) will fail with "Read-only file system" errors when attempting to write outside the working directory.

To allow bash commands to write to additional directories, use Edit allow rules:

{
  "permissions": {
    "allow": [
      "Edit(/path/to/directory/**)"
    ]
  },
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true
  }
}

Important:

  • Edit() permissions extend filesystem write access for all bash operations in the sandbox
  • Write() permissions only control the Write tool and do NOT affect any bash write capabilities
  • Use glob patterns like /** to allow writes to all files within a directory

Common use cases:

  • Allow temporary file creation: Edit(/tmp/myapp/**)
  • Allow tools to write to runtime directories: Edit(/run/user/1000/just/**)
  • Allow build tools to write to cache directories: Edit(/home/user/.cache/build/**)

Impact: High - Prevents users from using sandboxed mode with any bash operations that need to write to specific directories outside the working directory

Additional Context:

This issue causes severe confusion during troubleshooting where users:

  1. Try Write() permissions (doesn't work - only affects the Write tool)
  2. Try filesystem.allowWrite configuration (not exposed in Claude Code's settings.json)
  3. Find conflicting information from people discussing non-sandboxed mode
  4. Only discover Edit() works through trial and error after extensive research

The underlying sandbox-runtime library uses allowWrite configuration, but Claude Code exposes this through Edit() permissions instead - this mapping should be clearly documented.


Reproduction Steps

Prerequisites:

  • Claude Code with sandbox enabled
  • Configuration: "sandbox": { "enabled": true, "autoAllowBashIfSandboxed": true }

Steps:

  1. Try any bash write operation outside the working directory:

    echo "test" > /tmp/test.txt
    
  2. Observe the error:

    bash: line 4: /tmp/test.txt: Read-only file system
    
  3. Add "Write(/tmp/**)" to permissions.allow list in .claude/settings.local.json

  4. Reload Claude Code and retry the same command

  5. Observe it still fails with the same error:

    bash: line 4: /tmp/test.txt: Read-only file system
    

    (Write permissions don't apply to bash)

  6. Replace "Write(/tmp/**)" with "Edit(/tmp/**)" in settings

  7. Reload Claude Code and retry

  8. Observe it now succeeds:

    echo "test" > /tmp/test.txt && cat /tmp/test.txt
    # Output: test
    

    (Edit permissions control bash filesystem writes)

Expected Documentation

The documentation should clearly state in the Sandboxing section:

  • How to extend bash write permissions beyond the working directory
  • That Edit() allow rules control all bash filesystem writes in sandbox mode
  • That Write() allow rules only control the Write tool, not bash commands
  • Examples showing common bash operations (echo, touch, mkdir, etc.) and tools
  • Clear distinction between tool permissions and sandbox filesystem access

Impact

High - Prevents users from using a feature

Additional Context

Generated by: Claude Code (Sonnet 4.5) during sandbox permission troubleshooting session

Environment:

  • claude-code 2.0.27 (Claude Code)
  • Platform: Linux (NixOS)
  • Sandbox: Enabled with autoAllowBashIfSandboxed: true
  • Date: 2025-10-26

Other related docs: https://docs.claude.com/en/docs/claude-code/sandboxing

Moredread avatar Oct 26 '25 15:10 Moredread

Follow-up: Additional Permission Inconsistencies Found

While testing sandbox permissions, I discovered what appear to be broader issues with deny rules that warrant further investigation. I haven't tested all edge cases, not symlink reflection, and other escape mechanisms, as the basic permissions don't seem to work consistently.

Observed Behavior:

  • Read() deny rules: Work with relative sub-paths (e.g., Read(./.env)), but appear to be ignored with absolute paths (e.g., Read(/tmp/secret.txt)) and relative paths like '../secrets/' for Read/Write/Edit tools.
  • Write() deny rules: Appear to be ignored entirely by Write/Edit tools
  • Edit() deny rules: Work consistently (and also block Write tool)
  • Bash commands: Respect all deny rule types correctly

Quick Test:

{
  "permissions": {
    "deny": [
      "Read(/tmp/test.txt)",      // Appears ignored by Read tool
      "Write(~/.claude/test)",    // Appears ignored by Write tool
      "Edit(~/.claude/test2)"     // Works as expected
    ]
  }
}

This may be related to closed issues #6631, #6699, and #4467. Those issues suggest deny rules for Read/Write tools have been problematic for some time.

Recommendation for investigation: The interaction between deny rule types (Read/Write/Edit), path formats (relative/absolute), and different tools needs systematic testing to understand the actual behavior vs. documented behavior.

Moredread avatar Oct 26 '25 16:10 Moredread

Seems to be hardcoded, currently:

function jaB() {
        let A = xL1(),
                B = [
                        "/dev/stdout",
                        "/dev/stderr",
                        "/dev/null",
                        "/dev/tty",
                        "/dev/dtracehelper",
                        "/dev/autofs_nowait",
                        "/tmp/claude",
                        "/private/tmp/claude",
                        iJ.join(A, ".npm/_logs"),
                        iJ.join(A, ".claude/debug"),
                        ".",
                ],
                Q = _L1();
        if (Q) {
                let I = Gy();
                if (Q.originalCwd !== I) B.push(Q.originalCwd);
        }
        return B;
}

I'd like to see sandbox.allowDirectories: [] be added to the settings.

farnoy avatar Oct 30 '25 15:10 farnoy

same issue

maple5233 avatar Nov 10 '25 04:11 maple5233

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

github-actions[bot] avatar Dec 10 '25 10:12 github-actions[bot]

Please fix this. It makes it difficult to use the sandboxing feature on Linux since all cache locations have to be moved from their default locations to avoid having to do things like adding dependencies outside the sandbox. Given problems like the recent attacks via install scripts in NPM, being able to install in a sandbox is a nice feature: it's not perfect, but simple instructions to look for known compromises can help flag issues.

mkw avatar Dec 10 '25 16:12 mkw