Repository navigation
identity.ssh: sandbox ssh never laxer than host ssh for unpinned hosts (fixes #697) - #702
Merged
Merged
Conversation
fixes #697) The system-wide ssh_config replacement is written whenever the sandbox's own ssh (the first ssh on the sandbox PATH) is inside, not only where a bind supplies the host's file. On a host whose system file is under /etc/ssh, which @sys does not grant, the sandbox's ssh ran on OpenSSH's compiled-in defaults. - The probe asks the sandbox's ssh. When the host PATH ssh is a different file, snug re-probes with the sandbox's binary (global and pin) and resolves once more. It refuses when that binary is writable by this run, because the probe runs it on the host. - First-pass probe refusals are held until the sandbox's ssh is known. - The host's global RevokedHostKeys is staged at /snug/revoked_host_keys and named in the generated file. A profile mount there is refused whatever the host's config says. - On a tmpfs, only the top-level config is written (-vvv "Including file" lines identify the included ones). - Per-Host and Match blocks for unpinned hosts are not carried. This is the maintainer's choice, and --dry-run and the generated file say so, including that a negated pattern (Host * !x) applies to x inside. - --dry-run says REPLACED or WRITTEN per path, names the sandbox's ssh and the KRL's host file, and states when nothing was written. The integration suite's ssh wrapper is now the sandbox's ssh in every selection, and adds the suite known_hosts only for snug's host-side probe. No pinned test reads the account's real known_hosts. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
OpenSSH on the ubuntu-latest runner omits the revokedhostkeys line when none is set; OpenSSH 10.6 prints "none". TestTheSandboxsSSHIsProbedNotTheHostPATHs refused its own fixture on CI with revokedhostkeys "". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.
Fixes #697. Book changes not in this PR; facts listed on #700.
Change
sshon sandbox PATH, viaPolicy.SandboxBinary) is inside, not only where bind supplies host file. Debian/Fedora shape:/etc/ssh/ssh_configwritten on root tmpfs (system-ssh-etc.bwrap.txtgolden). Bind arm unchanged: bound existing host file always replaced (main's rule).ssh -G -vvv, pin probe too) with sandbox binary, re-resolve once, refuse if binary changes again.Policy.SandboxWritesHost): re-probe runs it on host.heldSSHErrs).RevokedHostKeysread (hostread.Required, relative path refuses), staged/snug/revoked_host_keys, named in generated file. Host path never written into file./snugrefused regardless of host KRL (Policy.Replaceno longer displaces it;refusals.txtgolden:/snug/enginewording).-vvvIncluding filelines mark includes).--dry-run, incl. negated pattern (Host * !x,Match !host x) matching probe name and so applying to x inside.--dry-runSSH block: REPLACED vs WRITTEN per path (Policy.SystemSSHReplaced), sandbox ssh row, KRL host path, "no system-wide ssh_config written" row.Tests
symlinkgrant into rw), held pin refusal yields to sandbox ssh, relative KRL refusal on re-probe, top-level-only on tmpfs, REPLACED/WRITTEN over profile tmpfs,/snug/revoked_host_keysmounts refused with/without KRL, dry-run rows. Each negative-controlled.test/integration/sshunpinned_test.go: unpinned KRL applied inside, Host block not carried (residual held), negated block applies to excluded host, sandbox ssh probed not host PATH's, pin asked of sandbox ssh, unpinned revoked key refused.suite-sshprofile); adds suite known_hosts only whenSNUG_SUITE_KNOWN_HOSTSset (probe inherits host env, sandbox env empty). Audit: github.com removed from suite known_hosts, everyidentity.sshtest failed, so none reads real known_hosts. Right-target testTestTheSuitesSSHIsTheSandboxsAndPlainInside.Runs (openSUSE, OpenSSH_10.6p1)
make gaterc=0.SNUG_REQUIRE_SANDBOX=1 make integrationrc=0; 61 SKIP, engine tests (host podman prints no version), same set as origin/main.make verify5 passed, 4 skipped, 0 failed./etc/sshshape not measured on real host: golden + unit only; ubuntu CI exercises it.Red team
3 rounds before PR.
Bad owner or permissions on /usr/etc/ssh/ssh_config.d/50-suse.conf), F4 pinned clause wording. Fixed.requiredrsasize 1024,revokedhostkeys none; host 3072 + KRL; dry-run claimed WRITTEN) (medium), F6 node per Include'd ssh_config, F7 REPLACED inferred from provenance, F8/snugrefusal host-dependent. Fixed.Residual
robind same file); disclosed on--dry-run.🤖 Generated with Claude Code