ControlFreak is security-sensitive because it observes and controls the Windows desktop.
The MCP can capture displays, regions, and windows; run local Windows OCR; retain up to sixteen short-lived visual baselines in memory; move/click/drag/scroll the pointer; focus existing windows; and inject keyboard input. Mouse clicks and drags are bounded atomic operations: the server does not expose raw button-down/button-up tools and attempts release cleanup after partial failures. The semantic text-click tool rejects zero or ambiguous OCR matches before injecting input. These are powerful local operations. Run it only for MCP clients you trust, and report suspected security problems privately through GitHub's security advisory interface instead of a public issue.
ControlFreak deliberately exposes no application-launch, shell, filesystem, clipboard, registry, network, or elevation tool. That is a tool-surface boundary rather than a security sandbox: keyboard input can still reach functionality exposed by an already-running desktop application.
The optional Windows setup program and its separate controlfreak-installer.exe utility edit only
the explicitly selected clients' MCP configuration. These are installation features, not MCP tools.
Setup creates private configuration backups alongside existing files; those backups may contain
credentials and are intentionally retained after uninstall. Backups preserve access permissions;
EFS-encrypted source configurations are refused before backup creation. Optional uninstall cleanup
retains data it cannot safely change and reports failed rollback as requiring backup recovery. The setup utility reports fixed error
messages rather than configuration contents. It never enables --allow-elevated in generated client
entries, starts a server, or changes the server's desktop-control checks. Run setup as the intended
non-elevated user so configuration changes apply to that user.
ControlFreak inherits the Windows access token of the MCP client that starts it. It never requests
elevation itself, but an elevated client would otherwise make ControlFreak elevated too. The server
therefore inspects its token before opening the MCP transport and refuses an elevated token by
default. The refusal is a JSON error on stderr with code elevated_operation_requires_opt_in.
Only start an elevated server when the task genuinely requires it:
controlfreak --allow-elevatedThis option is a deliberate trust decision for the whole server lifetime, not permission to cross
Windows integrity boundaries silently. Before every state-changing action, and again immediately
before each input batch, ControlFreak verifies the unlocked interactive Default input desktop and
the current target process integrity. A target above the server's integrity is refused with
higher_integrity_target; an unverifiable target is refused with target_integrity_unavailable.
UAC secure desktop, the lock screen, disconnected sessions, and non-default input desktops remain
blocked even when --allow-elevated is present.
Mutating sessions bind one server-issued opaque target reference. Each input batch validates that window's process creation time, ownership, desktop, foreground and integrity. Pointer batches also check the effective top-level window under the mapped point. References retain window bounds and display layout from observation; incompatible changes invalidate input. A bounded five-minute cache and Windows destroy-event watcher prevent raw HWND/PID reconstruction and retire destroyed-window references, including same-process handle reuse. Watcher failure refuses target resolution. Desktop-switch events retire existing references.
Focus acquisition uses only documented restoration and foreground APIs with a bounded retry budget. It validates on every poll and stops on competing foreground ownership. A mismatch invalidates session approval. Release-only cleanup remains permitted after earlier dispatch. These checks reduce OS races; out-of-context event notifications and input delivery are not atomic with validation. Post-action foreground evidence is a sample, not a continuous guarantee.
get_server_status and --print-capabilities report server_elevated, the Windows integrity level,
and whether elevated operation was explicitly allowed. Elevated mutation sessions replace the
standard blue glow and its bright core with red counterparts; all other indicator behavior and
styling remains unchanged. The capture-excluded indicator runs as a native Rust helper
mode of the same executable, without launching PowerShell or materializing executable scripts. A
per-helper Windows job object contains it when one can be created; if that fails the helper still
starts with cooperative cleanup only, and get_server_status reports whether containment is active.
Future platform capabilities must declare their permission requirements and preserve these explicit boundaries.
For transport diagnosis, the server emits process lifecycle plus tool name, operation ID, status,
and duration to stderr. These events deliberately exclude tool arguments, typed text, OCR contents,
window titles, screenshots, and image data. ControlFreak writes no diagnostics to disk by default.
Setting CONTROLFREAK_GLOW_ERROR_LOG opts into an append-only log at the given path, recording
indicator helper lifecycle, helper stderr, and error text. That log carries no desktop content.
A native navy session bar and physical Esc latch stop independently of MCP transport and provider progress. The bar is visible only while this server owns the desktop, including cleanup. A dedicated keyboard hook examines key identity and injection flags only to recognize physical Esc. It retains no typed values or keyboard history, ignores injected Esc, and consumes the stop key's press and release. Esc outside an owned session is passed through. A user-stop notification is sent over MCP and its reason remains available in status and refused actions. Clients may also stop all desktop work or cancel one request. No MCP call clears the stop latch. User-controlled server restart is the re-arming procedure, after draining and resolving any cleanup failure.
Cancellation is cooperative. An in-flight native call may finish after stop. Cleanup bypasses ordinary mutation admission but releases only acknowledged, unmatched owned inputs. It does not release every key named by a failed request. An existing held key or button is refused before new input dispatch. Unknown cleanup closes admission and retains the ownership lease and indicator. Status reports draining or cleanup failure without claiming to undo application effects. Stopping does not kill applications, lock Windows, or shut it down. The private OCR helper retains its pre-existing timeout and owned-process cleanup policy.