Security model
Objectives
Section titled “Objectives”The architecture is designed around a few explicit goals:
- Untrusted pane output must never gain local authority just because it appears inside a Honeymux UI surface.
- Remote-derived state must remain attributable to a specific host, pane, TTY, and process tree.
- Control-plane surfaces such as sockets, parser state, and permission-routing paths must stay private, bounded, and fail closed.
- Integration with tmux, SSH, and coding agents must preserve trust boundaries instead of flattening them.
Primary trust boundaries
Section titled “Primary trust boundaries”The important boundaries in Honeymux are not abstract. They are concrete interfaces where strings, events, or bytes move from one authority domain to another:
- Pane output into Honeymux rendering and UI state.
- tmux control-mode commands and format strings generated from local state, config, or remote metadata.
- Local runtime artifacts such as Unix sockets, state directories, and persisted session metadata.
- Remote mirror sessions and remote agent hooks projected back onto the local machine.
- Coding-agent permission events routed from hooks into Honeymux’s local approval UI.
The security model is built around making those crossings explicit and narrow. Honeymux does not assume that because something came from tmux, a terminal, or a remote server it is automatically safe to treat as local control-plane input.
Local containment and private runtime state
Section titled “Local containment and private runtime state”Honeymux keeps its own authority-bearing runtime artifacts private by default. Runtime directories and socket paths live under user-private runtime or state directories, are created with 0700 permissions, and reject unsafe socket names. Persisted session metadata is written as 0600 files.
That matters because Unix sockets and runtime files are not just cache entries. In Honeymux they can carry agent events, permission responses, and pane-proxy coordination. Treating them as private local control-plane surfaces is part of the security model, not just a filesystem hygiene detail.
Event provenance for agent hooks
Section titled “Event provenance for agent hooks”Agent events are not trusted based only on their JSON shape or self-reported pane metadata.
For local hooks, Honeymux validates that the reported PID actually belongs to the pane it claims. The PID must be on the expected TTY and must descend from the pane’s process tree. If that provenance check fails, the event is rejected.
For remote hooks, Honeymux applies a stricter two-step validation:
- The event’s reported TTY must resolve to a mirrored remote pane that is already bound to a specific local pane.
- Honeymux then validates on the remote host that the reported PID is genuinely bound to that remote pane’s TTY and process ancestry before it projects the event back onto a local pane.
This is the core reason Honeymux describes security as a provenance problem. An agent permission request is only meaningful if the system can show which pane and process tree actually produced it.
Permission handling and fail-closed behavior
Section titled “Permission handling and fail-closed behavior”Permission requests are held on live socket connections only for agents and routes that support programmatic allow or deny. Those connections are keyed to the active session or tool-use identity, and stale or superseded connections are torn down.
If an unanswered permission event fails validation, Honeymux denies it rather than leaving an uncertain approval path alive. If a permission socket disappears because the agent UI handled the request elsewhere, Honeymux synthesizes a cancellation event so the local unanswered state is cleared instead of lingering.
This is deliberate fail-closed behavior. A questionable permission path should end in rejection or cancellation, not in “maybe valid” state surviving in the background.
Remote panes and remote-to-local authority
Section titled “Remote panes and remote-to-local authority”Remote-pane support is one of the most sensitive parts of the design because it bridges SSH, a remote tmux instance, local pane state, and local UI surfaces.
When a local pane is converted to remote, Honeymux creates an explicit mapping between the local pane and a specific remote pane. The local proxy process must then register with the expected local pane ID and a fresh one-time token before queued or live remote output is delivered to it.
Remote agent hooks are also isolated per server rather than flowing through one ambient shared hook path. Honeymux forwards them through per-server ingress sockets and only associates them with a local pane after the remote TTY and PID binding checks succeed.
The intent is simple: remote traffic may be displayed locally, but it must not inherit local control-plane authority without a narrow, validated mapping.
Injection resistance at boundary crossings
Section titled “Injection resistance at boundary crossings”Several parts of Honeymux generate strings that cross into other parsers or command grammars. Those crossings are treated as security boundaries:
- SSH destinations are validated so a host string cannot be reinterpreted as additional SSH options.
- Remote shell argv is quoted for POSIX shell execution rather than concatenated naively.
- tmux control-mode arguments are quoted explicitly for tmux’s command grammar.
- tmux format literals are escaped so
#expansion markers and control characters cannot be interpreted as format expansion or control data when the string is meant to be literal text.
This is especially important because Honeymux often composes commands and labels from state that may ultimately be influenced by remote hosts, pane titles, session names, or config-derived strings.
Bounded parsers and stream handlers
Section titled “Bounded parsers and stream handlers”Long-lived parser state is an easy place for security bugs to hide, especially in systems that sit on continuous byte streams. Honeymux keeps these surfaces explicitly bounded:
- Hook socket input lines have a maximum size.
- Proxy registration messages have a maximum size.
- Pending proxy output is capped and keeps only the newest bytes.
- Captured SSH stderr is sanitized, truncated, and bounded.
If those buffers overflow their configured limits, the relevant connection or retained state is dropped rather than allowed to grow indefinitely. This is partly a robustness property, but it is also a security property: malformed or hostile input should not be able to turn the control plane into an unbounded memory sink or a desynchronized parser.
Scope and non-goals
Section titled “Scope and non-goals”Honeymux is explicit about what it does and does not promise.
- A compromised remote host is still a compromised remote host.
- Vulnerabilities that exist solely inside tmux, SSH, terminal emulators, or third-party coding agents are not automatically Honeymux vulnerabilities.
- Honeymux does not try to erase trust boundaries. It tries to preserve them, label them clearly, and avoid accidentally granting local authority to remote-derived data.
That last point is the practical summary of the model. Honeymux cannot make every component in a terminal workflow trustworthy. It can, however, make sure that when trust changes hands, it does so through explicit, narrow, and validated boundaries.
Screen captures powered by Honeyshots
Copyright © 2026 Aaron Campbell · Apache 2.0