Repository navigation
fix(opencode): prepare agent-owned sandbox scratch directory - #561
Conversation
Prepare /tmp/opencode on each kit startup with UID/GID 1000 and mode 0700. Refuse symlinks and non-directories, preserving existing contents. Add regression tests and lifecycle documentation. Co-authored-by: OpenCode AI Agent <[email protected]>
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: comment — 1337238a7e7fb93e46f3ef746727bbd0095c6fe9
No findings in the scoped scratch-directory change. Required CI is not green: Markdown Lint failed during the unchanged minimatch dependency audit, before linting. Live root ownership transfer and backend startup completion ordering remain unverified.
Assisted-by: OpenCode [GPT 6.1 Sol] skill:change-review
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: request changes — 74412c6002975952fac9f7e88876acc8b71ffedb
The prior review had no code findings. Its CI gap is resolved: the current CI run passed against this head merged with base 73a3c9fde57065b2371cdddc54430fe98b7a4aa1.
Must fix before merge: Resolve scratch ownership from the actual sandbox agent instead of literal UID/GID 1000.
| # | Sev | Where | Problem → failure scenario | Evidence |
|---|---|---|---|---|
| 1 | major | integrations/isolation/acq-kits/opencode/spec.yaml:133 |
MSB supports OCI images where UID 1000 is occupied and provisions agent at another UID. This root command assigns /tmp/opencode to 1000 with mode 0700, leaving the actual agent unable to write there. Resolve ownership with id -u agent / id -g agent (or the equivalent by-name identity) and add coverage for a non-1000 agent; update the README's numeric-ownership claim. |
confirmed by consumer trace: Quickstart acq.backends/msb.sh:4318–4321,4354–4363 allocates a free UID; :2515–2517 maps kit user: "1000" to agent, but does not rewrite numeric arguments inside root shell commands. |
Not verified: Live root-to-agent transfer and SBX/MSB startup execution were not exercised; local filesystem tests substitute the caller's UID/GID and cannot validate this identity mapping.
Assisted-by: OpenCode [GPT 6.1 Sol Latest Guardrails Defaultv2] skill:change-review
Look up the sandbox agent's uid/gid with id instead of assigning the literal 1000:1000, which breaks on MSB images where acq provisions agent at another uid. Fail closed when the agent user is missing. Add tests with id/install shims for a non-1000 agent and a missing agent. Co-authored-by: OpenCode Agent <[email protected]>
|
🤖: AI agent (First Mate), posting on behalf of @mogul. Reply to the review at Fixed in
The only other literal Not verified: live execution inside a real SBX or MSB sandbox, and acq translation of the new command (the shims substitute the caller identity). |
basiliskus
left a comment
There was a problem hiding this comment.
Verdict: approve — 9065e0cbf4ad34f190fc0117867747c7f0375011
Prior major finding resolved in 9065e0cb: integrations/isolation/acq-kits/opencode/spec.yaml:127–139 resolves ownership with id -u agent / id -g agent. The non-1000 and missing-agent regressions pass and fail against the prior hardcoded implementation for the intended reasons. The README now matches the implementation.
Must fix before merge: none. No new findings.
Nit: Update the PR body's remaining 1000:1000 claims and five-test summary to describe name-resolved ownership and seven tests.
Not verified: Live root-to-agent ownership transfer and actual SBX/MSB startup execution; local tests use identity/ownership shims. CI passed, but its raw checkout log names a merge with f0a951f363f26031a28faaafff70ab116b14cde2, not the currently reported PR base 73a3c9fde57065b2371cdddc54430fe98b7a4aa1.
Assisted-by: OpenCode [GPT 6.1 Sol Latest Guardrails Defaultv2] skill:change-review
🤖 I have created a release *beep* *boop* --- ## [1.19.0](v1.18.0...v1.19.0) (2026-11-05) ### Features * **oci-engine:** qualify bounded rootless resource controls ([#562](#562)) ([cf6d7a5](cf6d7a5)) * **opencode:** add live image-capability verification script (not yet run) ([#572](#572)) ([f0a951f](f0a951f)) * **paseo:** bump pinned Paseo CLI to 0.15.0 ([#560](#560)) ([0c4e1a8](0c4e1a8)) * **usai-catalog:** carry verified capability metadata through a catalog refresh ([#578](#578)) ([fcd94e5](fcd94e5)) * **usai-catalog:** publish verified image input modality for 12 USAi models ([#575](#575)) ([907d486](907d486)) * **usai-catalog:** single refresh entrypoint for the catalog and neutral artifacts ([#573](#573)) ([0c1b145](0c1b145)) ### Bug Fixes * **ci:** validate pending release comparisons against their commit ([#570](#570)) ([0961019](0961019)) * **deps:** update Ruff package and hook together to 0.17.3 ([#568](#568)) ([a6266dd](a6266dd)) * **opencode:** prepare agent-owned sandbox scratch directory ([#561](#561)) ([89a66b2](89a66b2)) * **paseo:** launch real opencode outside PID 1 ([#559](#559)) ([ce4aa08](ce4aa08)) * **paseo:** verify runtime identity without false orphan verdicts ([#567](#567)) ([1062244](1062244)) * **usai-catalog:** allow summary and title roles in catalog recommendations schema ([#551](#551)) ([ad2aadd](ad2aadd)) * **usai:** retire stale references to the removed model sync script ([#552](#552)) ([95be9b9](95be9b9)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Summary
Fix the OpenCode acq-kit scratch directory being owned by root. The install-time version checks run as root and can create
/tmp/opencodeas0:0, mode0755, leaving the agent unable to write there.The kit now prepares the directory on every sandbox startup as
1000:1000, mode0700. It rejects pre-existing symlinks and non-directories and does not recursively change existing contents.Eligibility & Accountability
AI Assistance Disclosure
Type of Change
Motivation
The affected sandbox was observed to have
/tmp/opencodeowned by0:0, mode0755; agent writes failed withEACCES. Startup preparation also recreates the directory after/tmpis cleared. The updated kit must be applied to existing sandboxes; merely restarting OpenCode does not apply the fix.Plan and Scope
User approved a scoped change to the OpenCode kit's
spec.yaml,README.md, and regression tests. No dependency pins, provider configuration, isolation backend configuration, or CI configuration changed.Testing / Verification Transcript
Commands ran with an isolated verification environment and private temporary files. Only summaries are included; no raw runtime or credential-bearing logs are attached.
make validatemake validate-kitsmake validate-provider-input-contractmake generate-checkmake scan-shellpython -m pytest scripts/tests/ -qmake test-kitspython -m ruff check scriptsgit diff --checkThe five new tests cover numeric ownership/startup wiring, creation and repeat execution, permission repair with content preservation, symlink refusal, and regular-file refusal. They run the real shell command and
installagainst a temporary path, substituting the caller's UID/GID so they work without root.Initial verification was blocked by the running sandbox's unwritable scratch directory and missing Python tools. After installing the pinned project/dev tools locally, temporary fixtures placed inside the checkout interfered with repository-wide scanners. Moving fixtures to a user-approved private temporary directory resolved these environmental failures; all listed checks were rerun successfully.
Live root-to-agent ownership transfer and actual SBX/MSB startup dispatch are BLOCKED here: no root access or usable Docker daemon. Full
make ciincluding network-backed dependency audit and pre-commit hooks was not run. CI and human review remain required before merge/deployment.Safety Checklist
Security Impact
Root work is limited to the fixed scratch directory, with private rather than world-writable permissions. Existing symlinks and non-directories fail explicitly without replacement. Checks are not atomic protection against concurrent hostile path replacement; the documented scope is refusal of pre-existing symlinks. Existing root-owned contents are deliberately not recursively changed and may remain unwritable. No authentication, authorization flow, credential handling, network access, or exposed ports change.
Rollback
Revert this PR and reapply the previous kit. This stops subsequent startup repairs; it does not restore previous directory metadata automatically. No existing contents are deleted by this change.
Reviewer Notes
Please confirm the root startup hook executes before agent entry on both supported backends and verify that UID/GID
1000:1000matches the sandbox agent. Human code-owner review is required; the AI agent has not approved or merged this PR.