Skip to content

IPC catalog

Version: 0.44.1
Main branch: 6d282acf
Date: 2026-06-12

This document catalogs every inter-process channel in AgentMux, their wire contracts, authentication models, and security properties observed in the Sweep 2026-06-12. It is intended as both a developer reference and a security audit anchor point.


  1. Architecture Overview
  2. Channel Summary Table
  3. Channel A: Renderer → Host Local IPC (HTTP)
  4. Channel B: Host → Renderer Event Push (CEF JS Bridge)
  5. Channel C: Host ↔ Launcher Named Pipe
  6. Channel D: Host → Srv Named Pipe (Read-only Bridge)
  7. Channel E: Renderer ↔ Srv WebSocket (RPC)
  8. Channel F: Renderer → Srv HTTP Service
  9. Channel G: Browser DOM API (HTTP over IPC)
  10. Channel H: OSC 16162 — Terminal Shell Integration Escape Sequences
  11. Channel I: Chromium Remote Debug Port (CDP)
  12. IPC Token and Auth Key — Lifecycle and Leak Surface
  13. Launcher ↔ Srv Named Pipe (Reducer Bus)
  14. Command/Event Domain Mixing in agentmux-common/src/ipc.rs
  15. Environment Variable Contract
  16. Security Findings Cross-Reference

IPC architecture: launcher (top-left, purple) connects bidirectionally to cef (top-right) via Ch C named pipe, and to srv (bottom-left) via Ch 13. CEF connects to renderer via Ch D (read-only) and Ch A/B (bidirectional dashed). Srv connects to renderer via Ch E/F WebSocket.

Process hierarchy (production):

agentmux-launcher.exe (owns Win32 Job Object J0)
└── agentmux-cef.exe (CEF host, IPC client)
└── [CEF subprocesses: renderer, GPU, plugin]
└── agentmux-srv.exe (backend sidecar, HTTP/WS server)

IDNameTransportDirectionAuthPurpose
ALocal IPC HTTPHTTP POST 127.0.0.1:<rnd>renderer→hostBearer ipc_tokenAll host command dispatch
BCEF JS event pushframe.execute_javascript()host→renderernone (same process trust)Push typed events to frontend
CLauncher named pipe / Unix socketNamed pipe (Win) / Unix sockethost↔launchernone (OS pipe ownership)Window state mirror, saga dispatch, WRR
DSrv named pipe bridgeNamed pipe (Win) / Unix sockethost←srv (read-only)none (OS pipe ownership)Forward srv reducer events to renderer
ESrv WebSocket RPCWS ws://127.0.0.1:<rnd>/wsrenderer↔srv?authkey= query param (WS-only)RPC commands, event bus subscription
FSrv HTTP serviceHTTP POST 127.0.0.1:<rnd>/agentmux/servicerenderer→srvX-AuthKey headerObject CRUD, tab/block/workspace ops
GBrowser DOM APIHTTP POST 127.0.0.1:<rnd>/agentmux/browser/*renderer→hostBearer ipc_tokenCSS query, JS eval, screenshot, click, key in browser panes
HOSC 16162Terminal escape sequence (PTY output)shell→renderernone (data in PTY stream)Inject env keys into block metadata; configure poller
IChromium remote debugHTTP/WS 127.0.0.1:9222 (prod) / 9223 (dev)any local process→renderernoneCDP automation; used internally by Browser DOM API
13Launcher↔Srv named pipeNamed pipe (Win) / Unix socketlauncher↔srvnone (OS pipe ownership)Srv reducer Command/Event bus

3. Channel A: Renderer → Host Local IPC (HTTP)

Section titled “3. Channel A: Renderer → Host Local IPC (HTTP)”

Source: agentmux-cef/src/ipc.rs

Axum HTTP server bound to 127.0.0.1:0 (random ephemeral port). Port is written to <data_dir>/ipc-port-<hash> file as <port>:<token> after CEF init. File is owner-readable only on Unix (0600); no Windows DACL restriction on the port file itself (only on authkey.dev).

Routes:

  • POST /ipc — main command handler (ipc.rs:84)
  • GET /health — unauthenticated health check (ipc.rs:85)
  • POST /agentmux/browser/* — Browser DOM API (see Channel G)

Authorization: Bearer <ipc_token> header required on POST /ipc (ipc.rs:135-151).
ipc_token is a random UUID generated once per host process.

Gap: CorsLayer::permissive() is applied (ipc.rs:90), accepting any Origin header. Any web page that guesses or reads the port can make unauthenticated cross-origin preflight-exempt requests (OPTIONS is ignored by the auth check) and then authenticated ones if it has obtained the token.

JSON body: {"cmd": "<command_name>", "args": <JSON>}
Response: {"success": bool, "data": <JSON>|null, "error": string|null} always HTTP 200 (even for errors; frontend checks success field). (ipc.rs:168)

All commands dispatched through route_command() (ipc.rs:181).

CommandArgsReturnsNotes
get_platform"win32" / "darwin" / "linux"
get_auth_keystringReturns state.auth_key — the srv-side auth key. Logged at debug with first 8 chars.
get_is_devbool
get_user_namestring
get_host_namestring
get_data_dirpath string
get_config_dirpath string
get_user_home_dirpath string
get_docsite_urlURL string
get_zoom_factornumber
get_about_modal_detailsobjectVersion, build label, etc.
get_host_infoobject
get_backend_endpoints{web_endpoint, ws_endpoint}Srv HTTP + WS addresses
get_wave_init_optsobject
set_window_init_status{status}null
fe_log{level, msg}nullFrontend log relay
fe_log_structured{level, msg, fields}null
CommandArgsReturnsNotes
get_backend_infoobject
restart_backendnullKills and respawns agentmux-srv
close_window{window_label?}null
minimize_window{window_label?}null
maximize_window{window_label?}null
toggle_floating_maximize{...}null
set_zoom_factor{factor}null
is_main_window{window_label}bool
get_window_label{window_label}string
open_new_windownull
open_subwindow{parent_instance_id}nullHidden subwindow; not user-accessible
open_floating_pane_window{...}nullTear-off pane window
get_instance_number{window_label}number
register_backend_window{window_label, window_id}nullMaps label → srv window UUID
get_env{key}string | nullReturns std::env::var(key) — any env var on the host process
open_external{url}nullOpens URL in OS default browser
reveal_in_file_explorer{path}null
set_window_transparency{...}null
set_window_opacity{window_label, opacity}null
get_window_opacity{window_label}number
start_window_drag{...}null
get_window_rect{window_label}rect
set_window_rect{window_label, rect}null
get_window_position{window_label}pointspawn_blocking (UI thread bounce, up to 250 ms)
resolve_window_at_cursorwindow_labelspawn_blocking
update_floating_redock_hover{...}nullspawn_blocking
clear_floating_redock_hover{...}null
move_window_by{dx, dy}null
set_window_position{x, y}null
toggle_devtools{window_label}null
inspect_element_at{x, y}null
show_context_menunullNo-op; handled in JS overlay
list_windowsarray
list_window_instancesarray
get_double_click_timenumber
focus_window{window_label}null
close_window_by_label{window_label}null
main_window_focus{window_label?}nullReclaim keyboard focus from pane HWNDs
CommandArgsReturns
start_cross_drag{...}null
update_cross_drag{...}null
complete_cross_drag{...}null
cancel_cross_drag{...}null
get_cursor_point{x,y}
get_mouse_button_stateobject
set_drag_cursornull
restore_drag_cursornull
release_drag_capturenull
set_js_drag_active{active}null
open_window_at_position{x, y}null
tear_off_pool_promote{pool_label}null
pool_window_ready{pool_label}null
tear_off_sc_move_handshake{...}object
CommandArgsReturnsNotes
read_clipboardstringCEF cannot use navigator.clipboard without permission policy
write_clipboard{text}null
CommandArgsReturnsNotes
browser_pane_create{block_id, url, x, y, width, height, window_label?}boolCreates native CefBrowserView child
browser_pane_navigate{block_id, url}bool
browser_pane_resize{block_id, x, y, width, height}boolFires on every pixel during drag
browser_pane_close{block_id}boolCancels pending HTTP-auth callbacks
browser_pane_go_back{block_id}bool
browser_pane_go_forward{block_id}bool
browser_pane_reload{block_id}bool
browser_pane_focus{block_id}bool
browser_pane_auth_submit{request_id, username, password}boolResolves parked CEF AuthCallback
browser_pane_auth_cancel{request_id}boolCancels auth challenge
browser_panes_set_overlay_clip{window_label?, rects[]}boolClips pane HWNDs around DOM overlays
CommandArgsReturns
detect_installed_clisarray
get_provider_configobject
save_provider_config{config}null
get_provider_install_info{provider}object
set_provider_auth{provider, ...}null
clear_provider_auth{provider}null
get_provider_auth_status{provider}object
check_cli_auth_status{cli}object
install_cli{cli, ...}null
get_cli_path{cli}string
check_nodejs_availablebool
ensure_auth_dir{provider}path
run_cli_login{cli, ...}null
cancel_cli_loginnull
ensure_settings_filenull
open_in_editor{path}null
copy_file_to_dir{src, dst_dir}null
consume_drag_pathsarray
CommandPurpose
run_commandCommand palette execution
open_agentOpen agent pane

4. Channel B: Host → Renderer Event Push (CEF JS Bridge)

Section titled “4. Channel B: Host → Renderer Event Push (CEF JS Bridge)”

Source: agentmux-cef/src/launcher_event_bridge.rs, agentmux-cef/src/srv_event_bridge.rs

frame.execute_javascript(...) injected by the host into every top-level renderer frame. Not a network channel; runs inside the CEF process boundary.

None. Host process trust. A compromised renderer cannot forge these events; they originate in the Rust host.

Launcher events dispatched as:

window.__agentmux_launcher_event(<JSON Event>)

Srv events dispatched as:

window.__agentmux_srv_event(<JSON Event>)

Event shapes are the agentmux_common::ipc::Event variants serialized to JSON (agentmux-common/src/ipc.rs:800-1503).

  • Launcher events: window lifecycle (open/close/pool), instance numbers, WRR drift, saga lifecycle, corrective moves, HostShouldQuit.
  • Srv events: workspace/tab/block CRUD, layout tree mutations, active-tab changes.

5. Channel C: Host ↔ Launcher Named Pipe

Section titled “5. Channel C: Host ↔ Launcher Named Pipe”

Source: agentmux-cef/src/launcher_ipc.rs, agentmux-common/src/ipc.rs

  • Windows: Win32 named pipe. Path passed via env var AGENTMUX_LAUNCHER_PIPE. Launcher creates with first_pipe_instance(true).
  • Unix/macOS: Unix domain socket. Same env var name.

Dev mode (task dev without launcher, or host invoked directly): AGENTMUX_LAUNCHER_PIPE is unset; all report_* calls are silent no-ops.

None. OS-level pipe ownership. The host process must be a child of the launcher (enforced by parent_process::parent_is_agentmux_launcher() check before connecting, agentmux-cef/src/main.rs:455-463).

Newline-delimited JSON. One message per line.

Host → Launcher: agentmux_common::ipc::Command variants (externally tagged: {"cmd":"register",...}).

Launcher → Host: agentmux_common::ipc::HostFrame envelope (Phase CPD-1+). Each frame is tagged with "kind":

  • {"kind":"event","event":"<name>",...} — launcher-emitted Event broadcast
  • {"kind":"command","cmd":"<name>",...} — saga-issued Command dispatched to host

Backward-compat: Pre-CPD-2 launchers emit bare Event JSON without the HostFrame wrapper; the host falls back to parsing as raw Event (launcher_ipc.rs:266-279).

CommandFieldsPurpose
Registerkind, pid, versionHandshake; MUST be first message
PingnonceRound-trip confirmation
GoodbyeGraceful disconnect
ReportWindowOpenedlabel, kind, parent_label?CEF on_after_created fired
ReportWindowClosedlabelCEF on_before_close fired
ReportPoolWindowAddedlabel, saga_id?Pool window spawned
ReportPoolWindowRemovedlabelPool window leaving pool
ReportPoolWindowPromotedlabelPool → user-visible window transition
ReportHostCountswindows, poolDrift detection snapshot
ReportHostPoolCountcountPool-only drift snapshot
ReportBackendWindowIdRegisteredlabel, window_idFrontend register_backend_window
ReportBackendWindowIdUnregisteredlabelWindow closed
ReportHwndOpenedhwnd, class_name, title, label_hint?Win32 EVENT_OBJECT_CREATE
ReportHwndDestroyedhwndWin32 EVENT_OBJECT_DESTROY
ReportHwndVisibilityChangedhwnd, visibleEVENT_OBJECT_SHOW/HIDE
ReportHwndForegroundChangedhwndEVENT_SYSTEM_FOREGROUND
ReportHwndIconicChangedhwnd, iconicEVENT_SYSTEM_MINIMIZE*
ReportHwndPositionChangedhwnd, rectWM_WINDOWPOSCHANGED (50 ms debounce)
ReportMonitorTopologyChangedrectsWM_DISPLAYCHANGE
ReportPanesReapedlabel, saga_id?Browser-pane HWNDs drained
ReportPoolDrainDecisionlabel, was_last, saga_id?Pool-drain-if-last decision
ReportSagaActionFailedsaga_id, reasonSchema-only CPD-1; no producer yet
GetSnapshotRequest full launcher state snapshot
GetSrvSnapshotRequest srv reducer snapshot
GetEventssinceReplay events since version
SpawnPoolWindowsaga_idSaga asks host to spawn a pool window
ReapPaneslabel, saga_idSaga asks host to drain pane HWNDs
DrainPoolIfLastlabel, saga_idSaga asks host to drain pool if last window

All agentmux_common::ipc::Event variants propagated. Key ones:

EventPurpose
RegisteredConnection ack
PongPing reply
ErrorParse/invariant violation
WindowOpened/ClosedWindow mirror updated
PoolWindowAdded/Removed/PromotedPool inventory changed
WindowInstanceAssigned/ReleasedInstance number assigned
BackendWindowIdRegistered/Unregisteredlabel↔window_id mapping
DriftDetectedMirror mismatch
HwndDriftDetectedCEF/Win32 HWND disagreement
CorrectiveWindowMoveReducer-initiated window repositioning
HostShouldQuitLast user-visible window gone
SagaStarted/Completed/FailedSaga lifecycle
SnapshotFull launcher state
SrvSnapshotFull srv reducer state
WorkspaceCreated/Deleted/RenamedWorkspace CRUD
TabCreated/Deleted/Reordered/MovedTab CRUD
BlockCreated/Deleted/MovedBlock CRUD
LayoutInsertNode / … (11 layout variants)Layout tree mutations

6. Channel D: Host → Srv Named Pipe (Read-only Bridge)

Section titled “6. Channel D: Host → Srv Named Pipe (Read-only Bridge)”

Source: agentmux-cef/src/srv_ipc.rs

  • Windows: Win32 named pipe. Path in env var AGENTMUX_SRV_PIPE_PATH (set by launcher’s srv_spawner.rs).
  • Unix: Unix domain socket (same env var).

Activated only when AGENTMUX_SRV_PIPE_PATH is set. Dev builds (is_dev_build_exe) short-circuit to None (main.rs:482-486).

None. OS-level pipe ownership.

Same agentmux_common::ipc::Event newline-delimited JSON as Channel C. The host reads events from srv’s reducer and forwards them to all renderer frames via srv_event_bridge::dispatch_to_renderers.

Host is a read-only subscriber. No outbound command channel exists today (saga coordinator in Phase E.5+ will add producers).


7. Channel E: Renderer ↔ Srv WebSocket (RPC)

Section titled “7. Channel E: Renderer ↔ Srv WebSocket (RPC)”

Source: agentmux-srv/src/server/websocket.rs

WebSocket at ws://127.0.0.1:<srv_port>/ws.

?authkey=<auth_key> query parameter on the WebSocket upgrade URL (agentmux-srv/src/server/mod.rs:387-396). This is the only route that accepts the authkey via query string; all other routes require the X-AuthKey header.

Gap (audit C3): The query-string authkey is visible in browser history, server access logs, and Referer headers on cross-origin navigations. Acceptable for WebSocket (where the browser API does not permit custom headers) but represents a key leak risk if the URL is ever logged or forwarded.

JSON text frames. Two message directions:

Renderer → Srv (wscommand):

{"wscommand": "<cmd>", "message": <RpcMessage>}

Or type-tagged messages for ping/bus/setblocktermsize/blockinput:

{"type": "ping"|"bus:register"|"bus:send"|"bus:inject", ...}

Srv → Renderer:

  • RPC events: {"eventtype":"rpc","data":{...}}
  • WaveObj updates: {"eventtype":"waveobj:update","oref":"block:<id>","data":{...}}
  • MessageBus messages: {"type":"bus:message","data":{...}}
  • Periodic ping: {"type":"ping","stime":<ms>} every 10 seconds
CommandPurpose
COMMAND_EVENT_SUBSubscribe to WPS event scope
COMMAND_EVENT_UNSUBUnsubscribe from scope
COMMAND_EVENT_UNSUB_ALLUnsubscribe all
COMMAND_EVENT_READ_HISTORYReplay buffered WPS events
COMMAND_CONTROLLER_INPUTSend input to block controller (PTY/stdin)
COMMAND_CONTROLLER_RESYNCForce controller state resync
COMMAND_GET_METAGet block/tab/workspace metadata
COMMAND_SET_METASet metadata
COMMAND_GET_FULL_CONFIGGet full wconfig
COMMAND_GET_AI_RATE_LIMITRate limit status
COMMAND_ROUTE_ANNOUNCEAnnounce wshrpc route
COMMAND_ROUTE_UNANNOUNCEDeannounce route
COMMAND_SET_CONFIGSet config value
COMMAND_APP_INFOGet app/version info
COMMAND_SUBPROCESS_SPAWNSpawn subprocess in pane
COMMAND_AGENT_INPUTSend text to agent PTY
COMMAND_AGENT_STOPStop agent
COMMAND_TOOL_DECISIONAccept/reject tool call
COMMAND_WRITE_AGENT_CONFIGWrite agent config
setblocktermsizeResize PTY terminal
blockinputSend raw bytes to PTY

MessageBus over WS:

TypeFieldsPurpose
bus:registeragent_idRegister pane as a bus agent
bus:sendfrom, to, payload, priority?Send message to agent
bus:injecttarget, bus_messageInject text into agent PTY

8. Channel F: Renderer → Srv HTTP Service

Section titled “8. Channel F: Renderer → Srv HTTP Service”

Source: agentmux-srv/src/server/service.rs, agentmux-srv/src/server/mod.rs

POST http://127.0.0.1:<srv_port>/agentmux/service

X-AuthKey: <auth_key> header required (agentmux-srv/src/server/mod.rs:374-406). Auth middleware also accepts ?authkey= query param exclusively on the /ws route.

http://127.0.0.1:* and http://localhost:* origins accepted (mod.rs:143-150). External origins rejected. This is a narrowing from the previous CorsLayer::permissive() that accepted any origin (corrected in 2026-05-11 audit C3).

POST body: {"service": "<service>", "method": "<method>", "args": [...], "uicontext": {...}}
Response: {"success": bool, "data"?: ..., "error"?: string, "updates"?: [WaveObjUpdate]}

Updates from service calls are broadcast on the event bus to all WebSocket subscribers.

Service / Method Catalog (representative subset)

Section titled “Service / Method Catalog (representative subset)”
ServiceMethodPurpose
objectGetObjectFetch one object by oref
objectGetObjectsFetch multiple objects
objectCreateBlockCreate a new block
objectUpdateObjectUpdate object meta
objectDeleteBlockDelete block
tabCreateTabCreate tab in workspace
tabCloseTabClose tab
workspaceCreateWorkspaceNew workspace
workspaceDeleteWorkspaceDelete workspace
windowCloseWindowClose window
Various agent, CLI, identity, install services

9. Channel G: Browser DOM API (HTTP over IPC)

Section titled “9. Channel G: Browser DOM API (HTTP over IPC)”

Source: agentmux-cef/src/browser_api/routes.rs, registered via crate::browser_api::register_routes(app) (ipc.rs:88)

Same HTTP server as Channel A (127.0.0.1:<ipc_port>). Routes under /agentmux/browser/*.

Authorization: Bearer <ipc_token> header required by every handler (routes.rs:747-753).

RouteMethodPurpose
POST /agentmux/browser/queryCSS selector query in pane DOMReturns matching Element[]
POST /agentmux/browser/focus_infoGet document.activeElementReturns focused Element
POST /agentmux/browser/evalRun arbitrary JS in pane rendererReturns serialized value
POST /agentmux/browser/screenshotCapture PNG of pane viewportReturns base64 PNG
POST /agentmux/browser/click_elementSynthesize mouse click at element centroidDispatches Input.dispatchMouseEvent
POST /agentmux/browser/focus_elementCall .focus() on first matching element
POST /agentmux/browser/dispatch_keySend text or named key to focused elementSupports Enter, Tab, Escape, Backspace, ArrowUp/Down/Left/Right, Space
POST /agentmux/browser/navigateNavigate pane to URL via Page.navigate
POST /agentmux/browser/backBrowser history backPage.goBack
POST /agentmux/browser/forwardBrowser history forwardPage.goForward
POST /agentmux/browser/reloadReload current pagePage.reload

All Browser DOM API routes proxy through the Chromium DevTools Protocol (CDP) WebSocket at ws://127.0.0.1:<debug_port>/devtools/page/<target> (routes.rs:49, routes.rs:737-744). The debug port is 9222 (prod) or 9223 (dev) (main.rs:652).

Security: /agentmux/browser/eval runs arbitrary JS. The eval route accepts a caller-supplied script string and executes it in the pane’s JS world via Runtime.evaluate with no sandbox or isolation (routes.rs:201). The script runs in whatever origin the pane currently loads. Any local process holding the ipc_token can execute arbitrary JS in any browser pane.


10. Channel H: OSC 16162 — Terminal Shell Integration Escape Sequences

Section titled “10. Channel H: OSC 16162 — Terminal Shell Integration Escape Sequences”

Source: agentmux-srv/src/backend/shellintegration/bash.sh (and zsh, fish, pwsh), frontend/app/view/term/termosc.ts:177-335, frontend/app/view/term/termwrap.ts:160-161

VT escape sequence embedded in PTY output, parsed by xterm.js in the renderer:

ESC ] 16162 ; <command> ; <JSON-payload> BEL

Registered as an OSC handler on xterm.js number 16162 (termwrap.ts:160).

None. The sequence is parsed from PTY byte stream. Any program running in the terminal can emit OSC 16162 and trigger the handler.

Sub-commandWire exampleHandler actionSecurity implication
E\033]16162;E;{"AGENTMUX_AGENT_ID":"Alice","AGENTMUX_AGENT_COLOR":"#ff0000"}\007Calls RpcApi.SetMetaCommand to write {"cmd:env": <payload>} into the block’s persistent metadata (termosc.ts:266-269). Empty payload clears.Env-key injection: any terminal program can write arbitrary keys into cmd:env. Values are then injected into child process environments (shell.rs:583-591). The AGENTMUX_AGENT_COLOR=#000000 Win11 focus-border bug was caused by a user’s shell profile emitting this sequence with a black color — no valid value range is enforced.
X\033]16162;X;{"muxbus_url":"https://...","muxbus_token":"tok"}\007Makes an authenticated POST /agentmux/reactive/poller/config to reconfigure the cloud MuxBus poller URL and token (termosc.ts:289-316).Poller injection: any terminal program can redirect the srv’s outbound polling to an attacker-controlled endpoint. Pre-audit C1/C2 this route was unauthenticated; now requires X-AuthKey.
A\033]16162;A;{}\007Sets shell:state = "ready" in block RT infoState metadata injection
C\033]16162;C;{"cmd64":"<b64>"}\007Sets shell:state = "running-command", decodes cmd64shell:lastcmdLast-command display
D\033]16162;D;{"exitcode":0}\007Sets shell:lastcmdexitcodeExit code display
I\033]16162;I;{"inputempty":true}\007Sets shell:inputemptyInput state
M\033]16162;M;{"shell":"bash","shellversion":"5.2","uname":"Linux"}\007Sets shell:type, shell:version, shell:unameShell metadata
R\033]16162;R;{}\007If in alternate screen buffer: writes ESC[?1049l to exit alternate screenScreen reset

Scripts are embedded in the srv binary (shellintegration.rs:16-19) and deployed to ~/.agentmux/shell/<type>/ on first launch or version change. The shell controller sources them via --rcfile (bash), ZDOTDIR (zsh), -File (pwsh), or -C source (fish) (shellintegration.rs:108-165).


11. Channel I: Chromium Remote Debug Port (CDP)

Section titled “11. Channel I: Chromium Remote Debug Port (CDP)”

Source: agentmux-cef/src/main.rs:652-674, agentmux-cef/src/browser_api/routes.rs:49

Chromium DevTools Protocol over HTTP and WebSocket:

  • http://127.0.0.1:9222/json — list targets (prod)
  • ws://127.0.0.1:9222/devtools/page/<target> — CDP per-target session

Port is 9222 in production, 9223 in dev builds (main.rs:652). No CSP header is configured.

None. The CDP endpoint is unauthenticated. Any local process can connect and:

  • Enumerate all browser targets (main window and all panes)
  • Execute arbitrary JavaScript in any target (Runtime.evaluate)
  • Capture screenshots
  • Intercept network traffic
  • Modify DOM

Note: no_sandbox: 1 is set in CEF settings (main.rs:664), which means the Chromium renderer processes run without the OS sandbox. This widens the blast radius of any renderer compromise.

The Browser DOM API (Channel G) connects to CDP per-request via CdpSession::connect() to serve its /agentmux/browser/* routes. The debug port is stored in state.debug_port (main.rs:653) and read by routes.rs:48.


12. IPC Token and Auth Key — Lifecycle and Leak Surface

Section titled “12. IPC Token and Auth Key — Lifecycle and Leak Surface”

There are two distinct secrets:

SecretName in codeWhere generatedWho uses itScope
ipc_tokenstate.ipc_tokenRandom UUID, host startupPOST /ipc (Channel A) and POST /agentmux/browser/* (Channel G)Per-host-process
auth_keystate.auth_key (host); AppState.auth_key (srv)Random UUID, srv startup; passed to host via env or backend-info/ws?authkey= (Channel E) and X-AuthKey (Channel F)Per-srv-process
VectorLeaksCondition
ipc-port-<hash> file (<data_dir>/ipc-port-<hash>)<port>:<ipc_token>Always (owner-readable, but data dir may have lax permissions on some installations)
authkey.dev file (<data_dir>/authkey.dev)Both ipc_token and auth_key, plus both endpoint addressesDev mode only (AGENTMUX_DEV=1); file is chmod 0600 (Unix) / DACL-restricted (Windows) (dev_authfile.rs)
Renderer URL query stringipc_token via ?ipc_token=<token> (if frontend embeds it in the URL on load)Visible in process arguments, browser history, Referer headers
WS URL query stringauth_key via ?authkey=<key>Visible in server access logs (server/mod.rs:387)
get_auth_key IPC commandauth_keyAny caller that already holds ipc_token — no additional gate
{
"version": 1,
"auth_key": "<uuid>",
"web_endpoint": "127.0.0.1:<port>",
"ws_endpoint": "127.0.0.1:<port>",
"ipc_endpoint": "127.0.0.1:<port>",
"ipc_token": "<uuid>",
"service_path": "/agentmux/service",
"file_path": "/agentmux/file",
"instance": "v<version>",
"data_dir": "<path>",
"host_pid": <pid>,
"created_at": "<ISO8601>"
}

(dev_authfile.rs:32-45)


13. Launcher ↔ Srv Named Pipe (Reducer Bus)

Section titled “13. Launcher ↔ Srv Named Pipe (Reducer Bus)”

Source: agentmux-common/src/ipc.rs (shared wire types), agentmux-launcher/src/ (server side, not read directly)

  • Windows: Named pipe (path keyed on hash(data_dir, version) for isolation invariant I5)
  • Unix: Unix domain socket

None. OS-level pipe ownership + launcher Job Object containment.

Same agentmux_common::ipc::Command / agentmux_common::ipc::Event newline-delimited JSON as Channel C. The launcher is the server; srv connects as a client with ClientKind::Srv.

srv-Domain Commands (routed to the srv reducer)

Section titled “srv-Domain Commands (routed to the srv reducer)”

All Command variants from the second half of ipc.rs (Phase E.x):

CommandPurpose
GetSrvSnapshotRequest srv reducer full snapshot
CreateWorkspace, DeleteWorkspace, RenameWorkspace, UpdateWorkspaceMetaWorkspace CRUD
CreateTab, DeleteTab, SetActiveTab, ReorderTab, ReorderTabsBulk, RenameTab, UpdateTabMeta, MoveTabTab CRUD and ordering
CreateWindow, CloseWindowInternal, SwitchWorkspace, UpdateWindowMetaWindow↔workspace mapping
CreateBlock, DeleteBlock, MoveBlock, UpdateBlockMetaBlock CRUD
SetFocusedNode, SetMagnifiedNodeLayout focus/magnify
LayoutInsertNode, LayoutInsertNodeAtIndex, LayoutDeleteNode, LayoutMoveNode, LayoutSwapNodes, LayoutResizeNodes, LayoutReplaceNode, LayoutSplitHorizontal, LayoutSplitVertical, LayoutClear, LayoutSetTreeLayout tree mutations (E.4.B, 11 variants)

agentmux-common/src/ipc.rs (2034 LOC) contains a single Command enum that conflates two distinct domains:

  • Launcher domain (Register, Ping, ReportWindow*, ReportHwnd*, SpawnPoolWindow, ReapPanes, DrainPoolIfLast, GetSnapshot, GetEvents, …) — processed by the launcher’s reducer.
  • Srv domain (GetSrvSnapshot, CreateWorkspace, DeleteWorkspace, CreateTab, LayoutInsertNode, …) — processed by the srv reducer.

These share a wire-level namespace. The routing logic lives in the respective process’s connection handler and is not enforced by the type system. A mis-addressed CreateWorkspace sent to the launcher pipe returns Event::Error { code: InvalidCommand } rather than a type error.

See ipc.rs:1-23 for the stated backward-compat policy (externally tagged enums, unknown-command → Event::Error).


14. Command/Event Domain Mixing in agentmux-common/src/ipc.rs

Section titled “14. Command/Event Domain Mixing in agentmux-common/src/ipc.rs”

agentmux-common/src/ipc.rs is 2034 lines. It defines:

  • ClientKind enum — Host, Renderer, Srv, Tool
  • Command enum — all commands from both the launcher domain and the srv domain (see §13 above)
  • Event enum — all events from both domains (~60 variants)
  • HostFrame{"kind":"event"|"command", ...} CPD-1 envelope
  • Helper types: Rect, WindowKind, WindowSnapshot, LifecyclePhase, DriftKind, HwndDriftKind, Severity, ErrorCode

There is no sub-module or feature-flag separation between launcher-domain and srv-domain variants. Operators reading the enum cannot tell at a glance which variants belong to which pipe. The only documentation is inline comments citing phase numbers (e.g., “Phase E.2”, “Phase B.4”).

Recommendation: Add // === LAUNCHER DOMAIN === and // === SRV DOMAIN === section comments at the boundary within the enum to make the split explicit without requiring a breaking split into two enums.


The following env vars are injected into PTY child processes by the shell controller (shell.rs:501-614) and are consumed by the OSC 16162 shell integration scripts. Their documented meaning, the source that sets them, and known hazards are listed here.

VariableSet byConsumed byNotes
AGENTMUXshell.rs (always "1")Shell integration scripts (guard against nested invocations)
AGENTMUX_BLOCKIDshell.rsShell integration, muxlogBlock UUID for the pane
AGENTMUX_TABIDshell.rsShell integrationTab UUID
AGENTMUX_VERSIONshell.rsShell integration (muxlog pointer resolution)Semver string
AGENTMUX_LOG_DIRshell.rsmuxlog helperPath to ~/.agentmux/logs/
AGENTMUX_LOCAL_URLshell.rs (forwarded from host’s env)Agent CLIs, bashwraphttp://127.0.0.1:<srv_port>
AGENTMUX_AGENT_IDUser’s shell profile or cmd:env block metaShell integration → OSC 16162 EPane title/color identity. Any value from the shell profile flows into block metadata via OSC 16162 E.
AGENTMUX_AGENT_COLORUser’s shell profile or cmd:env block metaShell integration → OSC 16162 E → UIRegression root cause: A user setting AGENTMUX_AGENT_COLOR=#000000 in their shell profile caused the Win11 focus-border to turn black. No value range validation exists.
AGENTMUX_AGENT_TEXT_COLORUser’s shell profileShell integrationSimilar risk to AGENTMUX_AGENT_COLOR
TERMshell.rs (xterm-256color)Terminal applications
COLORTERMshell.rs (truecolor)Terminal applications
TERM_PROGRAMshell.rs (agentmux)Terminal applications
ZDOTDIRshellintegration.rs (zsh only)zsh startupRedirects zsh config to ~/.agentmux/shell/zsh/
AGENTMUX_ZDOTDIRshellintegration.rs (zsh only)Integration scriptPreserved original ZDOTDIR

Variables removed from the environment when launching non-agent panes (no explicit cmd:env agent config, shell.rs:603-607):

  • AGENTMUX_AGENT_ID, AGENTMUX_AGENT_COLOR, AGENTMUX_AGENT_TEXT_COLOR, WAVEMUX_AGENT_ID, WAVEMUX_AGENT_COLOR

Gap: There is no schema for what values are valid for AGENTMUX_AGENT_COLOR. The shell controller accepts and injects whatever value the block meta contains without validation. A color value of #000000 produced a visible Win11 focus-border regression; other values (e.g., malformed CSS) could cause UI rendering issues.


This section maps the sweep findings to the specific code locations documented above.

FindingLocationImpactMitigation status
ipc_token leaks via ipc-port filemain.rs:827 writes port:token to <data_dir>/ipc-port-<hash>Any process that can read data dir obtains both port and token; can drive Channel A and G fullyFile permissions not explicitly restricted (unlike authkey.dev). The launcher reads it for single-instance forwarding.
ipc_token leaks via renderer URL queryFrontend’s load-time URL (not in scope of this sweep’s source read; reported by sweep)Token in browser history, Referer, process argumentsNot mitigated in code seen
authkey.dev leaks both tokens (dev mode)dev_authfile.rs:32-45; written when AGENTMUX_DEV=1Full API access with both ipc_token and auth_keyFile is chmod 0600 / owner DACL. Dev-only.
get_auth_key IPC command returns srv auth keyipc.rs:194-197Any renderer holding ipc_token can obtain auth_key (srv-side token)No separate gate; design intentional (renderer needs both)
get_env returns any env varplatform.rs:128-137; ipc.rs:247Renderer can extract AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, etc. from the host process environment. Requires ipc_token.No allowlist or blocklist enforced
/agentmux/browser/eval runs arbitrary JSroutes.rs:201Any caller with ipc_token can execute JS in any open browser pane (including cross-origin pages).Auth: ipc_token required. No script length or content restriction.
OSC 16162 E injects env keys into block metatermosc.ts:262-287Any program in the PTY can write arbitrary keys into cmd:env. Those keys are injected into future child process environments by shell.rs:583-591.No key allowlist. No value validation. Caused AGENTMUX_AGENT_COLOR Win11 bug.
OSC 16162 X reconfigures srv pollertermosc.ts:289-316Any terminal program can set the srv’s outbound polling URL/token (pre-audit C1/C2: unauthenticated; post-audit: authed with auth_key)Auth added in 2026-05-11 audit. auth_key required from renderer.
CorsLayer::permissive() on host IPC serveripc.rs:90Any Origin accepted on http://127.0.0.1:<ipc_port>. Web pages from the renderer’s browsed sites can make preflight-free requests if they guess/obtain the port and token.Not mitigated. Srv has been narrowed to loopback-only origins (mod.rs:143-150); host has not.
CDP port 9222 unauthenticatedmain.rs:674Any local process can enumerate targets, execute JS, capture screens, intercept network. Used internally by Channel G.No auth. no_sandbox: 1 widens blast radius.
No CSP on any routeipc.rs, srv/server/mod.rsXSS in the main window or a browser pane has no Content-Security-Policy barrier.Not mitigated.
no_sandbox: 1 in CEF settingsmain.rs:664Renderer processes run without OS sandbox. Renderer compromise can access host filesystem and processes directly.Required for current platform support; documented limitation.
WS authkey in query stringserver/mod.rs:387-396auth_key in URLs, logs, Referer. Intentional WS-only exception (browser WS API cannot set custom headers).Restricted to /ws route only by the audit C3 fix.
AGENTMUX_AGENT_COLOR no value validationshell.rs:604; termosc.ts:263-269Shell profile can inject arbitrary CSS color value into block meta → UI rendering with unvalidated color value. Root cause of Win11 focus-border regression.No validation added as of 0.44.1.

Document generated by AgentY (sweep 2026-06-12). Sources verified by direct code reads; no features invented.