[BUG] Sandbox fails on macOS Tahoe (darwin25): zsh 5.9 accesses hw.* sysctls not whitelisted in sandbox profile

Resolved 💬 4 comments Opened Apr 17, 2026 by QuellcodeWanderer Closed Jun 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Enabling sandbox.enabled: true in settings causes all Bash tool calls to fail with Sandbox failed to initialize. on macOS Tahoe (macOS 26, darwin25). The root cause has been identified through sandbox profile analysis: zsh 5.9 (arm64-apple-darwin25) reads hw.* sysctls at startup that are not in Claude Code's seatbelt profile allowlist, causing zsh initialization to fail inside the sandbox.

This is a regression specific to macOS Tahoe — the profile worked on macOS Sequoia (darwin24).

Environment:

  • Claude Code: 2.1.92
  • macOS: 26.4.1 (darwin 25.4.0), Apple Silicon (arm64)
  • Shell: zsh 5.9 (arm64-apple-darwin25.0)
  • sandbox-exec itself works: sandbox-exec -p '(version 1)(allow default)' /bin/echo OK → OK

Note: Issue #26095 reported the same symptom but was closed without root cause analysis.

What Should Happen?

Sandbox works out of the box on macOS Tahoe (darwin25).

Error Messages/Logs

Steps to Reproduce

  1. macOS 26 Tahoe (darwin25), Apple Silicon
  2. Set in ~/.claude/settings.json
{
  "sandbox": { "enabled": true, "failIfUnavailable": false }
}
  1. Run any Bash command via the Claude Code Bash tool
  2. Result: Sandbox failed to initialize.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.92

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

Root cause

The macOS sandbox profile in Claude Code 2.1.92 (Zx4() function) allows only specific sysctl-name entries and the prefix hw.optional.arm. On macOS Tahoe, zsh 5.9 reads additional hw.* sysctls at initialization (e.g. hw.targettype, hw.osenvironment, hw.features.allows_security_research, hw.jetsam_properties_product_type and others) that are denied by the profile's (deny default ...) rule.

Proof via manual sandbox-exec testing:

# FAILS - Claude Code's profile with specific hw.* entries:
sandbox-exec -f claude_profile.sb /bin/zsh -c 'echo test'
# → Exit 1

# WORKS - same profile + (sysctl-name-prefix "hw."):
sandbox-exec -f claude_profile_with_hw_prefix.sb /bin/zsh -c 'echo test'  
# → Exit 0

# WORKS - bash never needed the missing hw.* sysctls:
sandbox-exec -f claude_profile.sb /bin/bash -c 'echo test'
# → Exit 0

The (allow sysctl-read) block in the profile needs to be expanded:

- (sysctl-name-prefix "hw.optional.arm")
+ (sysctl-name-prefix "hw.")

or more conservatively, add the specific names zsh 5.9/darwin25 needs.

Workaround

Force Claude Code to use bash instead of zsh by adding to ~/.claude/settings.json:

{
  "sandbox": {
    "enabled": true,
    "failIfUnavailable": false
  },
  "env": {
    "CLAUDE_CODE_SHELL": "/bin/bash"
  }
}

bash does not access the additional hw.* sysctls and works correctly inside the sandbox.

View original on GitHub ↗

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