From 49e7875e678fe9d1681202906b066570d6030c98 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 1 Feb 2026 17:42:29 +0000 Subject: [PATCH] Fix security: only expose auth vars to containers, not full .env Previously, the entire .env file was copied and mounted into containers, exposing all environment variables to the agent. Now only the specific authentication variables needed by Claude Code (CLAUDE_CODE_OAUTH_TOKEN and ANTHROPIC_API_KEY) are extracted and mounted. https://claude.ai/code/session_01Y6Az5oUPkYmJhA1N9MUd67 --- .claude/skills/debug/SKILL.md | 2 +- SPEC.md | 2 +- src/container-runner.ts | 25 +++++++++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/.claude/skills/debug/SKILL.md b/.claude/skills/debug/SKILL.md index 4b348be..68e18b2 100644 --- a/.claude/skills/debug/SKILL.md +++ b/.claude/skills/debug/SKILL.md @@ -82,7 +82,7 @@ cat .env # Should show one of: **Apple Container Bug:** Environment variables passed via `-e` are lost when using `-i` (interactive/piped stdin). -**Workaround:** The system mounts `.env` as a file and sources it inside the container. +**Workaround:** The system extracts only authentication variables (`CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_API_KEY`) from `.env` and mounts them for sourcing inside the container. Other env vars are not exposed. To verify env vars are reaching the container: ```bash diff --git a/SPEC.md b/SPEC.md index f0ca5a8..2668f0a 100644 --- a/SPEC.md +++ b/SPEC.md @@ -230,7 +230,7 @@ The token can be extracted from `~/.claude/.credentials.json` if you're logged i ANTHROPIC_API_KEY=sk-ant-api03-... ``` -The `.env` file is automatically mounted into the container at `/workspace/env-dir/env` and sourced by the entrypoint script. This workaround is needed because Apple Container loses `-e` environment variables when using `-i` (interactive mode with piped stdin). +Only the authentication variables (`CLAUDE_CODE_OAUTH_TOKEN` and `ANTHROPIC_API_KEY`) are extracted from `.env` and mounted into the container at `/workspace/env-dir/env`, then sourced by the entrypoint script. This ensures other environment variables in `.env` are not exposed to the agent. This workaround is needed because Apple Container loses `-e` environment variables when using `-i` (interactive mode with piped stdin). ### Changing the Assistant Name diff --git a/src/container-runner.ts b/src/container-runner.ts index 3c6c783..2802e85 100644 --- a/src/container-runner.ts +++ b/src/container-runner.ts @@ -111,16 +111,29 @@ function buildVolumeMounts(group: RegisteredGroup, isMain: boolean): VolumeMount }); // Environment file directory (workaround for Apple Container -i env var bug) + // Only expose specific auth variables needed by Claude Code, not the entire .env const envDir = path.join(DATA_DIR, 'env'); fs.mkdirSync(envDir, { recursive: true }); const envFile = path.join(projectRoot, '.env'); if (fs.existsSync(envFile)) { - fs.copyFileSync(envFile, path.join(envDir, 'env')); - mounts.push({ - hostPath: envDir, - containerPath: '/workspace/env-dir', - readonly: true - }); + const envContent = fs.readFileSync(envFile, 'utf-8'); + const allowedVars = ['CLAUDE_CODE_OAUTH_TOKEN', 'ANTHROPIC_API_KEY']; + const filteredLines = envContent + .split('\n') + .filter(line => { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith('#')) return false; + return allowedVars.some(v => trimmed.startsWith(`${v}=`)); + }); + + if (filteredLines.length > 0) { + fs.writeFileSync(path.join(envDir, 'env'), filteredLines.join('\n') + '\n'); + mounts.push({ + hostPath: envDir, + containerPath: '/workspace/env-dir', + readonly: true + }); + } } if (group.containerConfig?.additionalMounts) {