Add agent settings injection into guest VM#54
Merged
Conversation
4f47a2c to
70c12aa
Compare
jhrozek
reviewed
Mar 17, 2026
Contributor
jhrozek
left a comment
There was a problem hiding this comment.
let's talk about the gues/host trust boundary and whether we want to migrate all the settings, the code in general looks good.
Implement a declarative, per-agent settings injection framework that copies host agent settings (rules, skills, commands, instructions, and config files) into the guest rootfs before boot. This ensures coding agents inside the VM start with the user's customizations. Key design decisions: - Allowlist-only field filtering for MergeFile entries (deny-by-default) - Tighten-only merge from workspace config (can only disable, never enable) - O_NOFOLLOW reads and source/destination path containment with EvalSymlinks - Hook ordering: credentials → settings → MCP config (deep-merge preserves user MCP servers alongside sandbox-tools) Closes #53 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update USER_GUIDE.md, ARCHITECTURE.md, and CLAUDE.md with settings injection documentation. Remove host MCP server configs from all agent manifests — the VM cannot reach host MCP servers, only the toolhive- proxied sandbox-tools endpoint should be present. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove hooks, bypassPermissions, enableAllProjectMcpServers from claude-code AllowKeys (security: no arbitrary command execution or permission bypass from host settings) - Make applyDenySubKeys recursive so *.apiKey strips nested API keys at all depths, not just immediate children - Bound deepMerge recursion by settings.MaxDepth to prevent stack overflow from pathologically nested configs - Add nil guard for injector parameter in InjectSettings hook - Pass logger from FSInjector to bestEffortChown instead of using package-level slog - Add 31 tests covering stripKeyRecursive, deepMerge/deepMergeN, and applyDenySubKeys (including end-to-end nested key stripping) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
70c12aa to
5ca9f92
Compare
jhrozek
approved these changes
Mar 18, 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.
Summary
~/.claude/), Codex (~/.codex/), OpenCode (~/.config/opencode/)sandbox-tools)--no-settingsCLI flag,settings_importconfig section, and tighten-only workspace merge semanticsArchitecture
Follows strict DDD — zero layer violations confirmed by review:
pkg/domain/settings/settings.go,filter.go— pure types, interfaces, constantsinternal/infra/settings/injector.go,jsonc.go— FSInjector with O_NOFOLLOW, path containment, field filteringinternal/infra/vm/settingshook.go— rootfs hook (mirrorscredentialhook.go)pkg/sandbox/sandbox.go—resolveSettingsManifestwith category filteringcmd/bbox/main.go,pkg/runtime/factory.go— wiringSecurity
*.env,*.headers,*.token, etc.)filepath.EvalSymlinks.broodbox.yaml(can only disable, never enable)Hook Ordering
Adding a Future Agent
Only requires populating
SettingsManifestinregistry.go— no new code paths.Test plan
task fmt— cleantask lint— 0 issuestask test— 26/26 packages pass (with race detector)filter_test.go,settingshook_test.go,injector_test.go(file/dir/merge/JSONC/safety limits), config merge tests, MCP deep-merge edge casesbbox claude-codewith~/.claude/settings.json, rules/, skills/ → verify files in guestbbox claude-code --no-settings→ verify no settings injectedbbox codexwith~/.codex/config.tomlcontaining[auth]→ verify auth stripped.claude.jsonpreserved alongsidesandbox-toolsCloses #53
🤖 Generated with Claude Code