Replies: 7 comments 1 reply
|
hi @nf-matt , thanks for the kind words! we are going to introduce overrides , I will see if I can expedite this in for the next release |
|
It looks like I managed to work around the issue. Specifically I needed a way to give SSH access for git and gh. My failed attempts: ❌ Try to override My success: ✅ Create a new With a little digging, I read that seatbelt operates at the kernel level, and doesn't care about symlinks. It looks at the final object, and will for sure block what nono considers to be off-limits. That's probably a good thing because it would make it harder to create a backdoor path to a file that should be protected. What worked specifically for git and gh after copying the key/pub to SEATBELT_DIR="${HOME}/.seatbelt"
GH_KEY="${SEATBELT_DIR}/.ssh/id_ed25519_github"
GH_PUB="${SEATBELT_DIR}/.ssh/id_ed25519_github.pub"
GH_CONFIG="${HOME}/.config/gh"
GIT_SSH_COMMAND="ssh \
-l git \
-o IdentityFile=${GH_KEY} \
-o StrictHostKeyChecking=accept-new \
-o UserKnownHostsFile=${SEATBELT_DIR}/.ssh/known_hosts \
-o GlobalKnownHostsFile=/dev/null"
nono run --profile claude-code \
# other args
--read "${SEATBELT_DIR}" \
--allow-file "${SEATBELT_DIR}/.ssh/known_hosts" \
--read-file "${GH_KEY}" \
--read-file "${GH_PUB}" \
--read "${GH_CONFIG}" \
-- env GIT_SSH_COMMAND="${GIT_SSH_COMMAND}" claude "$@"Thanks again, great tool! EDIT: known_hosts failed to update at first, but the git worked anyway. I did |
|
Not sure if that's going to be similar on Mac, but I guess when using a ssh agent one just needs to allow access to it's socket and maybe the known hosts file: |
The primary blocker: ProxyOnly mode activates (deny network*)The claude-code profile sets "network_profile": "developer". In NetworkConfig::has_proxy_flags() (profile/mod.rs:452), any non-None network_profile returns true, triggering ProxyOnly mode. In macos.rs:generate_profile (macos.rs:452-465), ProxyOnly mode emits: The (deny network*) rule in Seatbelt covers all address families — including AF_UNIX. Connecting to a Unix domain socket goes through network-outbound, which is denied here. So both Why
A potential inconsistency in the profile generationThere's an unconditional (allow system-socket) emitted at macos.rs:348 — before the network rules. In ProxyOnly mode, the narrower AF_INET/AF_INET6 rules added later are intended to scope it down. But since the earlier broad (allow system-socket) already matches all socket types, and Seatbelt's rule ordering is last-match-wins for equal specificity, the broad allow at the top may actually preempt the intended TCP-only scoping. That's potentially a bug in the ProxyOnly path — but it only matters for socket creation, not for connect(). The (deny network*) still prevents the actual connection. Summary
If you want SSH agent and cmux socket access to work, you'd need to avoid ProxyOnly mode (remove network_profile from the profile or override it), or the sandbox would need an explicit Seatbelt rule like (allow network-outbound (local unix-socket)) — which the current profile generator doesn't produce. Option 2 — Proper approach: This would be ~4 files touched:
This way --allow-socket "${SSH_AUTH_SOCK}" would:
Option 2 is the right design — it's opt-in and keeps the ProxyOnly security intent intact. |
|
I had claude create a new Save it to {
"meta": {
"name": "claude-code-local",
"version": "1.0.0",
"description": "claude-code without proxy filtering, for local socket access"
},
"security": {
"groups": [
"deny_credentials",
"deny_keychains_macos",
"deny_keychains_linux",
"deny_browser_data_macos",
"deny_browser_data_linux",
"deny_macos_private",
"deny_shell_history",
"deny_shell_configs",
"system_read_macos",
"system_read_linux",
"system_write_macos",
"system_write_linux",
"user_tools",
"homebrew",
"dangerous_commands",
"dangerous_commands_macos",
"dangerous_commands_linux",
"user_caches_macos",
"node_runtime",
"rust_runtime",
"python_runtime",
"vscode",
"unlink_protection"
]
},
"filesystem": {
"allow": [
"$HOME/.claude"
],
"read": [
"$HOME/.local/share/claude"
],
"allow_file": [
"$HOME/.claude.json",
"$HOME/.claude.json.lock"
],
"read_file": [
"$HOME/Library/Keychains/login.keychain-db",
"$HOME/.gitconfig",
"$HOME/.gitignore_global",
"$HOME/.config/git/ignore"
]
},
"network": {
"block": false
},
"workdir": {
"access": "readwrite"
},
"hooks": {
"claude-code": {
"event": "PostToolUseFailure",
"matcher": "Read|Write|Edit|Bash",
"script": "nono-hook.sh"
}
},
"undo": {
"exclude_patterns": [
"node_modules",
".next",
"__pycache__",
"target"
],
"exclude_globs": [
"*.tmp.[0-9]*.[0-9]*"
]
},
"interactive": true
} |
|
Hi. I'm stumbling upon issues like these, and I was wondering if we could have some official guidance/documentation on best practices related to git/ssh operations? I'm a bit tired of banging my head against Claude trying to hallucinate what's the best way to wrangle the config file to do what we want, so some guidance on best practices would be nice (I'm also hitting issues like #1695 on macOS). Ideally this should cover simple cases from keys with empty passphrase that don't require a ssh-agent, to more complex scenarios. |
|
@jdumas there is some good examples of tool sandboxing contributed by the datadog folks, does this help: https://github.com/nolabs-ai/nono/tree/main/tool-sandbox-examples/git-ssh |
Uh oh!
There was an error while loading. Please reload this page.
Hi, awesome project, and you're off to a great start! This has the potential to be a lot better than other sandboxing tools.
I am stuck trying to do one common thing. I have been unable to make
gitremotes work, either with SSH (preferred) or HTTPS. HTTPS adds credentials access "fun". SSH is what I would prefer to do, but no matter what I can't make the necessary files accessible.I tried every way I could think of (
--allow/--readcombinations of files and directories) to override the block on keys or sensitive files, which obviously it needs. Any suggestions?All reactions