Repository navigation
cmux-tui: only connect to derived local sockets served by this user - #15144
Conversation
Add failing tests for the checks a client should make before it writes to a socket at a path it derived: the socket directory is a private one this user owns, the listener runs as this user, the listener refuses other users, terminal hosts refuse a symlinked endpoint directory, and the remote daemon lets the mux owner derive its own socket. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A socket path cmux derives from a session name can fall back to a shared /tmp name. Before a client writes to one it now checks that the socket's directory is a private one this user owns and that the listener runs as this user. Explicit --socket and environment-selected paths keep their current behavior. The listener refuses clients from other users (root is still allowed). The remote daemon lets the mux owner derive its own socket instead of passing it back as an explicit --socket, and it and its sidecar only talk to mux and terminal-host listeners running as the same user. Terminal hosts keep their shared /tmp endpoint directory owned by this user and private, and check the host's uid before sending the owner capability. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
|
Warning Review limit reachedNext included review available in 4 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (15)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
|
Review (subagent, correctness-first; I re-verified the load-bearing check and the cross-PR detail myself) Findings: none blocking. The question I cared about was whether this is an fd check or a path check, because a pre-connect path stat would be TOCTOU and would not actually close anything. It is an fd check. Also confirmed:
Coverage, checked rather than assumed: the five Fixed: nothing needed. Left, none blocking:
Merging :) |
|
Merge receipt for |
ba94a13 CI: let Iroh release gate reuse unchanged TUI artifact 71a921c fix(web): stop orphaned Cloud VM alert pages (manaflow-ai#15138) 9971c2c Keep newer iOS connections alive when a recovery is superseded (manaflow-ai#15141) c307ab0 cmux-tui: only connect to derived local sockets served by this user (manaflow-ai#15144) 1220252 codex-teams: keep the watcher's socket password out of its arguments (manaflow-ai#15140) b3a73f0 chatmux-relay: keep cmux-tui sockets and journal cursors private to this user (manaflow-ai#15156) b0d5083 ci: dispatch UI tests from a default-branch workflow; PR CI keeps no write token (manaflow-ai#15226) 1255448 test: fix three app-host tests that keep main red (manaflow-ai#15204) 0fc4975 test: pin the fixture PATH inside the zsh watcher sleep test (manaflow-ai#15237) 758aaeb fix(ios): clear read notifications on foreground return (manaflow-ai#14725) 4c15bb3 cmux-browser: stop requiring GPL for web/package.json (manaflow-ai#15231) 97fe6b4 test: keep the Cloud notification harness workspace unselected (manaflow-ai#15215) 61083e3 test: keep workspace cwd inheritance tests off the shared standard defaults (manaflow-ai#15227) eae4994 Pin password badge actions to their source runtime (manaflow-ai#14921) fd96369 Check the owner of the Claude shim directory in the app, workspace commands and nushell (manaflow-ai#15185) 0ebf8d7 Fix main-thread freeze during SSH paste detection (manaflow-ai#15113) a98c560 test: pin font magnification in the Cloud outline attention test (manaflow-ai#15213)
Summary
When the preferred runtime path is too long, cmux-tui derives a session socket in a
/tmp/cmux-tui-<uid>or hashed fallback directory. Clients connected to that path without checking the directory or who was listening. The remote daemon'sensure_daemonalso passed its derived mux path to the mux owner as an explicit--socket, which skipped the owner's own directory check.Derived session sockets are now used only when they are in a private directory owned by this user and are served by this user:
cmux_tui_core::server::connect_session_socket, checks the directory, then connects withplatform::transport::connect_same_user. It refuses the listener before writing anything if the listener's peer uid isn't this user. Attach, relay, launch, the detached owner, the raw/wire/lifecycle CLI, local-owner startup and the machine agent all use it.ensure_daemonnow lets the mux owner derive its own socket instead of passing--socket. The remote daemon, sidecar and mux monitor check that the mux or terminal-host listener belongs to this user. That includesCMUX_MUX_SOCKET, because the daemon starts that owner itself./tmp/cmux-th-<uid>owned by this user at 0700 and refuse a symlink. They check the host's uid before sending the owner capability.Nothing changes for an explicit
--socketor env socket. Windows keeps a plain connect.Compatibility
There's no protocol change.
ensure_daemon, the sidecar and the mux owner are the same binary, so they derive the same path.PermissionDenied, and so does a Unix target without peer-credential support./tmp/cmux-th-<uid>.Not changed
schema_socket_ownersends only an identify probe.Testing
Focused command:
./scripts/verify-cmux-tui-hosted.sh --filter private_socket(hostedcargo test --workspace --locked private_socket, Linux and macOS).remote_cli::tests::private_socket_remote_mux_owner_derives_its_own_socketfailed because the mux owner got--socket. Cargo stops at the first failing test binary, so thecmux-tui-coreregressions in that run were compiled but not executed. Lint failed as expected on the red stub's unusedpeer_may_connect.private_sockettests passed on Linux and macOS, as did lint (Linux, macOS), Rust MSRV 1.91 and the release-path artifact build.remote_cli::tests::private_socket_remote_mux_owner_derives_its_own_socketplatform::tests::private_socket_listener_admits_only_the_owner_and_rootplatform::tests::private_socket_peer_uid_must_match_the_expected_userserver::tests::private_socket_connect_requires_a_private_derived_parentterminal_host_runtime::unix::tests::private_socket_terminal_host_endpoint_dir_refuses_a_symlinkpython3 scripts/verify-local.py: passed (portable checks only; no native build).Not run:
--fullhosted verification, including Windows.Changelog
🤖 Generated with Claude Code