sandbox.filesystem.denyRead not enforced on bundled rg subprocess

Resolved 💬 2 comments Opened Apr 6, 2026 by ankitvgupta Closed May 18, 2026

Summary

sandbox.filesystem.denyRead paths passed to query() are not enforced on the bundled rg (ripgrep) subprocess. When the SDK spawns rg for Grep/search tool calls, it doesn't translate denyRead paths into --glob exclusions or equivalent, so rg freely traverses into directories that should be blocked.

Context

We're building an Electron app that uses the Claude Agent SDK. On macOS, accessing certain user directories (~/Music, ~/Library, ~/Downloads, /Volumes, etc.) triggers TCC permission prompts attributed to our app. We pass denyRead to prevent the agent from accessing these directories:

const q = query({
  prompt,
  options: {
    sandbox: {
      filesystem: {
        denyRead: [
          `${process.env.HOME}/Music`,
          `${process.env.HOME}/Pictures`,
          `${process.env.HOME}/Movies`,
          `${process.env.HOME}/Library`,
          "/Volumes",
        ],
        allowRead: [
          `${process.env.HOME}/Library/Application Support/exo`,
        ],
      },
    },
    // ...
  },
});

Reproduction

  1. Pass sandbox.filesystem.denyRead with ~/Music (absolute path) to query()
  2. Ask the agent "list the files in my home directory"
  3. The agent runs ls ~ via Bash (correct, no TCC prompt) but the SDK also spawns rg searching from $HOME
  4. rg recursively traverses into ~/Music, ~/Library, /Volumes, etc., triggering macOS TCC permission prompts for Apple Music, Downloads, and Network Volumes

Evidence from macOS TCC logs

AUTHREQ_PROMPTING: service=kTCCServiceMediaLibrary
  accessing={identifier=rg, binary_path=.../app.asar.unpacked/node_modules/@anthropic-ai/claude-agent-sdk/vendor/ripgrep/arm64-darwin/rg}
  responsible={identifier=com.exo, binary_path=.../Exo.app/Contents/MacOS/Exo}

All three TCC prompts (MediaLibrary, Downloads, NetworkVolumes) come from the same rg process doing a broad search from $HOME.

Expected behavior

denyRead paths should be translated into --glob exclusions (e.g., --glob '!Music/**') when spawning rg, so the subprocess respects the same filesystem restrictions as the tool-call layer.

Environment

  • Claude Agent SDK: @anthropic-ai/claude-agent-sdk (latest as of April 2026)
  • Electron 39.8.6
  • macOS 24.6.0 (Sequoia)

View original on GitHub ↗

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