mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-11 03:13:24 +00:00
fix(docker): restore base capabilities in sandbox overlay (#523)
Sandbox overlay's cap_add replaces (not merges) the base compose, dropping SETUID, SETGID, CHOWN. This causes credential copy to fail with Permission denied when combining sandbox + claude-cli overlays. Changes: - Re-include base capabilities in sandbox overlay's cap_add - Use umask 077 for atomic permission-safe credential copy - Add ENABLE_CLAUDE_CLI build arg to pre-install Claude CLI in image - Add runtime warning when credentials mounted but CLI binary missing - Add WITH_CLAUDE_CLI to Makefile for overlay consistency - Add security warning comment for sandbox overlay attack surface
This commit is contained in:
1 parent
0cfe5800ca
commit
6bfad07ed8
6 files changed
+38
-6
No files matched your search
@@ -13,5 +13,9 @@ POSTGRES_PASSWORD=
|
||||
# Docker Compose auto-builds this from POSTGRES_USER/PASSWORD/DB.
|
||||
# GOCLAW_POSTGRES_DSN=postgres://user:pass@host:5432/dbname?sslmode=disable
|
||||
|
||||
# --- Sandbox (only when using docker-compose.sandbox.yml) ---
|
||||
# Docker socket GID: 999 on Linux, 0 on Windows/macOS Docker Desktop.
|
||||
# DOCKER_GID=0
|
||||
|
||||
# --- Debug ---
|
||||
# GOCLAW_TRACE_VERBOSE=1
|
||||
+6
-1
@@ -45,6 +45,7 @@ ARG ENABLE_SANDBOX=false
|
||||
ARG ENABLE_PYTHON=false
|
||||
ARG ENABLE_NODE=false
|
||||
ARG ENABLE_FULL_SKILLS=false
|
||||
ARG ENABLE_CLAUDE_CLI=false
|
||||
|
||||
# Install ca-certificates + wget (healthcheck) + optional runtimes.
|
||||
# ENABLE_FULL_SKILLS=true pre-installs all skill deps (larger image, no on-demand install needed).
|
||||
@@ -66,9 +67,13 @@ RUN set -eux; \
|
||||
apk add --no-cache python3 py3-pip; \
|
||||
pip3 install --no-cache-dir --break-system-packages edge-tts; \
|
||||
fi; \
|
||||
if [ "$ENABLE_NODE" = "true" ]; then \
|
||||
if [ "$ENABLE_NODE" = "true" ] || [ "$ENABLE_CLAUDE_CLI" = "true" ]; then \
|
||||
apk add --no-cache nodejs npm; \
|
||||
fi; \
|
||||
fi; \
|
||||
if [ "$ENABLE_CLAUDE_CLI" = "true" ]; then \
|
||||
npm install -g --cache /tmp/npm-cache @anthropic-ai/claude-code; \
|
||||
rm -rf /tmp/npm-cache; \
|
||||
fi
|
||||
|
||||
# Non-root user
|
||||
|
||||
@@ -33,6 +33,9 @@ endif
|
||||
ifdef WITH_REDIS
|
||||
COMPOSE_EXTRA += -f docker-compose.redis.yml
|
||||
endif
|
||||
ifdef WITH_CLAUDE_CLI
|
||||
COMPOSE_EXTRA += -f docker-compose.claude-cli.yml
|
||||
endif
|
||||
COMPOSE = $(COMPOSE_BASE) $(COMPOSE_EXTRA)
|
||||
UPGRADE = docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.upgrade.yml
|
||||
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
# Optional overlay: sync Claude CLI credentials from host into container.
|
||||
# Optional overlay: install Claude CLI and sync credentials from host into container.
|
||||
# Mounts host ~/.claude as read-only; entrypoint copies credentials to the data volume.
|
||||
# Adds ENABLE_CLAUDE_CLI build arg to install nodejs + @anthropic-ai/claude-code.
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.claude-cli.yml up -d
|
||||
# docker compose -f docker-compose.yml -f docker-compose.postgres.yml -f docker-compose.claude-cli.yml up -d --build
|
||||
|
||||
services:
|
||||
goclaw:
|
||||
build:
|
||||
args:
|
||||
ENABLE_CLAUDE_CLI: "true"
|
||||
volumes:
|
||||
- ${HOME}/.claude:/app/.claude-host:ro
|
||||
@@ -26,10 +26,16 @@ services:
|
||||
- GOCLAW_SANDBOX_CPUS=1.0
|
||||
- GOCLAW_SANDBOX_TIMEOUT_SEC=300
|
||||
- GOCLAW_SANDBOX_NETWORK=false
|
||||
# Override base cap_drop to allow Docker socket access
|
||||
# Override base cap_drop to allow Docker socket access.
|
||||
# Re-include base caps (SETUID/SETGID/CHOWN) lost when overriding cap_add.
|
||||
# WARNING: SETUID/SETGID with security_opt cleared (no no-new-privileges)
|
||||
# increases attack surface. Only use in trusted environments.
|
||||
cap_drop: []
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
- SETUID
|
||||
- SETGID
|
||||
- CHOWN
|
||||
security_opt: []
|
||||
group_add:
|
||||
- ${DOCKER_GID:-999}
|
||||
+12
-2
@@ -74,13 +74,23 @@ fi
|
||||
|
||||
# Copy Claude CLI credentials from root-owned read-only mount to goclaw-accessible location.
|
||||
# /app/.claude is a symlink → /app/data/.claude (writable volume, see Dockerfile).
|
||||
# Uses install(1) for atomic copy with correct ownership+permissions (no temp file needed).
|
||||
# Uses su-exec to copy as goclaw user because sandbox overlay's cap_add override
|
||||
# may remove CHOWN needed by install(1). umask 077 ensures file is created with 600.
|
||||
if [ -f /app/.claude-host/.credentials.json ]; then
|
||||
(mkdir -p /app/data/.claude \
|
||||
&& install -m 600 -o goclaw -g goclaw /app/.claude-host/.credentials.json /app/data/.claude/.credentials.json \
|
||||
&& if command -v su-exec >/dev/null 2>&1 && [ "$(id -u)" = "0" ]; then
|
||||
su-exec goclaw sh -c 'umask 077 && cp /app/.claude-host/.credentials.json /app/data/.claude/.credentials.json'
|
||||
else
|
||||
( umask 077 && cp /app/.claude-host/.credentials.json /app/data/.claude/.credentials.json )
|
||||
fi \
|
||||
&& echo "Claude CLI credentials synced from host.") || echo "WARNING: Claude credentials copy failed (non-fatal)"
|
||||
fi
|
||||
|
||||
# Warn if Claude credentials are mounted but CLI binary is missing (forgot --build).
|
||||
if [ -d /app/.claude-host ] && ! command -v claude >/dev/null 2>&1; then
|
||||
echo "WARNING: Claude credentials mounted but claude CLI not installed. Rebuild with: --build"
|
||||
fi
|
||||
|
||||
# Run command with privilege drop (su-exec in Docker, direct otherwise).
|
||||
run_as_goclaw() {
|
||||
if command -v su-exec >/dev/null 2>&1 && [ "$(id -u)" = "0" ]; then
|
||||
|
||||
Reference in new issue
Block a user