Harden Dev Container capabilities and PID bound to match installers - #174
Merged
Merged
Conversation
Apply the installers' --cap-drop=ALL capability set and --pids-limit=4096 to .devcontainer/devcontainer.json via runArgs. Add SYS_CHROOT, which the SSH server Feature's OpenSSH privilege separation needs (chroot to /run/sshd); without it every SSH connection is reset during key exchange. A static consistency check now requires the Dev Container to drop all capabilities, keep the 4096 PID bound, avoid widening flags, and use exactly the installers' capability set plus the documented SYS_CHROOT. 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.
Summary
install.sh,install.ps1anddocker-compose.ymlcreate the Box with--cap-drop=ALLplus a small re-added capability set and--pids-limit=4096..devcontainer/devcontainer.jsonhad neither. This PR adds the same hardening throughrunArgs:runArgsis used because the Dev Containers spec has no PID-limit property and no way to drop capabilities (capAddcan only add).Why the extra
SYS_CHROOTThe digest-locked
sshd:1.1.0Feature runs OpenSSH 10.2, whose privilege separationchroots the pre-auth child into/run/sshd. WithoutSYS_CHROOT,sshd -dlogschroot("/run/sshd"): Operation not permitted [preauth]and every connection is reset during key exchange. No other capability was needed: the Feature listens on port 2222, soNET_BIND_SERVICEisn't required, and logins succeeded withoutAUDIT_WRITE. The reason is recorded in SECURITY.md.Verification
Ran
devcontainer up(CLI 0.87.0) with--docker-path podman(rootless Podman 6.1.1) against a copy of the tree:scripts/devcontainer-postcreate.sh, which installed claude and node) finished withoutcome: successCHOWN DAC_OVERRIDE FOWNER KILL SETGID SETUID SYS_CHROOT, and/sys/fs/cgroup/pids.maxwas4096sudo -n apt-get updateasdevsucceededssh -p 2222 dev@127.0.0.1worked, both without and with a pty (-tt)SYS_CHROOT), the SSH connection failed as described aboveNot verified: rootful Docker (the Docker socket wasn't reachable) and Codespaces.
Tests
tests/test-repository-consistency.shnow checks that the Dev Container:--cap-drop=ALLand--pids-limit=4096--privileged,--cap-add=ALL,--security-opt, and nocapAdd,privilegedorsecurityOptproperties)install.shset (also cross-checked againstinstall.ps1) plusSYS_CHROOTI confirmed the check fails when
SYS_CHROOTor the PID limit is removed. All 19 host tests pass.🤖 Generated with Claude Code