(version 1) ;; Based on Para Sandboxing Profile - Standard - https://github.com/2mawi2/para/blob/218259b6e260be43334f308a74108f31920f7ca4/src/core/sandbox/profiles/standard.sb ;; Forbids reading HOME_DIR except for cwd (TARGET_DIR) ;; Forbids writing other than to cwd (TARGET_DIR) ;; All network is allowed ;; Deny everything by default (deny default) ;; Allow network access (required for Claude API) (allow network*) ;; Deny reading files anywhere on host (allow rules override this below) (deny file-read*) (deny file-read* (subpath "/") (subpath "/Users") (subpath (param "HOME_DIR")) (subpath (string-append (param "HOME_DIR") "/.ssh")) ) ;; allow directories required to launch claude-code (allow file-read* (subpath "/usr") (subpath "/bin") (subpath "/opt") (subpath "/var") (subpath "/private/var") (subpath "/etc") (subpath "/private/etc") (subpath "/System") (subpath "/nix") ) ;; necessary for nix-darwin's `/run/current-system/sw/bin` (allow file-read-metadata (subpath "/run")) ;; === IMPORTANT === MODIFY this section to include ALL directories leading to claude workdir === ;; for some reason claude-code needs list access to all parent directories of TARGET_DIR ;; - it doesn't need access to read the contents of directories, only the directories ;; themselves. Otherwise it will set PATH to "" and disable colored output (allow file-read* (literal "/") ) (allow file-read* ;; Git configuration (for commits) (subpath (string-append (param "HOME_DIR") "/.config/git")) (subpath (string-append (param "HOME_DIR") "/.config/jj")) (literal (string-append (param "HOME_DIR") "/.gitconfig")) ;; Nix configuration (subpath (string-append (param "HOME_DIR") "/.config/nix")) (subpath (string-append (param "HOME_DIR") "/.local/share/nix")) ;; Nix profile binaries (symlinks to /nix/store) (subpath (string-append (param "HOME_DIR") "/.nix-profile")) (subpath (string-append (param "HOME_DIR") "/.local/state/nix")) ;; gh CLI (subpath (string-append (param "HOME_DIR") "/.config/gh")) ) ;; Allow process execution and forking (children inherit policy) (allow process-exec) (allow process-fork) ;; Essential permissions - based on Chrome sandbox policy ;; Process permissions - from https://github.com/anthropic-experimental/sandbox-runtime/blob/1bafa66a2c3ebc52569fc0c1a868e85e778f66a0/src/sandbox/macos-sandbox-utils.ts#L200 (allow process-info* (target same-sandbox)) ;; Allow signals to all children (allow signal (target same-sandbox)) (allow mach-priv-task-port (target same-sandbox)) ;; User preferences - from https://github.com/anthropic-experimental/sandbox-runtime/blob/1bafa66a2c3ebc52569fc0c1a868e85e778f66a0/src/sandbox/macos-sandbox-utils.ts#L200 ;; (allow user-preference-read) ;; doesn't seem to be required by claude-code ;; Allow read access to system information ;; From Chromium's sandbox policy for macOS (allow sysctl-read (sysctl-name "hw.activecpu") (sysctl-name "hw.busfrequency_compat") (sysctl-name "hw.byteorder") (sysctl-name "hw.cacheconfig") (sysctl-name "hw.cachelinesize_compat") (sysctl-name "hw.cpufamily") (sysctl-name "hw.cpufrequency_compat") (sysctl-name "hw.cputype") (sysctl-name "hw.l1dcachesize_compat") (sysctl-name "hw.l1icachesize_compat") (sysctl-name "hw.l2cachesize_compat") (sysctl-name "hw.l3cachesize_compat") (sysctl-name "hw.logicalcpu_max") (sysctl-name "hw.machine") (sysctl-name "hw.memsize") (sysctl-name "hw.ncpu") ;; Needed for Lix (sysctl-name "hw.pagesize") (sysctl-name "hw.pagesize_compat") (sysctl-name "hw.physicalcpu_max") (sysctl-name "hw.tbfrequency_compat") (sysctl-name "kern.hostname") (sysctl-name "kern.maxfilesperproc") (sysctl-name "kern.osproductversion") (sysctl-name "kern.osrelease") (sysctl-name "kern.ostype") (sysctl-name "kern.osversion") (sysctl-name "kern.secure_kernel") (sysctl-name "kern.version") ) ;; Allow file writes to specific paths only ;; Note: file-write* does NOT include file-write-create, so we need both (allow file-read* file-write* file-write-create file-read-metadata file-ioctl ;; Project directory - primary workspace (subpath (param "TARGET_DIR")) ;; Include .git and .jj directories in case the root is above TARGET_DIR. (subpath (param "GIT_DIR")) (subpath (param "JJ_DIR")) ;; Temporary directories (subpath (param "TMP_DIR")) (subpath "/tmp") (subpath "/private/tmp") (subpath "/var/folders") ; macOS temp directory root (subpath "/private/var/folders") ; Real path (var is symlink to private/var) ;; below is from `para`'s' sandbox.sb, but these rules don't work because sandbox-exec uses GLOB 'regexes' ;; (regex #"^/var/folders/[^/]+/[^/]+/[^/]+/.*") ; macOS temp dirs and subdirs ;; (regex #"^/private/var/folders/[^/]+/[^/]+/[^/]+/.*") ; Real path version ;; (regex #"^/var/folders/.*") ; Allow all subdirectories under /var/folders for broader compatibility ;; (regex #"^/private/var/folders/.*") ; Real path version ;; Cache directory (subpath (param "CACHE_DIR")) (subpath (string-append (param "HOME_DIR") "/.cache")) ;; Claude configuration (subpath (string-append (param "HOME_DIR") "/.claude")) (literal (string-append (param "HOME_DIR") "/.claude.json")) (literal (string-append (param "HOME_DIR") "/.claude.json.backup")) (subpath (string-append (param "HOME_DIR") "/Library/Caches/claude-cli-nodejs")) ;; Gemini configuration (subpath (string-append (param "HOME_DIR") "/.gemini")) ;; Standard I/O devices (literal "/dev/stdout") (literal "/dev/stderr") (literal "/dev/null") (literal "/dev/zero") (literal "/dev/tty") (literal "/dev/ptmx") (literal "/dev/urandom") (literal "/dev/random") (regex #"^/dev/tty*") (regex #"^/dev/pty*") ) ;; File I/O on device files - sandbox-runtime - https://github.com/anthropic-experimental/sandbox-runtime/blob/1bafa66a2c3ebc52569fc0c1a868e85e778f66a0/src/sandbox/macos-sandbox-utils.ts#L200 (allow file-ioctl file-read-metadata file-read-data file-write-data (literal "/dev/dtracehelper")) (allow file-ioctl file-read-metadata file-read-data file-write-data (require-all (literal "/dev/null") (vnode-type CHARACTER-DEVICE) ) ) ;; Gemini-specific permissions (allow pseudo-tty) ;; Allow mach lookups for essential services (allow mach-lookup (global-name "com.apple.sysmond") ; For process listing (global-name "com.apple.FSEvents") ; For Node.js file watching (global-name "com.apple.SystemConfiguration.DNSConfiguration") ; For DNS resolution in Lix ) ;; Allow file attribute operations needed for file creation ;; (allow file-write-setugid) ;; (allow file-write-mode) ;; (allow file-write-owner) ;; (allow file-write-times) ;; (allow file-write-flags) (allow mach-lookup (global-name "com.apple.audio.systemsoundserver") (global-name "com.apple.distributed_notifications@Uv3") (global-name "com.apple.FontObjectsServer") (global-name "com.apple.fonts") (global-name "com.apple.logd") (global-name "com.apple.lsd.mapdb") (global-name "com.apple.PowerManagement.control") (global-name "com.apple.system.logger") (global-name "com.apple.system.notification_center") (global-name "com.apple.trustd.agent") (global-name "com.apple.system.opendirectoryd.libinfo") (global-name "com.apple.system.opendirectoryd.membership") (global-name "com.apple.bsd.dirhelper") (global-name "com.apple.securityd.xpc") (global-name "com.apple.coreservices.launchservicesd") ) ;; The following is required to get Claude API Key from macOS Keychain (if logged in via /login) ;; Specifically allow login keychain (allow file-read* (literal (string-append (param "HOME_DIR") "/Library/Keychains/login.keychain-db")) ) ;; Critical: Allow communication with securityd (keychain daemon) (allow mach-lookup (global-name "com.apple.SecurityServer") (global-name "com.apple.securityd") (global-name "com.apple.securityd.xpc") ) ;; Java/Scala development permissions ;; Java-specific services (allow mach-lookup (global-name "com.apple.diagnosticd") (global-name "com.apple.SystemConfiguration.configd") ) ;; Java-specific sysctl reads (allow sysctl-read (sysctl-name "security.mac.lockdown_mode_state") (sysctl-name "kern.bootargs") (sysctl-name "kern.osvariant_status") (sysctl-name "kern.argmax") (sysctl-name "hw.ephemeral_storage") (sysctl-name "hw.optional.armv8_crc32") (sysctl-name "hw.optional.arm.FEAT_LSE") (sysctl-name "hw.optional.armv8_1_atomics") (sysctl-name "hw.optional.arm.FEAT_SHA512") (sysctl-name "hw.optional.armv8_2_sha512") (sysctl-name "hw.optional.arm.FEAT_SHA3") (sysctl-name "hw.optional.armv8_2_sha3") (sysctl-name "net.routetable.0.0.3.0") ) ;; Java needs to read dtracehelper (allow file-read-data (literal "/dev/dtracehelper")) ;: ;; Java needs IPC shared memory for notification center ;; (allow ipc-posix-shm-read-data ;; (ipc-posix-name "apple.shm.notification_center") ;; ) ;; Java needs system sockets (domain:32 is AF_NDRV for network device raw access) (allow system-socket) ;; Java needs to read metadata on certain directories (allow file-read-metadata (literal "/dev") (literal "/private") (literal "/Library") (literal (string-append (param "HOME_DIR") "/Library")) (literal (string-append (param "HOME_DIR") "/Library/Caches")) ) (allow file-read-data (literal "/dev") ) ;; Java needs to read various preference files (allow file-read* (literal "/Library/Preferences/Logging/com.apple.diagnosticd.filter.plist") (literal "/Library/Preferences/.GlobalPreferences.plist") (literal "/Library/Preferences/com.apple.networkd.plist") (literal (string-append (param "HOME_DIR") "/Library/Preferences/.GlobalPreferences.plist")) (literal (string-append (param "HOME_DIR") "/Library/Preferences/.GlobalPreferences_m.plist")) (regex (string-append "^" (param "HOME_DIR") "/Library/Preferences/ByHost/\\.GlobalPreferences\\..*\\.plist$")) ) ;; read/write ~/.sbt, coursier and bloop caches (allow file-read* file-write* (subpath (string-append (param "HOME_DIR") "/.sbt")) (subpath (string-append (param "HOME_DIR") "/.ivy2")) (subpath (string-append (param "HOME_DIR") "/.m2")) (subpath (string-append (param "HOME_DIR") "/.jgit")) (subpath (string-append (param "HOME_DIR") "/.config/jgit")) (subpath (string-append (param "HOME_DIR") "/Library/Caches/Coursier")) (subpath (string-append (param "HOME_DIR") "/Library/Caches/ScalaCli")) ) ;; read [~]/Library/Java (allow file-read* (subpath (string-append (param "HOME_DIR") "/Library/Java")) (subpath "/Library/Java") ) ;; Xcode Command Line Tools - needed so /usr/bin/git (an xcode-select shim) ;; can locate the real git binary (allow file-read* (subpath "/Library/Developer/CommandLineTools") ) ;; Generated allow-read rules for: /Users/joe/src ;; for some reason claude-code needs list access to all parent directories of TARGET_DIR ;; - it doesn't need access to read the contents of directories, only the directories ;; themselves. Otherwise it will set PATH to "" and disable colored output (allow file-read* (literal "/Users")) (allow file-read* (literal "/Users/joe")) (allow file-read* (subpath "/Users/joe/src")) (allow file-read* (subpath (string-append (param "HOME_DIR") "/.dotfiles"))) (deny file-read* (subpath (string-append (param "HOME_DIR") "/.dotfiles/tmp")))