fix(sandbox): mount workspace skills read-only#85591
Conversation
|
Codex review: needs maintainer review before merge. Latest ClawSweeper review: 2026-05-23 23:18 UTC / May 23, 2026, 7:18 PM ET. Workflow note: Future ClawSweeper reviews update this same comment in place. How this review workflow works
PR Surface View PR surface stats
Summary Reproducibility: yes. at source level: current main mounts the workspace writable in PR rating Rank-up moves:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. Real behavior proof Risk before merge
Maintainer options:
Next step before merge Security Review detailsBest possible solution: Land this after sandbox/security owner acceptance of the hardened default, preserving absent-root write compatibility and adding an explicit editable-skills mode only if maintainers decide that workflow is supported. Do we have a high-confidence way to reproduce the issue? Yes, at source level: current main mounts the workspace writable in Is this the best way to solve the issue? Yes, with maintainer acceptance: read-only nested binds plus matching generic and remote bridge policy are a narrow maintainable fix for existing skill roots. The remaining question is whether the compatibility break, hot-container timing, and custom-bind boundary are acceptable as default policy. Label justifications:
What I checked:
Likely related people:
Codex review notes: model gpt-5.5, reasoning high; reviewed against 5c4a733912a8. |
|
ClawSweeper PR egg ✨ Hatched: 🥚 common Moonlit Shellbean Hatch commandComment Hatchability rules:
Rarity: 🥚 common. What is this egg doing here?
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Updated the PR body with exact-head Docker proof for |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Current-head proof has been refreshed for 69d60b0. The PR body now includes live terminal output covering Docker mounts, generic bridge blocking, remote bridge blocking, and the absent-root remote write compatibility case. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review PR 85591 current-head proof has been refreshed for The PR body now includes live terminal output from detached worktree
Please re-check the stale-proof finding against the current PR body and head. |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
69d60b0 to
b47a808
Compare
|
Verification before merge: Behavior addressed: workspace skill directories are mounted and enforced read-only for Docker, browser, local bridge, and remote bridge paths; symlink roots, symlink parents, remote-only skill roots, remote symlink aliases, and custom bind shadowing are covered. Thanks @jason-allen-oneal. |
|
Landed via rebase merge onto main.
Thanks @jason-allen-oneal. |
|
@jason-allen-oneal @steipete I'm confused. This PR is presented as introducing a feature, but in the existing state the sandbox workspace in rw mode didn't have built-in skills available at all, so I'm confused what making them read-only does. Did this PR also fix the bug that the skills weren't available? "Added read-only Docker overlays for existing workspace skill roots in rw mode." <- there was no existing workspace skills root, see #48011 which was closed due to hallucination of a PR as an issue tracker, of which the PR was closed in favor of this PR, of which does not seem to address that skills didn't exist in this mode in the first place? Did this also fix the skills bug? If this PR is only for a user-added skills directory, then the related issue needs reopened. @jason-allen-oneal separate feedback for the PR, you write "Kept ro and none on the existing read-only /workspace mount.", but this is not an enduring fix, because none being read-only is also a bug: #37634, so if the intent was to make skills read only this PR will be broken if that bug is fixed. So any solution for "rw" mode needs extended to none. n.b. "none" is the default. |
Summary
Fixes #17931.
This PR protects workspace skill paths exposed to sandboxes from in-sandbox writes.
In
workspaceAccess: "rw", the normal workspace remains writable, but existing workspace skill roots are protected:<workspace>/skills->/workspace/skills:ro,z<workspace>/.agents/skills->/workspace/.agents/skills:ro,zIn
workspaceAccess: "ro"and"none", the existing read-only/workspacemount provides the protection without adding a stale nested/workspace/skillsbind.What changed
rwmode.roandnoneon the existing read-only/workspacemount.SANDBOX_MOUNT_FORMAT_VERSIONfrom2to3.skills/roots.Security impact
This prevents sandboxed agents from rewriting existing workspace skill instructions they are executing under. Normal workspace writes in
rwmode still work, but writes under existing protected skill paths now fail. Absentskills/roots continue to behave as normal workspace paths until they exist and become protected roots.Validation
Targeted command:
Real behavior proof
Behavior addressed: Workspace skill instructions exposed to Docker sandboxes are protected from in-sandbox writes while the normal workspace remains writable. The generic and remote OpenClaw fs bridge write paths classify existing
/workspace/skillsand/workspace/.agents/skillsroots as read-only, so OpenClaw file operations do not bypass the Docker mount policy. The remote bridge also preserves compatibility for absentskills/roots by allowing normal workspace writes there until the protected root exists.Real environment tested: Repository openclaw/openclaw, PR #85591, branch jason-allen-oneal:fix/sandbox-readonly-skill-mounts, current PR head
69d60b0efc1266c1e4d6ca380954102ae0c1c2ea. Proof was run from detached worktree/tmp/openclaw-85591-proofusing the current branch head, Docker imageopenclaw-sandbox:bookworm-slim, a temporary workspace with existing skill roots, a temporary workspace with an absent skills root, the generic OpenClaw fs bridge, and the remote OpenClaw fs bridge runtime path.Exact steps or command run after this patch: Ran
.tmp-pr85591-current-proof.tsfrom/tmp/openclaw-85591-proofat current head69d60b0efc1266c1e4d6ca380954102ae0c1c2ea. The script created existingskills/demo/SKILL.mdand.agents/skills/demo/SKILL.mdroots, created a Docker sandbox with/workspacewritable and both existing skill roots mounted read-only, wrote a normal workspace file through the generic OpenClaw fs bridge, attempted writes to both existing protected skill roots through the generic bridge, wrote a normal workspace file through the remote OpenClaw fs bridge, attempted writes to both existing protected skill roots through the remote bridge, then verified remote bridge compatibility by writing under an absentskills/root.Evidence after fix: Copied terminal output from the current-head proof run:
Observed result after fix: Normal workspace writes succeeded through both the generic and remote OpenClaw fs bridges. Writes under existing
/workspace/skillsand/workspace/.agents/skillsfailed through both bridge paths with read-only sandbox path errors. The Docker mount table showed/workspacewritable while both existing skill roots were mounted read-only. The remote bridge allowed a normal write under an absentskills/root, matching Docker/generic existing-root filtering behavior.What was not tested: A full interactive UI session was not included. This proof covers the Docker mount behavior, both OpenClaw fs bridge write paths, and the final absent-root remote bridge compatibility behavior directly.