Skip to content

fix(profile): desktop (was sandbox) is shell-equivalent; add observe; document profiles - #46

Merged
chaodu-agent merged 4 commits into
mainfrom
fix/profile-honesty
Sep 30, 2026
Merged

chaodu-agent merged 4 commits into
mainfrom
fix/profile-honesty

Conversation

@chaodu-agent

Copy link
Copy Markdown
Contributor

First step of #45.

What changes

  • ToolProfile.sandbox → desktop. The wire and persisted value sandbox is still accepted and means desktop, so current Connect/Remote builds and grants stored on disk keep working (Swift init(rawValue:); Linux normalize_profile). Grants now report "desktop".
  • desktop declares isShellEquivalent. The doc comments, the grant instructions, README, the reverse-attach ADR (decision 4 amended) and the Linux docs now say it plainly: osascript / key / mouse reach the desktop user's shell, so removing exec* is not a privilege reduction. The docs recommend lending a dedicated computer when full control is granted, and note that the browser tools use this computer's logged-in profile and network.
  • browser_evaluate removed from the allowed browser tools (Swift + Linux). It is arbitrary JavaScript in the page, and the README already claimed it was excluded.
  • Adversary test ProfileBoundaryTests: it scans the shipped tool sources, so new tools are covered automatically. Any profile with isShellEquivalent == false must allow no exec* / osascript / key / mouse. It fails today for any attempt to call desktop narrower, and it is the gate for the planned observe / browser tiers.
  • No behaviour change beyond browser_evaluate: tool lists are otherwise identical.

Verified

  • macOS (macmini): swift test 118/118, including the 5 new boundary tests.
  • Linux (black): fmt and clippy -D warnings clean; 15/15 unit tests, including old sandbox grants resuming as desktop and unknown profiles dropped, never widened; smoke 47/47, including "old profile name sandbox is accepted as desktop".

Downgrade note: a grant persisted by this build carries "desktop". An older daemon would drop it at resume, which is safe (the grant ends; nothing is widened).

Client copy follow-up: oablab/oab-pty-mac#76.

…rop browser_evaluate

Refs #45. GUI control is a shell: osascript (do shell script), key and mouse all reach the desktop user's shell, so hiding exec* removed a convenience, not a privilege. Rename the profile to desktop (sandbox still accepted on the wire and in stored grants, on macOS and Linux), declare it isShellEquivalent, and add ProfileBoundaryTests: any profile that claims to be narrower must allow no shell-capable tool. Remove browser_evaluate from the allowed browser tools (arbitrary JS; contradicted the README). README, reverse-attach ADR and Linux docs state the limit and recommend lending a dedicated computer.
observe is the first profile that is a boundary: an allowlist of sys_info and screenshot, so any new tool (local or upstream) is denied until listed; isShellEquivalent = false, enforced by ProfileBoundaryTests. Same on the Linux node (local_tool_allowed / OBSERVE_TOOLS; hidden tools are unknown on call too). docs/tool-profiles.md records the profiles, their complete tool lists on macOS and Linux (from live tools/list on macmini and black), and what each loses against the previous one.
@chaodu-agent chaodu-agent changed the title fix(profile): desktop (was sandbox) is shell-equivalent; drop browser_evaluate fix(profile): desktop (was sandbox) is shell-equivalent; add observe; document profiles Sep 30, 2026
@chaodu-agent

Copy link
Copy Markdown
Contributor Author

Added in the second commit:

  • observe profile: sys_info + screenshot only. It is an allowlist, so new local or upstream tools are denied until they are listed. isShellEquivalent = false, and ProfileBoundaryTests.testObserveCanOnlyLook plus the general boundary test hold it to that. The Linux node matches: tools hidden from the list are also unknown on call.
  • docs/tool-profiles.md covers the available profiles and their complete tool lists on macOS (42 / 20 / 2) and Linux (37 / 20 / 2), taken from live tools/list on macmini and black. It also lists what each profile loses against the previous one. The lists were cross-checked by script against desktopBrowserTools (Swift == Rust) and the live owner list.
  • Verified: Swift 119/119. Linux: clippy clean, 16/16 unit tests, smoke 47/47.

Connect/Remote do not offer Observe yet (oablab/oab-pty-mac#76): they must keep sending sandbox until every computer runs this build.

… are accepted

BREAKING: `sandbox` is no longer an alias of `desktop`. It promised a boundary that does not exist, and a client still sending it has not been updated to tell its user the truth. POST /attach with profile=sandbox is a 400 (macOS and Linux), and a grant persisted under it is dropped at resume. Clients must send desktop/observe (oablab/oab-pty-mac#76) and ship together with computers running this build.
@chaodu-agent

Copy link
Copy Markdown
Contributor Author

Per maintainer decision: sandbox is removed, not aliased (third commit, marked breaking).

  • POST /attach {"profile":"sandbox"} returns 400 profile must be one of [owner, desktop, observe] on macOS and Linux. A smoke test covers it: "reject the old sandbox profile name".
  • A grant persisted under sandbox is dropped at resume. The new tests testAGrantStoredUnderTheOldSandboxNameIsDropped (Swift) and grants_stored_under_the_old_sandbox_name_are_dropped (Rust) cover this.
  • docs/tool-profiles.md, the README and the ADR state it.
  • Verified: Swift 120/120; Linux clippy clean, 16/16 unit tests, smoke 48/48; markdownlint on docs/** reports 0 errors.

Rollout consequence. Connect 1.8.0 and Remote 0.5.0 (in App Review) send sandbox and will be refused by any computer running this. The client change (send desktop, add Observe, honest copy) is oablab/oab-pty-mac#76, and it must ship together with the computers being updated.

@chaodu-agent
chaodu-agent merged commit 029b9d5 into main Sep 30, 2026
6 checks passed
@chaodu-agent
chaodu-agent deleted the fix/profile-honesty branch September 30, 2026 16:58
@chaodu-agent chaodu-agent mentioned this pull request Sep 30, 2026
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.

1 participant