Description
PR #3085 fixed #3077 by replacing per-path (allow file-read* (subpath ...)) rules with a global (allow file-read*) in the Seatbelt workspace profile. This is necessary to load dylibs from the macOS DYLD shared cache, but it also makes credential files readable by sandboxed bash (e.g. cat ~/.ssh/id_rsa would succeed).
The FirewallVerifier at crates/zeph-tools/src/verifier.rs:824-838 partially mitigates this for literal path references in bash commands, but does not catch wildcard/indirect access (tar, find, cp).
The fix is to add deny-first subpath rules for well-known secret paths before the global (allow file-read*) rule. In Seatbelt, the last matching rule wins — so (deny file-read*) placed after the global allow would take precedence.
Expected Behavior
Sandboxed bash should not be able to read files in known credential locations even under the workspace profile.
Affected File
crates/zeph-tools/src/sandbox/macos.rs — generate_sb_profile(), workspace profile branch.
Deny list (minimum)
(deny file-read* (subpath (string-append (param "HOME") "/.ssh")))
(deny file-read* (subpath (string-append (param "HOME") "/.aws")))
(deny file-read* (subpath (string-append (param "HOME") "/.config/gh")))
(deny file-read* (subpath (string-append (param "HOME") "/.config/op")))
(deny file-read* (subpath (string-append (param "HOME") "/.config/gcloud")))
(deny file-read* (subpath (string-append (param "HOME") "/.azure")))
(deny file-read* (subpath (string-append (param "HOME") "/.netrc")))
(deny file-read* (subpath (string-append (param "HOME") "/.docker/config.json")))
(deny file-read* (subpath (string-append (param "HOME") "/.kube/config")))
(deny file-read* (subpath (string-append (param "HOME") "/.gnupg")))
(deny file-read* (subpath (string-append (param "HOME") "/.password-store")))
(deny file-read* (subpath (string-append (param "HOME") "/.cargo/credentials.toml")))
(deny file-read* (subpath (string-append (param "HOME") "/.npmrc")))
(deny file-read* (subpath (string-append (param "HOME") "/.zsh_history")))
(deny file-read* (subpath (string-append (param "HOME") "/.bash_history")))
(deny file-read* (subpath (string-append (param "HOME") "/Library/Keychains")))
(deny file-read* (subpath (string-append (param "HOME") "/Library/Cookies")))
Compensating control (existing)
FirewallVerifier already blocks literal references to ~/.ssh/*, ~/.aws/*, *.pem, id_rsa, credentials etc. at pre-execution. Does not cover indirect access.
Acceptance Criteria
sandbox-exec -f <workspace.sb> /bin/bash -c "cat ~/.ssh/id_rsa" → denied
sandbox-exec -f <workspace.sb> /bin/bash -c "echo hello" → still works
sandbox-exec -f <workspace.sb> /bin/bash -c "ls ~" → still works (home listing OK)
- Deny list documented in
specs/010-security/spec.md
Description
PR #3085 fixed #3077 by replacing per-path
(allow file-read* (subpath ...))rules with a global(allow file-read*)in the Seatbelt workspace profile. This is necessary to load dylibs from the macOS DYLD shared cache, but it also makes credential files readable by sandboxed bash (e.g.cat ~/.ssh/id_rsawould succeed).The FirewallVerifier at
crates/zeph-tools/src/verifier.rs:824-838partially mitigates this for literal path references in bash commands, but does not catch wildcard/indirect access (tar,find,cp).The fix is to add deny-first subpath rules for well-known secret paths before the global
(allow file-read*)rule. In Seatbelt, the last matching rule wins — so(deny file-read*)placed after the global allow would take precedence.Expected Behavior
Sandboxed bash should not be able to read files in known credential locations even under the workspace profile.
Affected File
crates/zeph-tools/src/sandbox/macos.rs—generate_sb_profile(), workspace profile branch.Deny list (minimum)
Compensating control (existing)
FirewallVerifieralready blocks literal references to~/.ssh/*,~/.aws/*,*.pem,id_rsa,credentialsetc. at pre-execution. Does not cover indirect access.Acceptance Criteria
sandbox-exec -f <workspace.sb> /bin/bash -c "cat ~/.ssh/id_rsa"→ deniedsandbox-exec -f <workspace.sb> /bin/bash -c "echo hello"→ still workssandbox-exec -f <workspace.sb> /bin/bash -c "ls ~"→ still works (home listing OK)specs/010-security/spec.md