* feat: implement credential proxy for enhanced container environment isolation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review — bind proxy to loopback, scope OAuth injection, add tests - Bind credential proxy to 127.0.0.1 instead of 0.0.0.0 (security) - OAuth mode: only inject Authorization on token exchange endpoint - Add 5 integration tests for credential-proxy.ts - Remove dangling comment - Extract host gateway into container-runtime.ts abstraction - Update Apple Container skill for credential proxy compatibility Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: scope OAuth token injection by header presence instead of path Path-based matching missed auth probe requests the CLI sends before the token exchange. Now the proxy replaces Authorization only when the container actually sends one, leaving x-api-key-only requests (post-exchange) untouched. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: bind credential proxy to docker0 bridge IP on Linux On bare-metal Linux Docker, containers reach the host via the bridge IP (e.g. 172.17.0.1), not loopback. Detect the docker0 interface address via os.networkInterfaces() and bind there instead of 0.0.0.0, so the proxy is reachable by containers but not exposed to the LAN. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: bind credential proxy to loopback on WSL WSL uses Docker Desktop with the same VM routing as macOS, so 127.0.0.1 is correct and secure. Without this, the fallback to 0.0.0.0 was triggered because WSL has no docker0 interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: detect WSL via /proc instead of env var WSL_DISTRO_NAME isn't set under systemd. Use /proc/sys/fs/binfmt_misc/WSLInterop which is always present on WSL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
2.1 KiB
Docker
71 lines
2.1 KiB
Docker
# NanoClaw Agent Container
|
|
# Runs Claude Agent SDK in isolated Linux VM with browser automation
|
|
|
|
FROM node:22-slim
|
|
|
|
# Install system dependencies for Chromium
|
|
RUN apt-get update && apt-get install -y \
|
|
chromium \
|
|
fonts-liberation \
|
|
fonts-noto-cjk \
|
|
fonts-noto-color-emoji \
|
|
libgbm1 \
|
|
libnss3 \
|
|
libatk-bridge2.0-0 \
|
|
libgtk-3-0 \
|
|
libx11-xcb1 \
|
|
libxcomposite1 \
|
|
libxdamage1 \
|
|
libxrandr2 \
|
|
libasound2 \
|
|
libpangocairo-1.0-0 \
|
|
libcups2 \
|
|
libdrm2 \
|
|
libxshmfence1 \
|
|
curl \
|
|
git \
|
|
&& rm -rf /var/lib/apt/lists/*
|
|
|
|
# Set Chromium path for agent-browser
|
|
ENV AGENT_BROWSER_EXECUTABLE_PATH=/usr/bin/chromium
|
|
ENV PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium
|
|
|
|
# Install agent-browser and claude-code globally
|
|
RUN npm install -g agent-browser @anthropic-ai/claude-code
|
|
|
|
# Create app directory
|
|
WORKDIR /app
|
|
|
|
# Copy package files first for better caching
|
|
COPY agent-runner/package*.json ./
|
|
|
|
# Install dependencies
|
|
RUN npm install
|
|
|
|
# Copy source code
|
|
COPY agent-runner/ ./
|
|
|
|
# Build TypeScript
|
|
RUN npm run build
|
|
|
|
# Create workspace directories
|
|
RUN mkdir -p /workspace/group /workspace/global /workspace/extra /workspace/ipc/messages /workspace/ipc/tasks /workspace/ipc/input
|
|
|
|
# Create entrypoint script
|
|
# Container input (prompt, group info) is passed via stdin JSON.
|
|
# Credentials are injected by the host's credential proxy — never passed here.
|
|
# Follow-up messages arrive via IPC files in /workspace/ipc/input/
|
|
RUN printf '#!/bin/bash\nset -e\ncd /app && npx tsc --outDir /tmp/dist 2>&1 >&2\nln -s /app/node_modules /tmp/dist/node_modules\nchmod -R a-w /tmp/dist\ncat > /tmp/input.json\nnode /tmp/dist/index.js < /tmp/input.json\n' > /app/entrypoint.sh && chmod +x /app/entrypoint.sh
|
|
|
|
# Set ownership to node user (non-root) for writable directories
|
|
RUN chown -R node:node /workspace && chmod 777 /home/node
|
|
|
|
# Switch to non-root user (required for --dangerously-skip-permissions)
|
|
USER node
|
|
|
|
# Set working directory to group workspace
|
|
WORKDIR /workspace/group
|
|
|
|
# Entry point reads JSON from stdin, outputs JSON to stdout
|
|
ENTRYPOINT ["/app/entrypoint.sh"]
|