Repository navigation
feat(runner): start the sandbox on stock Ubuntu, or refuse with the AppArmor profile - #435
Merged
Merged
Conversation
Quest-Claim: c5af58d780e8131e
On Ubuntu 23.10 and later, AppArmor keeps unprivileged user namespaces to programs whose profile grants them, and Ubuntu's bwrap profile covers only /usr/bin/bwrap, so the runner's Nix-pinned bwrap failed every job when run from a normal login shell. Before taking jobs, the runner now runs a trivial command in the sandbox's namespaces and refuses with the AppArmor profile to install, for that exact store path, if it fails. The profile copies Ubuntu's bwrap-userns-restrict: bubblewrap gets namespaces while the commands it runs keep no capabilities. The README documents it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…profile Claude Code's seccomp helper makes a nested user namespace inside the sandbox for the capabilities it needs, so a profile copying Ubuntu's bwrap-userns-restrict, which strips capabilities from bwrap's children, passed the startup probe but broke every command. The profile is now the unconfined userns form Ubuntu gives other self-sandboxing programs, the probe nests a second bwrap so it catches the stripped case, and a system bwrap gets no profile, since a second one for /usr/bin/bwrap disables Ubuntu's own and leaves neither attached. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as ready for review
November 3, 2026 04:06
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 51 minutes. View limit details
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. CodeRabbit Verify
|
This was referenced Nov 3, 2026
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.
Finishes Ubuntu AppArmor: a runner started from an ordinary terminal on Ubuntu 23.10+ now either sandboxes jobs or refuses to start, printing the profile that fixes it.
Summary
src/runner/sandbox.tssandboxRefusal, called fromrunnerAdaptersthe first time an account needs an adapter on Linux): runstruein the namespaces Claude Code's sandbox and sandbox-runtime use (--unshare-user --unshare-pid --unshare-net --proc /proc …), nested inside a second bwrap. The nesting matters because Claude Code's seccomp helper makes its own nested user namespace inside the sandbox./proc/sys/kernel/apparmor_restrict_unprivileged_usernsis1and bwrap is in the Nix store (the runner package's), the error prints a ready-to-runsudo tee /etc/apparmor.d/quest-bwrap … && sudo apparmor_parser -r …with the profile filled in for that exact store path. For a system bwrap, it points to the runner package instead. Without the AppArmor restriction, it says unprivileged user namespaces are needed.profile quest-bwrap <store path> flags=(unconfined) { userns, }, the form Ubuntu ships for other self-sandboxing programs (and the Claude desktop profile that made moq-dev/quest#212 work).bwrapProfile.Verification
On this host, stock Ubuntu 26.04.1 with
kernel.apparmor_restrict_unprivileged_userns = 1. Every run was from an unconfined process started withsystemd-run --user, which has the same AppArmor label (unconfined) as a normal login shell. The profiles were loaded only for the test, withapparmor_parser -rfrom the checkout's.tmp/, and unloaded afterwards.apply-seccomploopback: Failed RTM_NEWADDR, prints profileNo permissions to create a new namespaceapply-seccomp: … nested userns is capability-restrictedunshare -Urinside the job refusedapply-seccomp),unshare -Urinside the job is still refused, because bwrap's--disable-usernsapplies (No space left on device).apparmor_parser4.0.1 (-Q -K, in anubuntu:24.04container). I couldn't check 23.10: it is end-of-life and its apt repositories are gone.just checkandjust testpass.quest runnertaking a Claude Code job end to end, which needs a kix login. Claude Code 2.1.305 embeds the sameapply-seccomp(its binary contains the helper's messages), and the probe reproduces that helper's requirement.Choices made without asking
/nix/store/*-bubblewrap-*/bin/bwrap, anyone able to build with Nix could add a matching store path and get around Ubuntu's restriction. The cost: a runner update that changes bubblewrap refuses to start until the newly printed profile is installed. The alternative is a glob for convenience.usernsprofile, not Ubuntu's capability-strippingbwrap-userns-restrictdesign. The stripping version breaks Claude Code's seccomp helper (see the table), and the helper can't be granted capabilities alone, because Claude Code extracts it from its own binary at no stable path. Job commands still can't make user namespaces: the helper's seccomp filter refuses them, or bwrap's--disable-usernsdoes./usr/bin/bwrapbeside Ubuntu'sbwrap-userns-restrictleft neither attached (tested: bwrap then failed outright), so the refusal points to the runner package instead.Follow-ups
sandbox-runtimepackage ships noapply-seccomp, so opencode jobs run without srt's Unix-socket blocking (srt logsapply-seccomp binary not available - unix socket blocking disabled). Worth a quest to package the helper, or to setseccomp.applyPath.Review
quest review), gpt-6.1-sol, medium effort.8e9a0484: one finding, [P1] "the stripping profile breaks the seccomp helper, and the probe only runstrue". Fixed: profile switched to unconfineduserns, probe nested, reproduced before and after (table above).9b0c69635e9c07efdb47128321f081fa03117ad9: no findings.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code