feat(sandbox): implement Linux sandbox helper binary#68
Conversation
…ock, and seccomp The runok project needs a Linux sandbox to restrict filesystem and network access when executing commands. This implements the Helper binary approach (task 12.3) as a separate workspace crate. The helper binary operates in two stages: - Stage 1: Sets up bubblewrap namespace isolation and re-invokes itself inside the sandbox - Stage 2: Applies landlock filesystem restrictions (ABI V5, BestEffort compatibility) and seccomp network filtering (blocks non-AF_UNIX sockets), then execvp the target command Also adds LinuxSandboxExecutor to the main crate with helper binary discovery (exe directory first, then PATH fallback) and SandboxPolicy serialization for JSON transport between the two binaries. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @fohte, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly enhances the security posture of command execution on Linux by integrating a sophisticated sandboxing mechanism. It introduces a dedicated helper binary that leverages core Linux security features like namespaces, Landlock, and seccomp to strictly control filesystem and network access for executed commands. This ensures that commands run in an isolated and restricted environment, minimizing potential security risks without requiring manual configuration from the user. Highlights
Changelog
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
…e helpers Landlock rules within a single ruleset are additive (union of permissions), so adding a read-only rule for a subpath after a read-write rule for its parent does not restrict write access. The read_only_subpaths enforcement is already handled by bubblewrap's mount ordering (--ro-bind after --bind). Also fix tmp_in_writable check that incorrectly matched children of /tmp as covering /tmp, and refactor add_path_rule to accept &Path instead of &str to support non-UTF8 filesystem paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #68 +/- ##
==========================================
- Coverage 89.45% 87.59% -1.87%
==========================================
Files 23 27 +4
Lines 5054 5344 +290
==========================================
+ Hits 4521 4681 +160
- Misses 533 663 +130 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The existing test only verified that find_linux_sandbox_helper() does not panic, without asserting the return value. The patch coverage was low because the exe-directory search path was never exercised. Add a test that creates a fake helper binary in the exe directory to verify the discovery logic, and strengthen the existing test to assert None is returned. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The patch coverage was low because the Exec command path in run_command() and create_executor() were not exercised by tests. Add tests that cover both functions to improve coverage on the lines changed in this PR. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /tmp writable-root check in bwrap.rs used exact string match (r.as_os_str() == "/tmp") while landlock_sandbox.rs used Path::starts_with which also matches parent paths like "/". This inconsistency caused bwrap to add --tmpfs /tmp even when a parent of /tmp was already in writable_roots. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
cargo llvm-cov was only running tests for default-members (main crate), but Codecov counts all diff lines including runok-linux-sandbox. This caused patch coverage to be 41% because the 811 lines in the Linux-only crate were never tested in CI. Adding --workspace runs tests for all crates in the workspace. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`Ruleset::set_compatibility()` requires the `Compatible` trait to be in scope. The import was accidentally dropped during the landlock refactoring, causing a build failure on Linux CI.
The `Compatible` trait import was missing from `landlock_sandbox.rs`, causing a build failure when `--workspace` coverage was enabled in CI. Also added tests for `DryRunError` conversion/display, `exec_command` error paths, `exit_code_from_status`, and `apply_seccomp` early return to improve patch coverage.
The test used `split_whitespace` to parse `sh -c 'exit 42'`, which split the quoted argument into `'exit` and `42'`. On Ubuntu where `sh` is `dash`, this caused a syntax error. Pass command arguments as a slice instead.
When a writable root is a child of /tmp (e.g. /tmp/myproject), the --tmpfs /tmp mount was still emitted and placed after the --bind mount, causing bubblewrap to mount a fresh tmpfs over /tmp and hide the writable bind. The same issue existed in landlock where /tmp would get full write access even when only a subdirectory was intended to be writable. Check both directions: whether /tmp starts_with the writable root (parent case) and whether the writable root starts_with /tmp (child case).
Why
What
runok-linux-sandboxhelper binary as a separate crate in the Cargo workspaceexecvpthe target commandLinuxSandboxExecutorto the main crate with helper binary discovery (exe directory first, PATH fallback) andSandboxPolicyJSON serialization