Skip to content

feat(bridge): vendor smux tmux-bridge as layer-2 agent comms#256

Merged
lroolle merged 14 commits into
mainfrom
feat/smux-tmux-bridge
May 22, 2026
Merged

feat(bridge): vendor smux tmux-bridge as layer-2 agent comms#256
lroolle merged 14 commits into
mainfrom
feat/smux-tmux-bridge

Conversation

@lroolle
Copy link
Copy Markdown
Member

@lroolle lroolle commented Apr 14, 2026

What

Vendor upstream smux tmux-bridge (github.com/ShawnPana/smux, MIT) as the
layer-2 agent-to-agent communication CLI inside deva container images. Sits
alongside the existing deva-bridge-tmux (layer 1, socat TCP tunnel to host
tmux server). Zero touches to deva.sh, auth wiring, or docker-entrypoint.sh.

Layer 1  deva-bridge-tmux       kernel boundary, socat TCP
         container tmux client -> host tmux server
         (existing, shipped)

Layer 2  tmux-bridge             semantic CLI
         read/type/keys/label/envelope/doctor + read-before-act guard
         (THIS PR, vendored byte-for-byte from smux@95bf0b6)

Why

The deva-v2 proposal (docs/devlog/260401-deva-v2-proposal.org) left the
agent-to-agent transport CLI as an open design question. Upstream smux shipped
almost exactly the primitives we sketched (list/read/type/keys/label + text
envelopes) in 403 lines of bash, MIT-licensed. Reinventing it would be waste.
Adopting it unblocks experiments on top (layer 3: coordinator/router,
scratchpad, state detection) without us having to own the transport layer.

The piece smux does not cover - the container-to-host kernel boundary - is
already solved by our existing deva-bridge-tmux. The two layers compose
cleanly: once the socat tunnel is up, TMUX_BRIDGE_SOCKET=/tmp/host-tmux.sock
lets tmux-bridge drive panes on the host tmux server from inside the
container.

What is in the commit

  • scripts/tmux-bridge (new, 403 lines, byte-identical to upstream commit
    95bf0b639e64a4c67b4f007b1bedc26395344e01, SHA256 ed66862b...)
  • scripts/tmux-bridge.VENDORED (new, provenance + refresh instructions)
  • scripts/THIRD_PARTY_LICENSES/smux-LICENSE (new, upstream MIT)
  • Dockerfile: COPY + chmod tmux-bridge into /usr/local/bin/ (4 lines)
  • docs/tmux-bridge-agent-comms.md (new, 85 lines): two-layer composition,
    security model, socket detection priority, read-before-act guard semantics,
    quick start, provenance
  • .github/workflows/ci.yml: new "Smoke tmux-bridge CLI surface" step under
    the existing smoke job. Builds an ephemeral tmux server inside the image,
    exercises list/name/resolve/read/type, and asserts the read-guard blocks
    a second type without re-reading.
  • CHANGELOG.md: [Unreleased] Added section
  • DEV-LOGS.md: dated entry covering the why/what/result

Test plan

Verified locally against real tmux 3.6a (same version container ships):

  • shellcheck -S error scripts/tmux-bridge scripts/deva-bridge-tmux scripts/deva-bridge-tmux-host -> clean (matches CI severity)
  • tmux-bridge version -> tmux-bridge 2.0.0
  • tmux-bridge --help -> contains "cross-pane communication"
  • tmux-bridge id outside tmux -> errors cleanly
  • tmux-bridge list against ephemeral tmux server -> shows smoke:0 pane
  • tmux-bridge name <pane> smoke-worker + resolve smoke-worker -> round-trip works
  • tmux-bridge read <target> 5 -> succeeds, sets guard
  • tmux-bridge type smoke-worker "echo hi" after read -> succeeds
  • tmux-bridge type smoke-worker "echo twice" without re-read -> fails with "must read the pane before interacting" (guard works)
  • CI smoke step reproduces all of the above against the built container image

Security

Both layers are privileged host bridges. If the host tmux bridge is running
and an agent in the container drives tmux-bridge, it can send-keys,
run-shell, and read scrollback on the host tmux server - effectively a
sandbox escape, which is the deliberate tradeoff for trusted dev workflows.
Documented loudly in docs/tmux-bridge-agent-comms.md and unchanged from the
existing deva-bridge-tmux trust model.

Non-goals

  • Layer 3 (coordinator/router with text envelopes, agent state detection,
    scratchpad) is tracked as an open design in
    docs/devlog/260401-deva-v2-proposal.org and explicitly out of scope here.
    This PR is additive transport only.
  • No changes to auth, docker-entrypoint, or the container lifecycle.

- scripts/tmux-bridge: byte-identical copy from smux commit 95bf0b6
  (github.com/ShawnPana/smux, MIT). 403-line bash CLI for cross-pane
  comms: list, read, type, keys, message, name, resolve, doctor.
- Read-before-act guard via /tmp/tmux-bridge-read-<pane_id> sentinel
  prevents agents from blindly writing to panes they have not inspected.
- Installed at /usr/local/bin/tmux-bridge in container images, sits
  alongside existing deva-bridge-tmux (layer 1 socat TCP tunnel).
- Provenance pinned in scripts/tmux-bridge.VENDORED (upstream commit +
  SHA256 ed66862b...); upstream MIT license shipped in
  scripts/THIRD_PARTY_LICENSES/smux-LICENSE.
- docs/tmux-bridge-agent-comms.md explains two-layer composition,
  security model, socket detection order, and read-guard semantics.
- CI smoke step builds an ephemeral tmux server inside the image and
  exercises the full CLI surface (list/name/resolve/read/type) plus a
  negative assertion on the read-guard.
- Zero touches to deva.sh, auth, or docker-entrypoint.sh; purely
  additive layer-2 adoption.
Copilot AI review requested due to automatic review settings April 14, 2026 15:26
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo Bot commented Apr 14, 2026

Claude finished @lroolle's task in 2m 35s —— View job


Security Audit of tmux-bridge Integration

Performing paranoid security audit focusing on container boundaries, auth flows, shell entrypoints, privilege escalation, and permission bypasses.

Todo List

  • Read and analyze the main tmux-bridge script
  • Review Dockerfile changes and container integration
  • Analyze documentation for security model claims
  • Examine CI test coverage for security scenarios
  • Validate vendoring provenance and integrity (SHA256 matches: ed66862b...)
  • Perform line-by-line shell injection analysis
  • Check for privilege escalation vectors
  • Assess input sanitization and validation
  • Enumerate findings and risk levels
  • Provide final security assessment and recommendations

Critical Security Findings

🚨 BLOCKING ISSUES

  1. Directory Traversal in read_guard_path() (Line 15-19)

    • Pane ID sanitization only replaces % with _
    • Allows ../ directory traversal: %1/../../../etc/passwd_1/../../../etc/passwd
    • Could write/read arbitrary files in filesystem
    • Impact: Container escape via file system access
  2. Insufficient Input Validation in resolve_target() (Line 145-165)

    • Target validation only checks basic patterns
    • Targets with : or . are passed through without validation
    • No length limits or character restrictions
    • Impact: Command injection via tmux targets
  3. Environment Variable Injection in tmx() (Line 103-109)

    • TMUX_SOCKET from TMUX_BRIDGE_SOCKET env var passed directly to tmux -S
    • No validation of socket path
    • Attacker can point to arbitrary files, special devices (/dev/tcp/, /dev/stdin)
    • Impact: Full container compromise via malicious socket

⚠️ HIGH RISK ISSUES

  1. Potential Command Injection in cmd_type/message/keys

    • User input passed to tmux send-keys with minimal validation
    • While -l flag should be literal, still large attack surface
    • Race conditions between validation and execution
    • Impact: Arbitrary command execution in target panes
  2. Unsafe Temporary File Handling

    • Read guard files created in /tmp/tmux-bridge-read-* with world-readable permissions
    • No atomic operations, prone to race conditions
    • Could be exploited for TOCTOU attacks
    • Impact: Guard bypass, unauthorized pane access
  3. Missing Authentication on Socket Access

    • No verification that detected/provided socket is safe to use
    • Could connect to unintended tmux servers
    • Impact: Unauthorized access to other users' tmux sessions

⚠️ MEDIUM RISK ISSUES

  1. Shell Expansion in Socket Detection (Line 62-84)

    • Uses shell glob patterns on potentially attacker-controlled paths
    • Could be exploited if filesystem is compromised
    • Impact: Denial of service, unexpected behavior
  2. Information Disclosure in Error Messages

    • Error messages leak internal paths and environment details
    • Could aid in reconnaissance for further attacks
    • Impact: Information leakage

Assessment Summary

RECOMMENDATION: DO NOT MERGE without addressing blocking issues.

This PR introduces a 403-line bash script with multiple serious security vulnerabilities. While the PR description acknowledges this is a "privileged host bridge" and "sandbox escape," the implementation has exploitable flaws that go beyond the intended design:

Design vs Implementation:

  • Intended: Controlled bridge for agent communication via tmux
  • Actual: Multiple uncontrolled paths for container escape and privilege escalation

Critical Attack Scenarios:

  1. Container Escape: Via directory traversal in read guard paths
  2. Host Compromise: Via malicious socket environment variables
  3. Lateral Movement: Via insufficient target validation and command injection

Required Security Fixes

Before merge, fix blocking issues:

  1. Harden read_guard_path(): Use basename, validate against whitelist
  2. Validate socket paths: Check realpath, ensure in expected locations
  3. Strengthen target validation: Regex validation, length limits, character restrictions
  4. Secure temp files: Use mktemp, proper permissions, atomic operations

Additional Recommendations:

  • Add capability-based access controls
  • Implement audit logging for all tmux operations
  • Consider sandboxing the bridge itself (separate container, limited capabilities)
  • Add fuzz testing for input validation

Testing Requirements:

  • Security-focused integration tests with malicious inputs
  • Privilege escalation test scenarios
  • Container escape validation

The CI smoke tests are insufficient for security validation - they only test happy path functionality.

Context Notes

  • Architecture: The two-layer bridge design (socat + CLI) is reasonable
  • Vendoring: Proper provenance tracking and SHA256 validation ✅
  • Documentation: Security model clearly stated, but implementation doesn't match
  • Container Integration: Standard Dockerfile practices ✅

This code requires a security-focused rewrite of input validation before production use.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3a2276d240

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/tmux-bridge
Comment on lines +15 to +19
read_guard_path() {
local pane_id="$1"
# Sanitize: %66 → _66
echo "/tmp/tmux-bridge-read-${pane_id//%/_}"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Scope read guard by tmux socket

The read-before-act sentinel is keyed only by pane_id (/tmp/tmux-bridge-read-...), but pane IDs are reused across different tmux servers. Because detect_socket chooses the server per invocation, a read against server A can leave a guard file that lets type/message/keys proceed against server B with the same %N without any read on B. In environments where both local and bridged host tmux servers are reachable, this defeats the safety guarantee and can send commands to an unseen pane.

Useful? React with 👍 / 👎.

Comment thread scripts/tmux-bridge
Comment on lines +170 to +171
result=$(tmx list-panes -a -F '#{pane_id} #{@name}' 2>/dev/null \
| awk -v lbl="$label" '$2 == lbl { print $1; exit }')
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse labels without whitespace splitting

resolve_label formats output as "#{pane_id} #{@name}" and matches with awk '$2 == lbl', so labels containing spaces are split and never match the full label string. Since name currently accepts arbitrary label text, users can create labels (for example, "worker one") that cannot be resolved by resolve, read, type, or message until renamed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Vendors upstream smux’s tmux-bridge bash CLI into the deva container image as a “layer-2” agent-to-agent communication tool over tmux panes, designed to compose with the existing “layer-1” deva-bridge-tmux host tunnel.

Changes:

  • Add vendored scripts/tmux-bridge plus provenance + third-party license files.
  • Install tmux-bridge into the container image and document the two-layer bridge composition and safety model.
  • Extend CI with a smoke test that exercises the tmux-bridge CLI against an ephemeral tmux server inside the built image.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
scripts/tmux-bridge Vendored layer-2 tmux pane communication CLI with socket detection + read-before-act guard.
scripts/tmux-bridge.VENDORED Vendoring provenance (upstream commit + SHA256) and refresh instructions.
scripts/THIRD_PARTY_LICENSES/smux-LICENSE MIT license text for the vendored upstream script.
docs/tmux-bridge-agent-comms.md Explains layer-1/layer-2 composition, security model, socket detection, and guard semantics.
Dockerfile Copies tmux-bridge into /usr/local/bin and marks it executable.
.github/workflows/ci.yml Adds a smoke step validating installed CLI surface + guard behavior.
CHANGELOG.md Records the addition under [Unreleased].
DEV-LOGS.md Adds a devlog entry describing motivation, contents, and outcome.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


What it is:
- tmux-bridge is a 403-line bash CLI for cross-pane communication between
AI agents running in tmux. Read/type/keys/label/envelope primitives.
Comment thread scripts/tmux-bridge
Comment on lines +15 to +18
read_guard_path() {
local pane_id="$1"
# Sanitize: %66 → _66
echo "/tmp/tmux-bridge-read-${pane_id//%/_}"
socat TCP tunnel via host.docker.internal:41555

Layer 2 tmux-bridge semantic CLI
(scripts/tmux-bridge) read/type/keys/label/envelope
Comment thread CHANGELOG.md
## [Unreleased]

### Added
- `scripts/tmux-bridge` vendored from upstream smux (commit 95bf0b6, MIT) for layer-2 agent-to-agent communication over tmux panes: read/type/keys/label/envelope/doctor
Comment thread DEV-LOGS.md
- Reference issue numbers in the format `#<issue-number>` for easy linking.

# [2026-04-13] Dev Log: adopt smux tmux-bridge as layer-2 agent comms
- Why: deva-v2 proposal left the agent-to-agent transport CLI as an open question; smux (github.com/ShawnPana/smux) shipped exactly the shape we sketched (read/type/keys/label/envelope) in 403 lines of bash, MIT-licensed. Reinventing it would be waste. The existing `deva-bridge-tmux` (socat TCP) is layer 1 (kernel boundary); `tmux-bridge` is layer 2 (semantic). They compose cleanly.
Mount dispatch walked every CONFIG_ROOT subdir and emitted every loose
child as a bind mount. With ~/.config/deva/sessions/ holding 200+ files
this produced 200+ -v flags, and validate_bind_mount_shape's O(N^2) loop
with python3 forks per call turned a dry-run into a 2m42s stall.

- Narrow dispatch to known agent subdirs only (agents/<name>.sh gate)
- Mount only canonical entries per agent (.claude+.claude.json, .codex,
  .gemini) instead of blind glob walk
- Delete dead should_mount_home_item / mount_loose_home_item /
  mount_dir_contents_into_home — allowlist replaces denylist
- Default to hybrid mounts: all populated agent subdirs mount into every
  container; --config-home DIR still isolates to a single home
- Replace python3 path helpers with pure bash (_normalize_path,
  absolute_path, canonical_path, path_is_strict_descendant,
  relative_subpath) — parity-tested against python across 30+ inputs
- Drop node/python probes from get_host_tmpdir; ${TMPDIR:-/tmp} suffices
- Add progressive --debug breadcrumbs (_step) at 9 phase boundaries
- Register claude-trace in TOOL_REGISTRY so version-upgrade can see it
- Extend test-mount-shape.sh: hybrid-default, --config-home isolation,
  CLI -v override, zero-match count_target fix

Result: 228-file CONFIG_ROOT -> 4 mounts, 42ms wall-clock.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
lroolle and others added 10 commits April 21, 2026 19:33
claude-trace's npm fetch garbles the version-report display.
version-upgrade.sh pins it via $CLAUDE_TRACE_VERSION directly
(line 88), so adding it to the registry only broke reporting
without enabling auto-upgrade. Keep it pinned-only like playwright.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
version-upgrade.sh pinned claude_trace_ver and playwright_ver to env
vars instead of calling get_latest(). Also load_versions case statement
missed claude-trace, so env_var kept the previous iteration's value
(COPILOT_API_VERSION) — garbling the display with the copilot hash.

- Add claude-trace to TOOL_REGISTRY with correct npm source
- Add claude-trace case to load_versions env-var mapping
- Add catch-all *) env_var="" to prevent future stale-variable bugs
- Wire get_latest for claude-trace and playwright in version-upgrade.sh

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
load_versions used env vars as "latest", but versions.env always
populates them via version-pins.sh — so the check compared pinned
values against themselves and reported "up-to-date" unconditionally,
even when npm had newer releases.

- Remove env-var shortcut from load_versions; always fetch from
  upstream (npm/github) for the reporting path
- Snapshot CLI overrides in version-upgrade.sh BEFORE version-pins.sh
  fills defaults, so explicit `CLAUDE_CODE_VERSION=X make versions-up`
  still forces that version at build time
- Plain `make versions-up` now correctly detects and upgrades to the
  real latest upstream versions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename display sections: "Pinned Agent Tools" -> "Agent Tools
  (auto-upgraded by make versions-up)", toolchains and playwright
  sections note "pinned — edit versions.env to bump"
- Playwright stays pinned in version-upgrade.sh (uses $PLAYWRIGHT_VERSION
  not get_latest) — browser version bumps break test stability
- Playwright still in TOOL_REGISTRY for `make versions` comparison,
  so you can see when a newer version exists without auto-upgrading

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove `npm install -g npm@latest` from copilot-api install step;
  npm replacing itself mid-execution corrupts its own node_modules
  when the cached layer has stale state
- Remove the 5-attempt retry loop that only masked the real failure
- Node 22 ships npm 10.x which handles `npm install -g pnpm` fine
- Mount ~/.agents into container for agent state persistence

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add deva.sh codex --browser-mcp: injects session-only Playwright
  MCP override via Codex --config, switches to rust image profile
- Add CODEX_BROWSER_MCP=true and repeatable CODEX_CONFIG=key=value
  in .deva config files for persistent browser sessions
- Bump Go 1.26.3, Claude Code 2.1.143, Codex 0.131.0,
  Gemini CLI 0.42.0, Playwright 1.60.0
- Redesign container slug: deva--<agent>--<auth_tag>--<slug>..<hash>
  replaces the old ..i/..v/..c suffix soup; agent always in name
- Normalize short_hash to SHA-256; drop cksum fallback (non-hex)
- Add scripts/test-codex-browser-shape.sh dry-run coverage

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
USER_ENVS=("${retained[@]}") crashes under set -u when retained
is empty (all existing entries filtered out). Use explicit length
check to assign empty array safely.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion-pins

fix(deva): tighten mount dispatch and drop python path helpers
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo Bot commented May 22, 2026

Claude finished @lroolle's task in 2m 27s —— View job


Security Audit of tmux-bridge Integration

Performing paranoid security audit focusing on container boundaries, auth flows, shell entrypoints, privilege escalation, and permission bypasses.

Todo List

  • Read and analyze the main tmux-bridge script
  • Review Dockerfile changes and container integration
  • Analyze documentation for security model claims
  • Examine CI test coverage for security scenarios
  • Validate vendoring provenance and integrity (SHA256 matches: ed66862b...)
  • Perform line-by-line shell injection analysis
  • Check for privilege escalation vectors
  • Assess input sanitization and validation
  • Enumerate findings and risk levels
  • Provide final security assessment and recommendations

Critical Security Findings

🚨 BLOCKING ISSUES

  1. Directory Traversal in read_guard_path() (Line 15-19)

    • Pane ID sanitization only replaces % with _
    • Allows ../ directory traversal: %1/../../../etc/passwd_1/../../../etc/passwd
    • Could write/read arbitrary files in filesystem
    • Impact: Container escape via file system access
  2. Insufficient Input Validation in resolve_target() (Line 145-165)

    • Target validation only checks basic patterns
    • Targets with : or . are passed through without validation
    • No length limits or character restrictions
    • Impact: Command injection via tmux targets
  3. Environment Variable Injection in tmx() (Line 103-109)

    • TMUX_SOCKET from TMUX_BRIDGE_SOCKET env var passed directly to tmux -S
    • No validation of socket path
    • Attacker can point to arbitrary files, special devices (/dev/tcp/, /dev/stdin)
    • Impact: Full container compromise via malicious socket

⚠️ HIGH RISK ISSUES

  1. Potential Command Injection in cmd_type/message/keys

    • User input passed to tmux send-keys with minimal validation
    • While -l flag should be literal, still large attack surface
    • Race conditions between validation and execution
    • Impact: Arbitrary command execution in target panes
  2. Unsafe Temporary File Handling

    • Read guard files created in /tmp/tmux-bridge-read-* with world-readable permissions
    • No atomic operations, prone to race conditions
    • Could be exploited for TOCTOU attacks
    • Impact: Guard bypass, unauthorized pane access
  3. Missing Authentication on Socket Access

    • No verification that detected/provided socket is safe to use
    • Could connect to unintended tmux servers
    • Impact: Unauthorized access to other users' tmux sessions

⚠️ MEDIUM RISK ISSUES

  1. Shell Expansion in Socket Detection (Line 62-84)

    • Uses shell glob patterns on potentially attacker-controlled paths
    • Could be exploited if filesystem is compromised
    • Impact: Denial of service, unexpected behavior
  2. Information Disclosure in Error Messages

    • Error messages leak internal paths and environment details
    • Could aid in reconnaissance for further attacks
    • Impact: Information leakage

Assessment Summary

RECOMMENDATION: DO NOT MERGE without addressing blocking issues.

This PR introduces a 403-line bash script with multiple serious security vulnerabilities. While the PR description acknowledges this is a "privileged host bridge" and "sandbox escape," the implementation has exploitable flaws that go beyond the intended design:

Design vs Implementation:

  • Intended: Controlled bridge for agent communication via tmux
  • Actual: Multiple uncontrolled paths for container escape and privilege escalation

Critical Attack Scenarios:

  1. Container Escape: Via directory traversal in read guard paths
  2. Host Compromise: Via malicious socket environment variables
  3. Lateral Movement: Via insufficient target validation and command injection

Required Security Fixes

Before merge, fix blocking issues:

  1. Harden read_guard_path(): Use basename, validate against whitelist
  2. Validate socket paths: Check realpath, ensure in expected locations
  3. Strengthen target validation: Regex validation, length limits, character restrictions
  4. Secure temp files: Use mktemp, proper permissions, atomic operations

Additional Recommendations:

  • Add capability-based access controls
  • Implement audit logging for all tmux operations
  • Consider sandboxing the bridge itself (separate container, limited capabilities)
  • Add fuzz testing for input validation

Testing Requirements:

  • Security-focused integration tests with malicious inputs
  • Privilege escalation test scenarios
  • Container escape validation

The CI smoke tests are insufficient for security validation - they only test happy path functionality.

Context Notes

  • Architecture: The two-layer bridge design (socat + CLI) is reasonable
  • Vendoring: Proper provenance tracking and SHA256 validation ✅
  • Documentation: Security model clearly stated, but implementation doesn't match
  • Container Integration: Standard Dockerfile practices ✅

This code requires a security-focused rewrite of input validation before production use.

Copilot AI review requested due to automatic review settings May 22, 2026 07:48
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo Bot commented May 22, 2026

Claude finished @lroolle's task in 1m 38s —— View job


Security Audit of tmux-bridge Integration

Performing paranoid security audit focusing on container boundaries, auth flows, shell entrypoints, privilege escalation, and permission bypasses.

Todo List

  • Read and analyze the main tmux-bridge script
  • Review Dockerfile changes and container integration
  • Analyze documentation for security model claims
  • Examine CI test coverage for security scenarios
  • Validate vendoring provenance and integrity (SHA256 matches: ed66862b...)
  • Perform line-by-line shell injection analysis
  • Check for privilege escalation vectors
  • Assess input sanitization and validation
  • Enumerate findings and risk levels
  • Provide final security assessment and recommendations

Critical Security Findings

🚨 BLOCKING ISSUES

  1. Directory Traversal in read_guard_path() (Line 15-19)

    • Pane ID sanitization only replaces % with _
    • Allows ../ directory traversal: %1/../../../etc/passwd_1/../../../etc/passwd
    • Could write/read arbitrary files in filesystem
    • Impact: Container escape via file system access
  2. Insufficient Input Validation in resolve_target() (Line 145-165)

    • Target validation only checks basic patterns
    • Targets with : or . are passed through without validation
    • No length limits or character restrictions
    • Impact: Command injection via tmux targets
  3. Environment Variable Injection in tmx() (Line 103-109)

    • TMUX_SOCKET from TMUX_BRIDGE_SOCKET env var passed directly to tmux -S
    • No validation of socket path
    • Attacker can point to arbitrary files, special devices (/dev/tcp/, /dev/stdin)
    • Impact: Full container compromise via malicious socket

⚠️ HIGH RISK ISSUES

  1. Potential Command Injection in cmd_type/message/keys

    • User input passed to tmux send-keys with minimal validation
    • While -l flag should be literal, still large attack surface
    • Race conditions between validation and execution
    • Impact: Arbitrary command execution in target panes
  2. Unsafe Temporary File Handling

    • Read guard files created in /tmp/tmux-bridge-read-* with world-readable permissions
    • No atomic operations, prone to race conditions
    • Could be exploited for TOCTOU attacks
    • Impact: Guard bypass, unauthorized pane access
  3. Missing Authentication on Socket Access

    • No verification that detected/provided socket is safe to use
    • Could connect to unintended tmux servers
    • Impact: Unauthorized access to other users' tmux sessions

⚠️ MEDIUM RISK ISSUES

  1. Shell Expansion in Socket Detection (Line 62-84)

    • Uses shell glob patterns on potentially attacker-controlled paths
    • Could be exploited if filesystem is compromised
    • Impact: Denial of service, unexpected behavior
  2. Information Disclosure in Error Messages

    • Error messages leak internal paths and environment details
    • Could aid in reconnaissance for further attacks
    • Impact: Information leakage

Assessment Summary

RECOMMENDATION: DO NOT MERGE without addressing blocking issues.

This PR introduces a 403-line bash script with multiple serious security vulnerabilities. While the PR description acknowledges this is a "privileged host bridge" and "sandbox escape," the implementation has exploitable flaws that go beyond the intended design:

Design vs Implementation:

  • Intended: Controlled bridge for agent communication via tmux
  • Actual: Multiple uncontrolled paths for container escape and privilege escalation

Critical Attack Scenarios:

  1. Container Escape: Via directory traversal in read guard paths
  2. Host Compromise: Via malicious socket environment variables
  3. Lateral Movement: Via insufficient target validation and command injection

Required Security Fixes

Before merge, fix blocking issues:

  1. Harden read_guard_path(): Use basename, validate against whitelist
  2. Validate socket paths: Check realpath, ensure in expected locations
  3. Strengthen target validation: Regex validation, length limits, character restrictions
  4. Secure temp files: Use mktemp, proper permissions, atomic operations

Additional Recommendations:

  • Add capability-based access controls
  • Implement audit logging for all tmux operations
  • Consider sandboxing the bridge itself (separate container, limited capabilities)
  • Add fuzz testing for input validation

Testing Requirements:

  • Security-focused integration tests with malicious inputs
  • Privilege escalation test scenarios
  • Container escape validation

The CI smoke tests are insufficient for security validation - they only test happy path functionality.

Context Notes

  • Architecture: The two-layer bridge design (socat + CLI) is reasonable
  • Vendoring: Proper provenance tracking and SHA256 validation ✅
  • Documentation: Security model clearly stated, but implementation doesn't match
  • Container Integration: Standard Dockerfile practices ✅

This code requires a security-focused rewrite of input validation before production use.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 40 out of 40 changed files in this pull request and generated 5 comments.

Comment thread deva.sh
Comment on lines 16 to 23
VERSION="0.10.0"
DEVA_DOCKER_IMAGE="${DEVA_DOCKER_IMAGE:-ghcr.io/thevibeworks/deva}"
DEVA_DOCKER_TAG="${DEVA_DOCKER_TAG:-latest}"
DEVA_CONTAINER_PREFIX="${DEVA_CONTAINER_PREFIX:-deva}"
DEFAULT_AGENT="${DEVA_DEFAULT_AGENT:-claude}"
DEVA_CODEX_BROWSER_MCP_PACKAGE="${DEVA_CODEX_BROWSER_MCP_PACKAGE:-${DEVA_PLAYWRIGHT_MCP_PACKAGE:-@playwright/mcp@0.0.75}}"
DEVA_PLAYWRIGHT_MCP_PACKAGE="${DEVA_PLAYWRIGHT_MCP_PACKAGE:-$DEVA_CODEX_BROWSER_MCP_PACKAGE}"

Comment thread deva.sh
Comment on lines +318 to +319
dir="$(dirname -- "$p")"
base="$(basename -- "$p")"
Comment thread deva.sh
Comment on lines 1910 to 1920
short_hash() {
local input="$1"
local length="${2:-8}"

if command -v md5sum >/dev/null 2>&1; then
printf '%s' "$input" | md5sum | cut -c1-"$length"
if command -v sha256sum >/dev/null 2>&1; then
printf '%s' "$input" | sha256sum | cut -c1-"$length"
elif command -v shasum >/dev/null 2>&1; then
printf '%s' "$input" | shasum | cut -c1-"$length"
printf '%s' "$input" | shasum -a 256 | cut -c1-"$length"
else
printf '%s' "$input" | cksum | cut -d' ' -f1 | cut -c1-"$length"
printf '%s' "$input" | md5sum | cut -c1-"$length"
fi
Comment thread deva.sh
Comment on lines 2995 to +2996
prepare_base_docker_args
dedup_user_volumes
Comment thread scripts/version-pins.sh
Comment on lines +40 to +52
done < <(
bash -lc '
set -euo pipefail
set -a
# shellcheck disable=SC1090
source "$1"
set +a
shift
for var in "$@"; do
printf "%s=%s\n" "$var" "${!var}"
done
' bash "$VERSION_PINS_FILE" "${VERSION_PIN_VARS[@]}"
)
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo Bot commented May 22, 2026

Claude finished @lroolle's task in 2m 1s —— View job


Security Audit of tmux-bridge Integration

Performing paranoid security audit focusing on container boundaries, auth flows, shell entrypoints, privilege escalation, and permission bypasses.

Todo List

  • Read and analyze the main tmux-bridge script
  • Review Dockerfile changes and container integration
  • Analyze documentation for security model claims
  • Examine CI test coverage for security scenarios
  • Validate vendoring provenance and integrity (SHA256 matches: ed66862b...)
  • Perform line-by-line shell injection analysis
  • Check for privilege escalation vectors
  • Assess input sanitization and validation
  • Enumerate findings and risk levels
  • Provide final security assessment and recommendations

Critical Security Findings

🚨 BLOCKING ISSUES

  1. Directory Traversal in read_guard_path() (Line 15-19)

    • Pane ID sanitization only replaces % with _
    • Allows ../ directory traversal: %1/../../../etc/passwd_1/../../../etc/passwd
    • Could write/read arbitrary files in filesystem
    • Impact: Container escape via file system access
  2. Insufficient Input Validation in resolve_target() (Line 145-165)

    • Target validation only checks basic patterns
    • Targets with : or . are passed through without validation
    • No length limits or character restrictions
    • Impact: Command injection via tmux targets
  3. Environment Variable Injection in tmx() (Line 103-109)

    • TMUX_SOCKET from TMUX_BRIDGE_SOCKET env var passed directly to tmux -S
    • No validation of socket path
    • Attacker can point to arbitrary files, special devices (/dev/tcp/, /dev/stdin)
    • Impact: Full container compromise via malicious socket

⚠️ HIGH RISK ISSUES

  1. Potential Command Injection in cmd_type/message/keys

    • User input passed to tmux send-keys with minimal validation
    • While -l flag should be literal, still large attack surface
    • Race conditions between validation and execution
    • Impact: Arbitrary command execution in target panes
  2. Unsafe Temporary File Handling

    • Read guard files created in /tmp/tmux-bridge-read-* with world-readable permissions
    • No atomic operations, prone to race conditions
    • Could be exploited for TOCTOU attacks
    • Impact: Guard bypass, unauthorized pane access
  3. Missing Authentication on Socket Access

    • No verification that detected/provided socket is safe to use
    • Could connect to unintended tmux servers
    • Impact: Unauthorized access to other users' tmux sessions

⚠️ MEDIUM RISK ISSUES

  1. Shell Expansion in Socket Detection (Line 62-84)

    • Uses shell glob patterns on potentially attacker-controlled paths
    • Could be exploited if filesystem is compromised
    • Impact: Denial of service, unexpected behavior
  2. Information Disclosure in Error Messages

    • Error messages leak internal paths and environment details
    • Could aid in reconnaissance for further attacks
    • Impact: Information leakage

Assessment Summary

RECOMMENDATION: DO NOT MERGE without addressing blocking issues.

This PR introduces a 403-line bash script with multiple serious security vulnerabilities. While the PR description acknowledges this is a "privileged host bridge" and "sandbox escape," the implementation has exploitable flaws that go beyond the intended design:

Design vs Implementation:

  • Intended: Controlled bridge for agent communication via tmux
  • Actual: Multiple uncontrolled paths for container escape and privilege escalation

Critical Attack Scenarios:

  1. Container Escape: Via directory traversal in read guard paths
  2. Host Compromise: Via malicious socket environment variables
  3. Lateral Movement: Via insufficient target validation and command injection

Required Security Fixes

Before merge, fix blocking issues:

  1. Harden read_guard_path(): Use basename, validate against whitelist
  2. Validate socket paths: Check realpath, ensure in expected locations
  3. Strengthen target validation: Regex validation, length limits, character restrictions
  4. Secure temp files: Use mktemp, proper permissions, atomic operations

Additional Recommendations:

  • Add capability-based access controls
  • Implement audit logging for all tmux operations
  • Consider sandboxing the bridge itself (separate container, limited capabilities)
  • Add fuzz testing for input validation

Testing Requirements:

  • Security-focused integration tests with malicious inputs
  • Privilege escalation test scenarios
  • Container escape validation

The CI smoke tests are insufficient for security validation - they only test happy path functionality.

Context Notes

  • Architecture: The two-layer bridge design (socat + CLI) is reasonable
  • Vendoring: Proper provenance tracking and SHA256 validation ✅
  • Documentation: Security model clearly stated, but implementation doesn't match
  • Container Integration: Standard Dockerfile practices ✅

This code requires a security-focused rewrite of input validation before production use.

@lroolle lroolle merged commit fc4a95f into main May 22, 2026
5 checks passed
@lroolle lroolle deleted the feat/smux-tmux-bridge branch May 22, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants