The entrypoint script (PID 1) in the agent container had sensitive tokens (GITHUB_TOKEN, OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) in its environment. While the one-shot-token library successfully cached these tokens in the agent process and cleared them from /proc/self/environ, the entrypoint's environment at /proc/1/environ still contained the tokens, making them accessible to malicious code.
Modified the entrypoint to unset all sensitive tokens from its own environment after the agent process has started and cached them. This is implemented in both chroot and non-chroot execution modes.
-
Added
unset_sensitive_tokens()function (entrypoint.sh:145-176)- Maintains a list of sensitive token environment variables
- Iterates through the list and unsets each token from the parent shell
- Logs which tokens were unset
-
Modified chroot mode execution (entrypoint.sh:449-468)
- Changed from
exec chroot ...tochroot ... &(run in background) - Added 5-second sleep to allow agent to initialize and cache tokens
- Call
unset_sensitive_tokens()to clear tokens from parent shell - Use
wait $AGENT_PIDto wait for agent completion - Exit with agent's exit code
- Changed from
-
Modified non-chroot mode execution (entrypoint.sh:484-499)
- Changed from
exec capsh ...tocapsh ... &(run in background) - Added 5-second sleep to allow agent to initialize and cache tokens
- Call
unset_sensitive_tokens()to clear tokens from parent shell - Use
wait $AGENT_PIDto wait for agent completion - Exit with agent's exit code
- Changed from
-
Updated one-shot-token library (one-shot-token/src/lib.rs:32-50)
- Added
GITHUB_PERSONAL_ACCESS_TOKENto default token list - Added
CLAUDE_CODE_OAUTH_TOKENto default token list - Now matches the list in entrypoint.sh
- Added
The following tokens are unset from the entrypoint's environment:
- GitHub tokens: COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN, GITHUB_API_TOKEN, GITHUB_PAT, GH_ACCESS_TOKEN, GITHUB_PERSONAL_ACCESS_TOKEN
- OpenAI tokens: OPENAI_API_KEY, OPENAI_KEY
- Anthropic/Claude tokens: ANTHROPIC_API_KEY, CLAUDE_API_KEY, CLAUDE_CODE_OAUTH_TOKEN
- Codex tokens: CODEX_API_KEY
- t=0s: Container starts, entrypoint receives tokens in environment
- t=0s: Entrypoint starts agent command in background
- t=0-5s: Agent initializes, reads tokens via getenv(), one-shot-token library caches them
- t=5s: Entrypoint calls
unset_sensitive_tokens(), clearing tokens from/proc/1/environ - t=5s+: Agent continues running with cached tokens,
/proc/1/environno longer contains tokens - t=end: Agent completes, entrypoint exits with agent's exit code
- Before: Tokens accessible via
/proc/1/environthroughout agent execution - After: Tokens accessible via
/proc/1/environonly for first 5 seconds, then cleared - Agent behavior: Unchanged - agent can still read tokens via getenv() (cached by one-shot-token library)
Integration test added at tests/integration/token-unset.test.ts:
- Verifies GITHUB_TOKEN cleared from
/proc/1/environafter agent starts - Verifies OPENAI_API_KEY cleared from
/proc/1/environafter agent starts - Verifies ANTHROPIC_API_KEY cleared from
/proc/1/environafter agent starts - Verifies multiple tokens cleared simultaneously
- Verifies behavior in both chroot and non-chroot modes
- Verifies agent can still read tokens via getenv() after unsetting
Manual test script at test-token-unset.sh:
- Can be run locally with
./test-token-unset.sh - Requires sudo and Docker
- Sets test tokens and verifies they are cleared from
/proc/1/environ
- The 5-second delay is necessary to give the agent process time to initialize and cache tokens via the one-shot-token library before the parent shell unsets them
- Both token lists (entrypoint.sh and one-shot-token library) must be kept in sync when adding new token types
- The exit code handling is preserved - the entrypoint exits with the agent's exit code