Skip to content

Autosolve bwrap sandbox#29

Open
fantapop wants to merge 2 commits into
mainfrom
autosolve-bwrap-sandbox
Open

Autosolve bwrap sandbox#29
fantapop wants to merge 2 commits into
mainfrom
autosolve-bwrap-sandbox

Conversation

@fantapop
Copy link
Copy Markdown
Contributor

Wrap the claude subprocess invoked by both assess and implement in a bubblewrap sandbox that denies access to anything not explicitly bound. This prevents Claude from inadvertently reading credentials or other
repositories that earlier workflow steps may have dropped into GITHUB_WORKSPACE or RUNNER_TEMP.

@fantapop fantapop force-pushed the autosolve-bwrap-sandbox branch 3 times, most recently from 2c41941 to 7d08083 Compare May 14, 2026 00:22
@fantapop fantapop requested a review from Copilot May 14, 2026 00:33
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Wraps the claude subprocess invoked by autosolve/assess and autosolve/implement in a bubblewrap filesystem sandbox so Claude can only read/write paths the action explicitly binds. This prevents inadvertent reads of credentials or unrelated repos that earlier workflow steps may drop into GITHUB_WORKSPACE/RUNNER_TEMP. Coordination files (commit message, PR body) are moved out of the repo into a scratch dir, and working_directory becomes a required strict subdirectory of GITHUB_WORKSPACE.

Changes:

  • New bwrap wrapper (wrapWithBwrap/buildBwrapArgs) plus SandboxOptions plumbed through assess, implement, and the AI security review.
  • New sandbox config validation (loadSandboxConfig) requiring working_directory to be a strict subdir of GITHUB_WORKSPACE, and resolving read_paths and GOOGLE_APPLICATION_CREDENTIALS.
  • Action.yml updates to install bubblewrap, relax apparmor_restrict_unprivileged_userns, install claude into /usr/local/bin, and pass new read_paths input; commit-message / PR-body coordination moved to env-var-driven scratch paths.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Documents the sandbox, new read_paths input, and the working_directory requirement.
autosolve/assess/action.yml Adds sandbox setup, requires working_directory, adds read_paths, installs claude into /usr/local/bin.
autosolve/implement/action.yml Same sandbox setup and input changes as the assess action.
autosolve/internal/claude/claude.go Adds SandboxOptions, wrapWithBwrap/buildBwrapArgs, runs claude via bwrap, and adds coordination env vars to baseline.
autosolve/internal/claude/claude_test.go Tests for buildBwrapArgs covering binds, denied paths, tmpfs, --share-net, and tail argv.
autosolve/internal/config/config.go Adds WorkingDir/ScratchDir/ReadPaths to Config and loadSandboxConfig validation.
autosolve/internal/config/config_test.go Tests covering workspace-root rejection, outside-workspace rejection, path population, and creds auto-bind.
autosolve/internal/assess/assess.go Passes SandboxOptions to the runner.
autosolve/internal/implement/implement.go Sets coordination env vars, switches commit/PR-body paths to scratch dir, allows printenv for them, passes SandboxOptions.
autosolve/internal/implement/implement_test.go Updates mock and tests to use scratch-dir paths via env vars.
autosolve/internal/prompt/templates/implementation-footer.md Instructs claude to use AUTOSOLVE_*_PATH env vars instead of in-repo dotfiles.
autosolve/go.mod Lowers Go directive from 1.26 to 1.24.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread autosolve/assess/action.yml
Comment thread autosolve/implement/action.yml
Comment thread README.md
@fantapop fantapop force-pushed the autosolve-bwrap-sandbox branch from 7d08083 to 465aa67 Compare May 14, 2026 01:18
@fantapop fantapop requested a review from linhcrl May 14, 2026 01:21
@fantapop fantapop marked this pull request as ready for review May 14, 2026 01:21
fantapop and others added 2 commits May 14, 2026 10:14
The hosted ubuntu-latest runners ship with Go 1.25.x preinstalled. With
go.mod declaring "go 1.26", the action's "skip setup-go when go is on
PATH" branch trusts the existing 1.25, but go build then sees the 1.26
directive and Go's auto-toolchain machinery downloads 1.26.0 mid-build,
adding latency on every cold cache run.

The autosolve packages don't use any post-1.21 stdlib features
(slices.Contains is the newest), so 1.25 is well within the floor we
need. Matching the directive to the runner's preinstalled toolchain
eliminates the download.

Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
Wrap the claude subprocess invoked by both `assess` and `implement` in a
bubblewrap sandbox that denies access to anything not explicitly bound.
This prevents Claude from inadvertently reading credentials or other
repositories that earlier workflow steps may have dropped into
GITHUB_WORKSPACE or RUNNER_TEMP.

Bind layout:
- working_directory: RW (Claude's cwd)
- additional_read_paths: RO (caller-specified files or directories)
- GOOGLE_APPLICATION_CREDENTIALS file: RO, auto-bound when set so
  Claude can refresh Vertex tokens
- /usr, /etc, /lib, /lib64, /opt: RO (OS + tooling, no per-user data).
  The action's setup step installs claude into /usr/local/bin so the
  binary is reachable via the /usr ro-bind without per-binary plumbing
- /run/systemd/resolve: RO when present, required for DNS via
  /etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf. We
  deliberately do NOT bind all of /run, which would expose
  /run/docker.sock — the GHA runner user is in the docker group and a
  reachable docker.sock is a sandbox-escape vector
- Private /tmp tmpfs: RW, discarded after the run

Everything else is denied — including the workspace root, RUNNER_TEMP,
/home/runner, ssh keys, and credential files dropped by other steps.

Other notes:
- working_directory is now required and rejects the workspace root
  outright, since other actions (e.g. google-github-actions/auth) drop
  credential files there. Callers must check the target repo into a
  subdirectory like ./repo and pass working_directory: ./repo.
- --share-net keeps the host network namespace; the alternative
  (private netns) fails on Ubuntu 24.04+ because AppArmor blocks
  RTM_NEWADDR for unprivileged netns. The sandbox enforces filesystem
  isolation, not network isolation.
- The action setup step disables
  kernel.apparmor_restrict_unprivileged_userns; acceptable on
  ephemeral hosted runners, persistent self-hosted runners should
  evaluate the tradeoff first.
- README documents the bind layout, caveats, and the required
  actions/checkout subdirectory pattern.

Co-Authored-By: roachdev-claude <roachdev-claude-bot@cockroachlabs.com>
@fantapop fantapop force-pushed the autosolve-bwrap-sandbox branch from 465aa67 to 967cc12 Compare May 14, 2026 17:14
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.

2 participants