Description
The session key authentication introduced in #5 was applied to the server (detached) mode but not to the TUI (interactive) mode. Any local process that can read ~/.psmux/*.port can connect to a TUI-mode session's TCP control port and execute commands without authentication.
Root Cause
In server mode (src/server/mod.rs), the accept loop generates a session key, writes it to a .key file, and passes it to connection::handle_connection(), which enforces AUTH <key> as the first line of every connection:
In TUI mode (src/app.rs), the accept loop reads the first line directly as a command. No session key is generated, no .key file is written, and no authentication check is performed:
Impact
Commands accepted without auth in TUI mode include new-window and split-window, both of which accept an arbitrary command argument that gets passed to create_window() → build_command() → spawn_command(). This allows any local process to execute arbitrary commands as the psmux user.
source-file is also accepted unauthenticated, which can load config files containing run-shell directives.
PoC (PowerShell)
# 1. Find the port file for any running TUI session
# (No .key file exists — TUI mode doesn't create one)
$portFile = Get-ChildItem "$env:USERPROFILE\.psmux\*.port" | Select-Object -First 1
$port = Get-Content $portFile
# 2. Send a command without authentication
$tcp = New-Object System.Net.Sockets.TcpClient("127.0.0.1", [int]$port)
$stream = $tcp.GetStream()
$writer = New-Object System.IO.StreamWriter($stream)
$writer.WriteLine('new-window "cmd /c calc.exe"')
$writer.Flush()
$tcp.Close()
Scope
The TCP listener is bound to 127.0.0.1, so this is a local-only attack surface. On single-user desktops the practical risk is limited. The concern is multi-user systems or environments with sandboxed/compromised processes that can make TCP connections and read the port file.
Suggested Fix
Apply the same authentication pattern from server/mod.rs to app.rs:
- Generate a session key in
app.rs (same logic as server/mod.rs:334-342)
- Write the key to
~/.psmux/<session>.key
- Route TCP connections through
connection::handle_connection() instead of inline command parsing
This would unify both code paths and ensure all TCP connections are authenticated regardless of the mode.
Additional Hardening Suggestion
Session names are used directly in file paths (types.rs:774, session.rs:93) without sanitization. A name containing ../ could write .port/.key files outside ~/.psmux/. Consider rejecting path separators and .. sequences in session names. (Low severity — requires local CLI access.)
Environment
- psmux v3.3.2 (commit
3bf380d)
- Windows 11 Pro (Build 26200)
- Audited on: 2026-04-12
Description
The session key authentication introduced in #5 was applied to the server (detached) mode but not to the TUI (interactive) mode. Any local process that can read
~/.psmux/*.portcan connect to a TUI-mode session's TCP control port and execute commands without authentication.Root Cause
In server mode (
src/server/mod.rs), the accept loop generates a session key, writes it to a.keyfile, and passes it toconnection::handle_connection(), which enforcesAUTH <key>as the first line of every connection:src/server/mod.rs:334-342src/server/connection.rs:38-57In TUI mode (
src/app.rs), the accept loop reads the first line directly as a command. No session key is generated, no.keyfile is written, and no authentication check is performed:src/app.rs:280-480Impact
Commands accepted without auth in TUI mode include
new-windowandsplit-window, both of which accept an arbitrary command argument that gets passed tocreate_window()→build_command()→spawn_command(). This allows any local process to execute arbitrary commands as the psmux user.source-fileis also accepted unauthenticated, which can load config files containingrun-shelldirectives.PoC (PowerShell)
Scope
The TCP listener is bound to
127.0.0.1, so this is a local-only attack surface. On single-user desktops the practical risk is limited. The concern is multi-user systems or environments with sandboxed/compromised processes that can make TCP connections and read the port file.Suggested Fix
Apply the same authentication pattern from
server/mod.rstoapp.rs:app.rs(same logic asserver/mod.rs:334-342)~/.psmux/<session>.keyconnection::handle_connection()instead of inline command parsingThis would unify both code paths and ensure all TCP connections are authenticated regardless of the mode.
Additional Hardening Suggestion
Session names are used directly in file paths (
types.rs:774,session.rs:93) without sanitization. A name containing../could write.port/.keyfiles outside~/.psmux/. Consider rejecting path separators and..sequences in session names. (Low severity — requires local CLI access.)Environment
3bf380d)