Skip to content

Conversation

@lroolle
Copy link
Collaborator

@lroolle lroolle commented Dec 2, 2025

  • 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

- 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
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.

Copilot finished reviewing on behalf of lroolle December 2, 2025 15:10
Copy link

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.
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