Add sandbox.container.excluded_files to mask worktree files from containers#134
Merged
raine merged 4 commits intoraine:mainfrom Apr 18, 2026
Merged
Conversation
18dd8d0 to
44c47d7
Compare
Address review feedback on the excluded_files masking feature:
- Path safety: replace stringy `contains("..")` check with a
Component::ParentDir walk so legitimate filenames like `foo..bar`
and `.env..local` are no longer falsely rejected while actual
parent-dir traversal is still blocked.
- Global-only scope: a project's `.workmux.yaml` can no longer set
`excluded_files`. Letting project config override the global list
defeats the purpose -- a malicious repo could hand itself an empty
list to strip user-level secret protections. Now matches the scope
rules already used for host_commands, extra_mounts, and network.
- Apple Container: set-but-unusable is now a hard error instead of
a silent tracing warning. The warning was written to the log file
rather than stderr, so users would not notice that their secrets
were still readable inside the sandbox. Fail fast instead.
- Main-worktree alias: workmux bind-mounts the main worktree for
symlink resolution, which created an alias path through which
a masked secret (e.g. `.env` symlinked into the main worktree)
remained readable. The masking step now runs after both mounts
and shadows both the current-worktree and main-worktree paths.
Tests updated and added: global-only merge semantics, hard error on
Apple Container, safe dotted names accepted, and main-worktree alias
masking under a realistic gitlink layout. Docs updated to describe
the new behavior.
Two follow-ups to excluded_files: - Relative gitdir: `git worktree add --relative-paths` (git 2.48+) writes a `.git` gitlink file with a path like `gitdir: ../main/.git/worktrees/wt1`. The previous code passed the raw pointer into `ancestors().nth(2)`, which yielded relative paths and emitted bogus `--mount source=../main,target=../main` args that Docker rejects or misinterprets. Now the pointer is resolved against the worktree root when it's not already absolute, matching how the sidebar daemon's worktree resolver already handles this. A test covers the relative case and asserts that all mount spec sources and targets are absolute. - Directory entries: `is_file()` returns false for directories, so excluding a directory (e.g. `.aws`) previously produced a misleading "does not exist on disk" warning even though the path was there. Now we detect `is_dir()` in the candidate loop and emit a dedicated message explaining that only regular files can be masked.
44c47d7 to
bdf34ac
Compare
Owner
|
Thank you |
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
sandbox.container.excluded_filesconfig: list of worktree-relative paths that get shadowed by a read-only/dev/nullbind mount, so an agent running inside the container cannot read them (e.g..envfiles). Default unset — no behavior change...) are rejected; missing files are skipped with a warning.docs/guide/sandbox/container.mdand discoverable viaworkmux config reference/workmux init.Test plan
cargo fmt --checkcleancargo testsuite (946 tests) passes.envfile shows size 0 while the host file is unchanged; non-excluded files likeREADME.mdremain readable