feat(agent): per-connection ssh cache contexts, per-app no-fallback, pwd-scoped cache keys#3
Merged
Merged
Conversation
…pwd-scoped cache keys Three auth-cache context fixes: 1. Forwarded-agent narrowing: when the socket peer is the OpenSSH client, every cache mode (incl. global) anchors the context on that ssh process (pid, start_tvsec) instead of the terminal session / app ancestor / shared global slot. A remote host over `ssh -A` can reuse its own approvals within the TTL but can no longer ride grants from local tabs or other remote hosts; the context dies with the connection. The per-session/per-app TTY gate runs before the ssh branch so a TTY-less binary renamed `ssh` cannot bypass it. 2. per-app: find_app_pid returns Option; no .app ancestor (tmux panes, ssh logins) now means uncacheable instead of keying on the short-lived peer pid, which could never hit again but inserted a dead entry per call. 3. Cache keys fold in the client-reported pwd as an advisory narrower (mirrors the Worker DEK cache): decrypt key = SHA256(type‖salt‖host‖pwd) (domain tag bumped to v2), sign cache now keys on SHA256(fp‖pwd). Plain agent-protocol signs carry no ClientMeta and key on empty pwd (unchanged behavior); global-mode grants are now scoped per project tree. Known tradeoff: repeated one-shot `ssh host` invocations no longer share a sign grant within the TTL (same peer process for self-auth and forwarding — indistinguishable); ControlMaster-multiplexed connections still share one.
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
Three auth-cache context fixes for
vt ssh agent(design reviewed with codex-expert before and after implementation):ssh), every cache mode (incl.global) anchors the context on that ssh process(pid, start_tvsec)instead of the terminal session / app ancestor / shared global slot. A remote host overssh -Acan reuse its own approvals within the TTL, but can no longer ride grants issued by other local tabs or other remote hosts; the context dies with the connection. The per-session/per-app TTY gate runs before the ssh branch, so a TTY-less binary renamedsshcannot bypass it.find_app_pidreturnsOption; no.app/Contents/ancestor (tmux panes, ssh logins) now means uncacheable instead of keying on the short-lived peer pid, which could never hit again but inserted a dead cache entry per call.pwdinto the key as an advisory narrower, mirroring the Worker DEK cache design: decrypt key =SHA256(type‖salt‖host‖pwd)(domain tag bumped to v2), sign cache keys onSHA256(fingerprint‖pwd). Plain agent-protocol signs carry no ClientMeta → empty pwd, behavior unchanged;global-mode grants are now scoped to one project tree.Known tradeoff
Repeated one-shot
ssh hostinvocations no longer share a sign grant within the TTL — the agent cannot distinguish ssh authenticating itself from ssh relaying a forwarded request (same peer process). ControlMaster-multiplexed connections still share one context (one long-lived master process). Documented in CLAUDE.md.Test plan
cargo test(226 passed; new unit tests foris_ssh_client_path,sign_cache_key, pwd partition + field-shift boundaries)cargo check --target x86_64-unknown-linux-gnu(via zigbuild; agent module is macOS-gated)🤖 Generated with Claude Code