Skip to content

feat: add bwopencode2 sandbox launcher for OpenCode 2 - #24

Merged
Matt Snyder (maatthias) merged 10 commits into
NSLS2:mainfrom
stuwilkins:add_bwopencode2
Oct 19, 2026
Merged

Matt Snyder (maatthias) merged 10 commits into
NSLS2:mainfrom
stuwilkins:add_bwopencode2

Conversation

@stuwilkins

@stuwilkins Stuart B. Wilkins (stuwilkins) commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

feat: add bwopencode2 sandbox launcher for OpenCode 2

Summary

Adds bin/bwopencode2, the bubblewrap sandbox launcher for OpenCode 2
(command opencode2, npm @opencode/cli), parallel to bin/bwopencode
(OpenCode 1). It reuses lib/bwrap_sandbox_lib.sh and keeps the same wrapper
options (--help, --dry-run, --exec, --new-session, --ro-path,
--rw-path, --github-tokens). --init-auth is dropped (see below).
README, docs/bw-wrappers.md and AI_DISCLOSURE.md are updated.

@stuwilkins
Stuart B. Wilkins (stuwilkins) marked this pull request as ready for review October 18, 2026 19:27
Copilot AI balanced review requested due to automatic review settings October 18, 2026 19:27

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved sandbox escape, sensitive-file exposure, and Git configuration issues block approval.

No open issues 🎉

What changed in this PR

Adds bwopencode2 alongside the existing sandbox launchers, reusing the shared bubblewrap library.

Changes:

  • Adds separate OpenCode 2 storage, managed mounts, and launch-argument guards.
  • Documents usage, persistent authentication, and isolation behavior.
  • Updates AI disclosure coverage.
File Description
README.md Lists the launcher and its option differences.
docs/​bw-wrappers.md Documents storage, mounts, and standalone behavior.
bin/​bwopencode2 Implements the OpenCode 2 sandbox launcher.
AI_DISCLOSURE.md Includes the new launcher in disclosure lists.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Config parent symlinks can expose blocked files, and relocated Git configuration breaks relative includes.

No open issues 🎉

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Verified symlink-validation gaps can expose protected host paths, and Git include normalization can hide configuration settings.

1 open issue

Review effort: Balanced

Comment thread lib/bwrap_sandbox_lib.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Git mount handling leaves credential exposure, symlink-related startup failures, and missing relative includes unresolved.

3 open issues
1 resolved since last review

Review effort: Balanced

Comment thread lib/bwrap_sandbox_lib.sh Outdated
Comment thread lib/bwrap_sandbox_lib.sh Outdated
Comment thread lib/bwrap_sandbox_lib.sh Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread lib/bwrap_sandbox_lib.sh Outdated
Comment thread lib/bwrap_sandbox_lib.sh
Parallel to bwopencode for the opencode2 command. Uses separate opencode2 XDG dirs, forces --standalone and refuses server-related options so tools cannot run in an unsandboxed background service.

Assisted-by: opencode:claude-sonnet-5-5
bwopencode: allowlist OPENCODE_* env. Library: mask git credentials, redact secret-like values in --dry-run. All launchers: run /opt/nsls2/libexec/agent-account-check when installed and report an inaccessible command clearly. bwopencode2: allowlist OPENCODE_* env, leave service*.json unmounted.

Assisted-by: opencode:claude-sonnet-5-5
Resolve config entries, git includes and the XDG git/pixi/ccache dirs with realpath before the blocked-path check, so a symlinked parent cannot hide a blocked target. bwopencode2 links the XDG git config to the real mount so relative includes resolve. Add a shared bwrap_resolve_tool and account check for all launchers.

Assisted-by: opencode:claude-sonnet-5-5
…antics

The ansible opencode2 wrapper runs the binary from /opt/nsls2/opencode2, which the sandbox did not mount. Git include paths are no longer collapsed lexically: directories walked before a .. are created, and a symlinked directory before a .. mounts the include at its real path only.

Assisted-by: opencode:claude-sonnet-5-5
Mount only allowed_signers, config, ignore and attributes from ~/.config/git (never the directory, never credentials). Recreate symlinked directories on git include paths so .. resolves as on the host. Skip entries that resolve into blocked locations with a warning; ~/.ssh is never mounted.

Assisted-by: opencode:claude-sonnet-5-5
…reated dirs

Treat only the /etc directories actually bound as present in the sandbox. Skip recreating a host symlink whose destination is already a directory in the sandbox mount list (for example ~/.config) and fall back to a warning, mounting includes at their lexical path where safe.

Assisted-by: opencode:claude-sonnet-5-5

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Git include handling can silently omit configuration, and overlapping mounts can expose excluded OpenCode 2 service settings.

3 open issues
2 resolved since last review

Review effort: Balanced

Comment thread lib/bwrap_sandbox_lib.sh Outdated
Comment thread lib/bwrap_sandbox_lib.sh
Comment thread lib/bwrap_sandbox_lib.sh
…s; refuse dirs containing blocked paths

Deduplicate git includes by raw path, follow nested includes (depth 10, cycle-safe), treat a symlink that is itself a bind root as a conflict, and refuse a working directory or extra path that contains a blocked location.

Assisted-by: opencode:claude-sonnet-5-5
Copilot AI balanced review requested due to automatic review settings October 18, 2026 23:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Verified credential exposure paths and omitted nested Git includes need correction before approval.

2 open issues
3 resolved since last review

Review effort: Balanced

Comment thread lib/bwrap_sandbox_lib.sh
Comment thread lib/bwrap_sandbox_lib.sh Outdated
Add ~/.git-credentials and $XDG_CONFIG_HOME/git/credentials to the blocked list so whole-dir and explicit mounts refuse them. Track parsed git includes by the path as opened so symlinked configs sharing a target are all followed.

Assisted-by: opencode:claude-sonnet-5-5
Copilot AI balanced review requested due to automatic review settings October 18, 2026 23:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Credential-exposure paths and configuration-handling regressions remain unresolved.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Decode quoted Git include paths before selecting mounts

lib/​bwrap_sandbox_lib.sh:1760

A valid Git include such as path = "work.conf" now loses its settings when work.conf is in the XDG Git directory. parse_git_includes retains the quotes, so it does not record the file, and this four-file mount omits it. Previously the whole-directory mount made it available. Decode Git's quoted and escaped include values before relying on the parser to select mounts; this regression affects all five wrappers.

2 resolved since last review

Review effort: Balanced

Decode include path values the way git does (double quotes, escapes, trailing comments, case-insensitive key) before choosing mounts, so a quoted include in ~/.config/git is found, and a quoted include of a blocked file is refused.

Assisted-by: opencode:claude-sonnet-5-5
Copilot AI balanced review requested due to automatic review settings October 19, 2026 08:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Verified mount-validation gaps can expose credentials and excluded host-service settings.

1 open issue

Review effort: Balanced

Comment thread lib/bwrap_sandbox_lib.sh
The blocked list held literal paths while callers compare canonical ones, so a symlinked ~/.config/git, ~/.git-credentials, ~/.ssh or ~/.config let a blocked file through --ro-path, --rw-path or a git include. List each entry both as written and at its resolved target.

Assisted-by: opencode:claude-opus-5-5
Copilot AI balanced review requested due to automatic review settings October 19, 2026 09:37

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Verified mount-validation gaps can expose blocked host credentials and excluded service settings.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@maatthias
Matt Snyder (maatthias) merged commit 1934d9d into NSLS2:main Oct 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants