fix(sandbox): add deny-first Seatbelt rules for well-known secret paths#3103
Merged
fix(sandbox): add deny-first Seatbelt rules for well-known secret paths#3103
Conversation
PR #3085 replaced per-path file-read rules with a global (allow file-read*) to fix dylib loading. This inadvertently allowed sandboxed bash to read credential files. Since Seatbelt applies the last matching rule, adding deny rules after the global allow closes the gap. Changes: - Add SECRET_DIRS (26 entries, subpath) and SECRET_FILES (11 entries, literal) covering SSH, AWS, GCP, Azure, GnuPG, Docker, Kubernetes, git credentials, AI agent caches (.claude, .anthropic, .codex), Zeph age vault (.config/zeph), shell histories, npm/pypi/cargo credentials, HashiCorp vault token, and more - Extract generate_sb_profile_for_home(policy, home) as pure inner function; generate_sb_profile() fails closed (SandboxError::Policy + warn!) when dirs::home_dir() returns None - Apply deny rules to all non-Off profiles (ReadOnly gap fixed) - Add 11 unit tests covering ordering invariant, all profile types, user allow_read override, quote escaping, and 37-rule count assertion - Document mechanism, non-goals, and key invariants in specs/010-security/spec.md - Add CHANGELOG entry under [Unreleased] ### Security Closes #3086
5aa327a to
226f855
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
file-readrules with a global(allow file-read*)to fix dylib loading from the macOS DYLD shared cache. This inadvertently made credential files readable by sandboxed bash.SECRET_DIRS(26 entries,subpath) andSECRET_FILES(11 entries,literal), covering SSH, AWS, GCP, Azure, GnuPG, Docker, Kubernetes, git credentials, AI agent caches (.claude,.anthropic,.codex), Zeph age vault (.config/zeph), shell histories, npm/pypi/cargo credentials, HashiCorp vault token, and more.Changes
crates/zeph-tools/src/sandbox/macos.rs:SECRET_DIRS/SECRET_FILESconsts,push_secret_deny_rules_for_home(), refactoredgenerate_sb_profile_for_home()inner function, fail-closed onhome_dir() == None, deny rules applied to all non-Off profiles, 11 new unit testsspecs/010-security/spec.md: new "Deny-First Secret Paths (sandbox/macos: add deny-first rules for well-known secret paths #3086)" subsection with mechanism, path table, non-goals, key invariantsCHANGELOG.md: entry under[Unreleased] ### SecurityTest plan
cargo nextest run -p zeph-tools --lib— 1029 tests passtest_deny_ordering— deny rules appear after(allow file-read*)in generated profiletest_readonly_has_deny_rules/test_network_allow_all_has_deny_rules— all non-Off profiles coveredhome_path_with_quotes_is_escaped— Seatbelt injection via hostile HOME path preventedall_37_deny_rules_emitted— full deny list count verifiedsandbox-exec -f <workspace.sb> /bin/bash -c "cat ~/.ssh/id_rsa"→ deniedsandbox-exec -f <workspace.sb> /bin/bash -c "echo hello"→ succeedsFollow-up
Security audit identified additional long-tail paths (browser profiles, IaC tokens, cloud CLIs) deferred to a separate issue.
Closes #3086