Skip to content

feat(gateway): read-only agents.workspace list/get browsing RPCs#100738

Merged
steipete merged 5 commits into
mainfrom
feat/gateway-workspace-browse-rpcs
Jul 6, 2026
Merged

feat(gateway): read-only agents.workspace list/get browsing RPCs#100738
steipete merged 5 commits into
mainfrom
feat/gateway-workspace-browse-rpcs

Conversation

@steipete

@steipete steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Related: #100705

What Problem This Solves

Operator clients have no way to browse an agent's workspace or preview arbitrary files in it. The existing agents.files.* API is deliberately limited to allowlisted bootstrap files, and sessions.files.* can list the workspace tree but only returns content for transcript-touched text files, keyed by session rather than agent. The mobile file browser (#100705) needs one canonical, agent-scoped, read-only surface.

Why This Change Was Made

Adds a read-only RPC pair, agents.workspace.list and agents.workspace.get (both operator.read), instead of per-client ad hoc paths. Listing is paginated (offset/limit, capped at 500 per page, deterministic directories-first ordering) and reads are bounded: 256 KiB for UTF-8 text, 5 MiB for images returned as base64. Content gating is enforced server-side — text must decode as UTF-8 with no NUL bytes, and image payloads are verified by magic-byte sniffing (@openclaw/media-core detectMime, buffer-only, no filename hints), so a renamed binary cannot ride the image path. Path confinement goes through the existing fs-safe root infrastructure: realpathed root, lexical containment pre-check, symlink and hardlink escape rejection. The bounded browse helpers shared with the session file browser were extracted from sessions-files.ts into workspace-fs.ts so both surfaces run on one policy; sessions.files.* behavior is unchanged. There are deliberately no write operations in this namespace — mutations stay with the allowlisted agents.files.* surface and the separately tracked workspace CRUD discussion (#61368).

Method descriptors are appended at the end of the advertised block to keep existing method indices stable for older clients. Protocol schema changes are additive; Swift models regenerated.

User Impact

Gateway operators get a stable read-only API for workspace browsing; the mobile apps (stacked PRs) build their Files section on it. No behavior change for existing methods or clients.

Evidence

  • Blacksmith Testbox tbx_01kwvyh1rxs9e9jprrepjjtjff: 414 focused tests green, including 16 handler cases covering ../ and absolute-path rejection, symlinked file/directory escapes, hardlink rejection, invalid UTF-8, renamed-binary image bypass, both size caps, pagination determinism, and unknown-agent rejection, plus the session-browser regression suite and registry/protocol guards.
  • Blacksmith Testbox tbx_01kwvzj0hc4evz1sb9fkkv0t4h: full check:changed green across conflicts/changelog/dependency guards, core and core-test tsgo, all core lint shards, five macOS app CI Vitest shards, database/import-cycle guards, and generated checks.
  • pnpm protocol:gen + pnpm protocol:gen:swift output committed; regen on a clean box reproduces the committed bytes.
  • Codex autoreview: extension-only image gating fixed via magic-byte sniffing; final branch review clean. Maintainer review also removed the unused absolute host workspace path from both responses and added explicit POSIX/Windows absolute-input rejection.

Review request

This is a security-sensitive file-read surface (path confinement, read scope). Requesting an owner review from @openclaw/openclaw-secops before merge.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime size: XL maintainer Maintainer-authored PR labels Jul 6, 2026

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

Copy link
Copy Markdown
Contributor

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: 9029e911ef

ℹ️ 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".

Comment thread src/gateway/methods/core-descriptors.ts
@clawsweeper

clawsweeper Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 6, 2026, 5:14 AM ET / 09:14 UTC.

Summary
The PR adds agent-scoped read-only workspace listing and file preview RPCs, shared workspace filesystem helpers, protocol schemas/Swift models, docs, and gateway tests.

PR surface: Source +450, Tests +346, Docs +1, Other +172. Total +969 across 13 files.

Reproducibility: not applicable. as a bug reproduction: this is a feature PR. The security issue is source-reproducible from the new operator.read descriptor and the handler that returns file content.

Review metrics: 1 noteworthy metric.

  • New read-scope file RPCs: 2 added. agents.workspace.list and agents.workspace.get both use operator.read, which matters because one returns arbitrary workspace file content.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/server-methods/sessions-files.ts, unknown-data-model-change: packages/gateway-protocol/src/schema/agents-workspace.ts, unknown-data-model-change: src/gateway/server-methods/sessions-files.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100705
Summary: This PR is the gateway implementation candidate for the mobile read-only workspace browser issue; the broader CRUD workspace-management issue overlaps but remains a separate product/security thread.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🌊 off-meta tidepool
Patch quality: 🦪 silver shellfish
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Decide and implement the approved scope for agents.workspace.get, then add an authorization regression test for read-only clients.
  • [P2] Have the security owner review the final workspace file-read boundary and docs before merge.

Risk before merge

  • [P1] If merged unchanged, existing read- or write-scoped operator clients could read arbitrary UTF-8 files and supported images from an agent workspace, including .env, generated configs, logs, or other local secrets.
  • [P1] The PR is protected by the maintainer label and explicitly requests security-owner review, so the permanent scope boundary should be settled before merge.

Maintainer options:

  1. Gate Workspace File Content Before Merge (recommended)
    Change the content-read RPC to the approved higher-privilege scope and add negative authorization coverage for read-only clients.
  2. Accept Read-Scoped File Browsing
    Merge unchanged only if security owners explicitly accept arbitrary workspace previews for existing read/write-scoped operator tokens.
  3. Pause For Workspace API Direction
    Hold this PR while maintainers decide whether the narrower mobile read-only API should precede the broader workspace-management design.

Next step before merge

  • [P1] Manual security/product review is needed because the narrow code repair depends on whether maintainers choose operator.admin or a new dedicated file-read scope.

Maintainer decision needed

  • Question: Should agents.workspace.get be available to ordinary operator.read clients, or must workspace file content require operator.admin or a new dedicated file-read scope before this API lands?
  • Rationale: This is an intentional product/security boundary choice: a mechanical code change can gate the method, but maintainers need to choose whether mobile read-only browsing is trusted at the existing read scope.
  • Likely owner: steipete — They own the protected PR/linked feature request and are already routing it to secops for the scope decision.
  • Options:
    • Gate Content Above Read Scope (recommended): Require operator.admin or an approved dedicated file-read scope for agents.workspace.get, then update docs and tests before merge.
    • Accept Read-Scope Content Reads: Keep both list and get at operator.read only if secops explicitly accepts that existing read-scoped clients may read arbitrary in-workspace previews.
    • Pause For Broader API Design: Hold this PR until the read-only slice and the broader workspace-management thread share one approved authorization model.

Security
Needs attention: The diff introduces a security-sensitive file-read surface whose content RPC is currently authorized too broadly.

Review findings

  • [P1] Gate workspace file reads above read scope — src/gateway/methods/core-descriptors.ts:257
Review details

Best possible solution:

Land the read-only workspace API only after file-content reads are gated above ordinary operator.read or behind an explicitly approved dedicated file-read scope, with docs and authorization tests matching that boundary.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a bug reproduction: this is a feature PR. The security issue is source-reproducible from the new operator.read descriptor and the handler that returns file content.

Is this the best way to solve the issue?

No. The shared fs-safe extraction and read-only split are plausible, but agents.workspace.get is too broad at operator.read; the safer solution is a higher-privilege content-read scope plus matching tests and docs.

Full review comments:

  • [P1] Gate workspace file reads above read scope — src/gateway/methods/core-descriptors.ts:257
    The new descriptor registers agents.workspace.get as operator.read, and gateway authorization lets any read- or write-scoped operator client through. The handler then returns arbitrary UTF-8/base64 file content from the agent workspace, so bounded mobile/non-admin tokens can fetch files such as .env, generated configs, or other workspace secrets. Require operator.admin or an approved dedicated file-read scope before exposing this content-read RPC.
    Confidence: 0.9

Overall correctness: patch is incorrect
Overall confidence: 0.9

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 3dc00f46704d.

Label changes

Label changes:

  • add P2: This is a normal-priority feature PR with a merge-blocking security-boundary issue, not a shipped user-facing outage.
  • add merge-risk: 🚨 security-boundary: Merging unchanged would expose arbitrary workspace file previews to existing non-admin operator scopes.
  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🌊 off-meta tidepool and patch quality is 🦪 silver shellfish.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The contributor proof gate is not applied because this is a protected maintainer-labeled PR; the PR body provides Testbox/CI validation, but the merge blocker here is security scope approval.

Label justifications:

  • P2: This is a normal-priority feature PR with a merge-blocking security-boundary issue, not a shipped user-facing outage.
  • merge-risk: 🚨 security-boundary: Merging unchanged would expose arbitrary workspace file previews to existing non-admin operator scopes.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🌊 off-meta tidepool and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The contributor proof gate is not applied because this is a protected maintainer-labeled PR; the PR body provides Testbox/CI validation, but the merge blocker here is security scope approval.
Evidence reviewed

PR surface:

Source +450, Tests +346, Docs +1, Other +172. Total +969 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 10 593 143 +450
Tests 1 346 0 +346
Docs 1 1 0 +1
Config 0 0 0 0
Generated 0 0 0 0
Other 1 172 0 +172
Total 13 1112 143 +969

Security concerns:

  • [high] Read-scope workspace content disclosure — src/gateway/methods/core-descriptors.ts:257
    agents.workspace.get is advertised with operator.read while returning arbitrary in-workspace text/image content, expanding existing non-admin tokens into a sensitive file-preview capability.
    Confidence: 0.9

What I checked:

  • PR exposes file-content RPC as read scope: The PR appends agents.workspace.list and agents.workspace.get to the advertised core method block with operator.read, making both callable by non-admin read/write-scoped operator clients. (src/gateway/methods/core-descriptors.ts:256, 9029e911ef42)
  • Handler returns arbitrary workspace file contents: agents.workspace.get resolves a workspace-relative path and returns UTF-8 text or base64 image content from the agent workspace once path and type checks pass. (src/gateway/server-methods/agents-workspace.ts:168, 9029e911ef42)
  • Current auth model lets write scope satisfy read methods: The gateway scope checker allows operator.read methods when the caller has either operator.read or operator.write; only operator.admin bypasses all scopes. (src/gateway/method-scopes.ts:149, 3dc00f46704d)
  • Existing agent file API is allowlisted: Current main limits agents.files.* to bootstrap and memory file names, so the PR expands the existing read boundary from named files to arbitrary in-root paths. (src/gateway/server-methods/agents.ts:102, 3dc00f46704d)
  • Existing session file API gates content by transcript relevance: Current main only adds file content for session-touched paths; browser-only files can be listed but sessions.files.get returns not found when the path lacks session relevance. (src/gateway/server-methods/sessions-files.ts:397, 3dc00f46704d)
  • Related canonical issue is open: The linked mobile workspace-browser issue remains open and already records that this feature is security-sensitive and maintainer-routed.

Likely related people:

  • steipete: They opened the protected mobile workspace-browser issue and this PR, and recent history shows gateway/control UI work in the same operator-client area. (role: feature requester and recent gateway/control UI contributor; confidence: high; commits: eae4000c38e2; files: src/gateway/control-ui.ts, src/gateway/methods/core-descriptors.ts, packages/gateway-protocol/src/schema/agents-workspace.ts)
  • Agustin Rivera: Their prior merged work tightened existing agents.files.* workspace file opens and fs-safe behavior, which is the safety boundary this PR extends. (role: workspace file safety contributor; confidence: medium; commits: 472bcbbccc65; files: src/gateway/server-methods/agents.ts, src/gateway/server-methods/agents-mutate.test.ts, src/infra/fs-safe.ts)
  • Colin Johnson: They authored the session workspace rail that provides the closest current read-only workspace browsing analogue. (role: adjacent workspace browser contributor; confidence: medium; commits: fd855c831f77; files: src/gateway/server-methods/sessions-files.ts, packages/gateway-protocol/src/schema/sessions.ts)
  • Peter Steinberger: History shows repeated gateway scope and authorization refactors relevant to deciding where this new file-read boundary belongs. (role: gateway authorization contributor; confidence: medium; commits: 2777d8ad937d, a40c10d3e245, 51149fcaf15a; files: src/gateway/method-scopes.ts, src/gateway/server-methods.ts, src/gateway/methods/core-descriptors.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. labels Jul 6, 2026
@steipete steipete self-assigned this Jul 6, 2026
@steipete
steipete force-pushed the feat/gateway-workspace-browse-rpcs branch from fa54358 to 1a4711b Compare July 6, 2026 15:24
@steipete
steipete force-pushed the feat/gateway-workspace-browse-rpcs branch from 1a4711b to ab567c9 Compare July 6, 2026 15:26
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready review complete on the exact PR head.

  • Tightened the boundary by removing absolute host workspace paths from both responses, rejecting POSIX and Windows absolute inputs explicitly, and adding invalid UTF-8 plus full image-cap coverage.
  • Verified the shared fs-safe policy directly against @openclaw/fs-safe and the image gate against @openclaw/media-core / file-type; both workspace browsers use the same confinement helpers.
  • Blacksmith Testbox tbx_01kwvyh1rxs9e9jprrepjjtjff: 414 focused handler/session/registry/protocol tests green.
  • Blacksmith Testbox tbx_01kwvzj0hc4evz1sb9fkkv0t4h: full check:changed green across type, lint, guard, database, import-cycle, and app CI lanes.
  • Final Codex autoreview: clean. Hosted exact-head workflow: https://github.com/openclaw/openclaw/actions/runs/28802896398

Known proof gap: the source-blind CLI probe was blocked before Gateway startup by a stale Testbox dependency state and a frozen-lockfile override mismatch. Focused behavior tests, the full changed gate, security workflows, and exact-head hosted CI cover the landed surface.

@steipete
steipete merged commit 30e5dfc into main Jul 6, 2026
105 checks passed
@steipete
steipete deleted the feat/gateway-workspace-browse-rpcs branch July 6, 2026 15:41
@steipete

steipete commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 7, 2026
…nclaw#100738)

* feat(gateway): add read-only agents.workspace list/get browsing RPCs

* fix(gateway): gate workspace image reads on sniffed magic bytes, not extension

* fix(gateway): tighten workspace browsing boundary

* docs(gateway): clarify workspace read trust scope

* chore(gateway): leave release notes to release flow
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…nclaw#100738)

* feat(gateway): add read-only agents.workspace list/get browsing RPCs

* fix(gateway): gate workspace image reads on sniffed magic bytes, not extension

* fix(gateway): tighten workspace browsing boundary

* docs(gateway): clarify workspace read trust scope

* chore(gateway): leave release notes to release flow
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 security-boundary 🚨 May affect sandboxing, authorization, credentials, or sensitive data. P2 Normal backlog priority with limited blast radius. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant