Skip to content

test/changelog: follow up sandbox workspace mount fixes#32274

Merged
steipete merged 1 commit intomainfrom
fix/32227-followup-tests-changelog
Mar 2, 2026
Merged

test/changelog: follow up sandbox workspace mount fixes#32274
steipete merged 1 commit intomainfrom
fix/32227-followup-tests-changelog

Conversation

@steipete
Copy link
Contributor

@steipete steipete commented Mar 2, 2026

Follow-up to #32227 and #32217.

Scope:

Why:

@cursor
Copy link

cursor bot commented Mar 2, 2026

PR Summary

Low Risk
Low risk: changes are limited to tests and changelog updates, with no production behavior modifications.

Overview
Adds regression coverage to verify the primary /workspace bind mount is read-only when workspaceAccess is ro or none, and remains writable for rw, across both ensureSandboxContainer and ensureSandboxBrowser create flows.

Updates CHANGELOG.md to include the missing fix entries for sandbox workspace mount permissions and Signal react message-id fallback.

Written by Cursor Bugbot for commit 4f9ffea. This will update automatically on new commits. Configure here.

@steipete steipete merged commit 02eeb08 into main Mar 2, 2026
11 of 12 checks passed
@steipete steipete deleted the fix/32227-followup-tests-changelog branch March 2, 2026 22:59
@openclaw-barnacle openclaw-barnacle bot added agents Agent runtime and tooling size: S maintainer Maintainer-authored PR labels Mar 2, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4f9ffea9cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

bindArgs.push(args[i + 1]);
}
}
expect(bindArgs).toContain(expectedMainMount);

Choose a reason for hiding this comment

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

P2 Badge Strengthen mount-permission assertion in workspaceAccess table test

This assertion only checks that the expected mount string is present, but this test case builds cfg with createSandboxConfig([], undefined, workspaceAccess), which keeps the default custom bind "/tmp/workspace:/workspace:rw"; since custom binds are appended after the main mount in container creation, a ro/none case can still end up effectively writable while this test passes. As written, the regression test can miss exactly the permission regression it is meant to guard against.

Useful? React with 👍 / 👎.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

"uses expected main mount permissions when workspaceAccess=$workspaceAccess",
async ({ workspaceAccess, expectedMainMount }) => {
const workspaceDir = "/tmp/workspace";
const cfg = createSandboxConfig([], undefined, workspaceAccess);
Copy link

Choose a reason for hiding this comment

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

Test fixture adds conflicting rw bind overriding ro mount

Medium Severity

The new parameterized test calls createSandboxConfig([], undefined, workspaceAccess), where undefined for binds falls through to the default ["/tmp/workspace:/workspace:rw"]. The production code in createSandboxContainer first adds the main mount with the correct :ro suffix, then appendCustomBinds appends this default bind as -v /tmp/workspace:/workspace:rw for the same target. For the ro and none cases, the Docker args end up with both a :ro and a :rw bind for /workspace, with the :rw coming last. The toContain assertion passes because the :ro entry exists, but the regression test doesn't catch that a conflicting :rw mount undermines the read-only protection. Passing [] instead of undefined for binds would make this a proper regression test.

Additional Locations (1)

Fix in Cursor Fix in Web

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

This PR adds regression tests for the workspace mount permissions fix from #32227 across both sandbox create paths (browser.create.test.ts and docker.config-hash-recreate.test.ts), and adds the two missing changelog entries for #32227 and #32217.

  • docker.config-hash-recreate.test.ts: a new createSandboxConfig optional parameter (workspaceAccess, defaulting to "rw") and a parameterised it.each covering all three valid access modes (rw, ro, none) with correct mount-suffix expectations.
  • browser.create.test.ts: two individual tests added for none and rw modes; the ro mode is not explicitly tested (minor coverage gap — both ro and none share the same implementation branch in browser.ts, so it is implicitly covered).
  • The redundant cfg.workspaceAccess = "none" assignment in the first new browser test is a no-op since buildConfig already returns that value.
  • CHANGELOG.md entries are correctly formatted and placed.

Confidence Score: 4/5

  • Safe to merge — tests and changelog only; no production code changed.
  • The PR only touches tests and changelog. The core logic being tested was already verified against the implementation. The only gaps are a missing ro case in the browser tests and a trivially redundant assignment, both non-blocking.
  • Minor attention to src/agents/sandbox/browser.create.test.ts for the missing ro coverage case.

Last reviewed commit: 4f9ffea

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

3 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +188 to +190
it("mounts the main workspace read-only when workspaceAccess is none", async () => {
const cfg = buildConfig(false);
cfg.workspaceAccess = "none";
Copy link
Contributor

Choose a reason for hiding this comment

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

Redundant workspaceAccess assignment

buildConfig(false) already returns a config with workspaceAccess: "none" (line 51 of this file), so the explicit reassignment on line 190 is a no-op. It creates a false impression that the test is changing something meaningful. The line can be removed without affecting behaviour.

Suggested change
it("mounts the main workspace read-only when workspaceAccess is none", async () => {
const cfg = buildConfig(false);
cfg.workspaceAccess = "none";
const cfg = buildConfig(false);
// workspaceAccess is already "none" from buildConfig
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/sandbox/browser.create.test.ts
Line: 188-190

Comment:
**Redundant `workspaceAccess` assignment**

`buildConfig(false)` already returns a config with `workspaceAccess: "none"` (line 51 of this file), so the explicit reassignment on line 190 is a no-op. It creates a false impression that the test is changing something meaningful. The line can be removed without affecting behaviour.

```suggestion
    const cfg = buildConfig(false);
    // workspaceAccess is already "none" from buildConfig
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +188 to +225
it("mounts the main workspace read-only when workspaceAccess is none", async () => {
const cfg = buildConfig(false);
cfg.workspaceAccess = "none";

await ensureSandboxBrowser({
scopeKey: "session:test",
workspaceDir: "/tmp/workspace",
agentWorkspaceDir: "/tmp/workspace",
cfg,
});

const createArgs = dockerMocks.execDocker.mock.calls.find(
(call: unknown[]) => Array.isArray(call[0]) && call[0][0] === "create",
)?.[0] as string[] | undefined;

expect(createArgs).toBeDefined();
expect(createArgs).toContain("/tmp/workspace:/workspace:ro");
});

it("keeps the main workspace writable when workspaceAccess is rw", async () => {
const cfg = buildConfig(false);
cfg.workspaceAccess = "rw";

await ensureSandboxBrowser({
scopeKey: "session:test",
workspaceDir: "/tmp/workspace",
agentWorkspaceDir: "/tmp/workspace",
cfg,
});

const createArgs = dockerMocks.execDocker.mock.calls.find(
(call: unknown[]) => Array.isArray(call[0]) && call[0][0] === "create",
)?.[0] as string[] | undefined;

expect(createArgs).toBeDefined();
expect(createArgs).toContain("/tmp/workspace:/workspace");
expect(createArgs).not.toContain("/tmp/workspace:/workspace:ro");
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing ro workspace access test case

The docker path in docker.config-hash-recreate.test.ts uses it.each to cover all three valid SandboxWorkspaceAccess values (rw, ro, none), but this file only adds two tests — none and rw — leaving the ro case untested for the browser create path.

In browser.ts, both ro and none follow the same code branch (both map to :ro), so the none test provides implicit coverage. However, to stay consistent with the docker test and to guard against any future divergence in that branch, adding an explicit ro test here (or converting the two tests into an it.each over all three modes) would be a worthwhile follow-up.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/sandbox/browser.create.test.ts
Line: 188-225

Comment:
**Missing `ro` workspace access test case**

The docker path in `docker.config-hash-recreate.test.ts` uses `it.each` to cover all three valid `SandboxWorkspaceAccess` values (`rw`, `ro`, `none`), but this file only adds two tests — `none` and `rw` — leaving the `ro` case untested for the browser create path.

In `browser.ts`, both `ro` and `none` follow the same code branch (both map to `:ro`), so the `none` test provides implicit coverage. However, to stay consistent with the docker test and to guard against any future divergence in that branch, adding an explicit `ro` test here (or converting the two tests into an `it.each` over all three modes) would be a worthwhile follow-up.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling maintainer Maintainer-authored PR size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant