Skip to content

feat: forward the host SSH agent into the sandbox ([container] ssh) - #63

Open
TakiTake wants to merge 1 commit into
feat/herdr-socket-bridgefrom
feat/container-ssh
Open

feat: forward the host SSH agent into the sandbox ([container] ssh)#63
TakiTake wants to merge 1 commit into
feat/herdr-socket-bridgefrom
feat/container-ssh

Conversation

@TakiTake

Copy link
Copy Markdown
Owner

Closes #54. Stacked on #62 (feat/herdr-socket-bridge) — GitHub retargets this to main once that merges. Only the last commit belongs to this PR.

Why

The default image bakes GitHub's SSH host keys so git-over-SSH works without a TOFU prompt (.pall8t/Containerfile), but nothing forwarded an agent — so the only way to actually authenticate was a private key inside ~/.pall8t/home/.ssh: readable by the sandboxed agent, and still there after the run. docs/design/DESIGN.md:220,230 already called for --ssh as a per-project opt-in.

container run --ssh takes SSH_AUTH_SOCK from the client's environment, forwards that socket into the guest at /var/host-services/ssh-auth.sock (UnixSocketConfiguration(direction: .into)), and sets the container's own SSH_AUTH_SOCK to it. No key material crosses the boundary — only signing requests.

What

  • [container] ssh in global and project config (project wins), default false.
  • pall8t run --ssh / --ssh=false for one run — the same precedence as --readonly (flag beats config beats default), as a pure config::ssh_enabled.
  • Off by default on purpose: while the run lasts, code in the sandbox can authenticate as you anywhere your keys are trusted. That is a capability the sandbox otherwise lacks — even though it is safer than the key-in-the-home alternative it replaces.
  • A warning when forwarding is on and the host has no SSH_AUTH_SOCK (config::ssh_warning): verified on 1.2.2, the runtime logs that to its own log, forwards nothing, and still sets SSH_AUTH_SOCK inside the container — so without the warning the only symptom is ssh failing to connect to a socket that was never there.
  • Skeletons, README (a new "SSH agent forwarding" section), CHANGELOG.

Verification

Unit: 112 tests, scripts/lint.sh clean. cargo mutants -f src/config.rs: nothing missed in the new code (the 4 misses are pre-existing as_str/path helpers).

Live, on container 1.2.2, with an alpine test image running as dev (uid 501):

case result
ssh = true guest SSH_AUTH_SOCK=/var/host-services/ssh-auth.sock; ssh-add -l → "The agent has no identities" (exit 1 — a protocol answer from the host agent, not a connect failure)
ssh = true + --ssh=false SSH_AUTH_SOCK unset inside
ssh = false SSH_AUTH_SOCK unset inside
ssh = false + --ssh forwarded
--ssh with no host agent warning printed; guest still has the (dangling) SSH_AUTH_SOCK, exactly as the warning says

🤖 Generated with Claude Code

https://claude.ai/code/session_01YTFLvjR7dWvxFQfSyBY4Zm

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 76ea6112-bd7f-40fa-8488-c6f5680b037f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The default image bakes GitHub's SSH host keys so git-over-SSH works
without a TOFU prompt, but nothing forwarded an agent — so the only way
to authenticate was a private key sitting in ~/.pall8t/home/.ssh, where
the sandboxed agent can read it and where it stays after the run.

apple/container forwards the agent socket instead: `--ssh` takes
SSH_AUTH_SOCK from the client's environment, mounts that socket into the
guest at /var/host-services/ssh-auth.sock, and points the container's own
SSH_AUTH_SOCK at it. No key material crosses the boundary, only signing
requests. DESIGN.md already had this as the intended v3.2 shape.

- `[container] ssh` (global + project, project wins), default false, plus
  `pall8t run --ssh` / `--ssh=false` for one run — same precedence as
  `--readonly`. Off by default because while the run lasts, code in the
  sandbox can authenticate as the user anywhere their keys are trusted.
- Warn when forwarding is on and the host has no SSH_AUTH_SOCK: the
  runtime forwards nothing but still sets SSH_AUTH_SOCK inside the
  container, so the only other symptom is a connect failure.

Verified live on container 1.2.2: `ssh-add -l` inside the sandbox reaches
the host agent (protocol answer, not a connection failure); `--ssh=false`
and config-off leave SSH_AUTH_SOCK unset inside; `--ssh` overrides a
config that had it off; and the no-agent warning fires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YTFLvjR7dWvxFQfSyBY4Zm
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant