-
Notifications
You must be signed in to change notification settings - Fork 18
Security: --env-all passes unprotected secrets; one-shot token list incomplete #1481
Description
Problem
When gh-aw invokes AWF with --env-all, all host environment variables — including secrets — are passed into the agent container. While AWF has a one-shot token mechanism that sanitizes known tokens from /proc/1/environ after agent startup, there are several gaps:
Upstream issue: github/gh-aw#23197
Gap 1: Incomplete one-shot token list
The one-shot token list (docker-manager.ts:517) covers:
COPILOT_GITHUB_TOKEN, GITHUB_TOKEN, GH_TOKEN, GITHUB_API_TOKEN,
GITHUB_PAT, GH_ACCESS_TOKEN, OPENAI_API_KEY, OPENAI_KEY,
ANTHROPIC_API_KEY, CLAUDE_API_KEY, CODEX_API_KEY
But gh-aw workflows inject additional secrets that are NOT in this list:
GITHUB_MCP_SERVER_TOKENGH_AW_GITHUB_TOKENGH_AW_GITHUB_MCP_SERVER_TOKEN
These tokens remain fully visible in the agent's environment for the entire run.
Gap 2: No --exclude-env flag
There is no way for callers to exclude specific env vars from --env-all passthrough. The only exclusion mechanism is the hardcoded EXCLUDED_ENV_VARS set (docker-manager.ts:467-492), which cannot be extended at runtime.
Gap 3: 5-second race window
The one-shot token mechanism waits 5 seconds (entrypoint.sh:682) for the agent to cache tokens via LD_PRELOAD before unsetting them. During this window, tokens are visible via env, printenv, or /proc/self/environ.
Gap 4: One-shot token list is not extensible
The list of tokens protected by one-shot sanitization is hardcoded in both docker-manager.ts (the AWF_ONE_SHOT_TOKENS env var) and entrypoint.sh (the unset_sensitive_tokens function). There is no CLI flag to add custom tokens to the one-shot protection list.
Attack Scenario
In a pull_request_target workflow with bash: true, a prompt injection in PR content could instruct the agent to:
- Run
env | grep TOKEN(succeeds if within the 5s window, or for unprotected tokens at any time) - Exfiltrate values via allowed channels (PR comments, repo-memory, allowed domains)
Proposed Solutions
1. Add --exclude-env flag (high priority)
Allow callers to exclude specific env vars from --env-all:
awf --env-all --exclude-env GITHUB_MCP_SERVER_TOKEN --exclude-env GH_AW_GITHUB_TOKEN -- ...Implementation:
- Add
--exclude-env <name>repeatable option to CLI (src/cli.ts) - Add
excludeEnv?: string[]toWrapperConfig(src/types.ts) - Merge into
EXCLUDED_ENV_VARSbefore theconfig.envAllloop (docker-manager.ts:596)
2. Add --one-shot-tokens flag (high priority)
Allow callers to extend the one-shot token protection list:
awf --env-all --one-shot-tokens GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN -- ...Implementation:
- Add
--one-shot-tokens <names>option to CLI - Append to
AWF_ONE_SHOT_TOKENSenv var passed to container entrypoint.shalready reads this var — just needs to merge custom tokens intounset_sensitive_tokens()
3. Expand default one-shot token list (medium priority)
Add commonly used gh-aw tokens to the default list in docker-manager.ts:517:
AWF_ONE_SHOT_TOKENS: 'COPILOT_GITHUB_TOKEN,GITHUB_TOKEN,GH_TOKEN,...,GITHUB_MCP_SERVER_TOKEN,GH_AW_GITHUB_TOKEN,GH_AW_GITHUB_MCP_SERVER_TOKEN'And mirror in entrypoint.sh unset_sensitive_tokens().
4. Reduce race window (low priority)
The 5-second sleep could be replaced with a readiness signal (e.g., the LD_PRELOAD library writes a ready file after caching tokens), but this is complex and the window is already small.
Relevant Files
src/docker-manager.ts:467-492—EXCLUDED_ENV_VARSsetsrc/docker-manager.ts:517—AWF_ONE_SHOT_TOKENSlistsrc/docker-manager.ts:596-603—--env-allpassthrough loopcontainers/agent/entrypoint.sh:348-379—unset_sensitive_tokens()containers/agent/entrypoint.sh:674-689— one-shot token sanitization flowsrc/cli.ts:1263-1266—--envflag definitionsrc/types.ts—WrapperConfiginterface