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_TOKEN
GH_AW_GITHUB_TOKEN
GH_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[] to WrapperConfig (src/types.ts)
- Merge into
EXCLUDED_ENV_VARS before the config.envAll loop (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_TOKENS env var passed to container
entrypoint.sh already reads this var — just needs to merge custom tokens into unset_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_VARS set
src/docker-manager.ts:517 — AWF_ONE_SHOT_TOKENS list
src/docker-manager.ts:596-603 — --env-all passthrough loop
containers/agent/entrypoint.sh:348-379 — unset_sensitive_tokens()
containers/agent/entrypoint.sh:674-689 — one-shot token sanitization flow
src/cli.ts:1263-1266 — --env flag definition
src/types.ts — WrapperConfig interface
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/environafter 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:But gh-aw workflows inject additional secrets that are NOT in this list:
GITHUB_MCP_SERVER_TOKENGH_AW_GITHUB_TOKENGH_AW_GITHUB_MCP_SERVER_TOKENThese tokens remain fully visible in the agent's environment for the entire run.
Gap 2: No
--exclude-envflagThere is no way for callers to exclude specific env vars from
--env-allpassthrough. The only exclusion mechanism is the hardcodedEXCLUDED_ENV_VARSset (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 viaenv,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(theAWF_ONE_SHOT_TOKENSenv var) andentrypoint.sh(theunset_sensitive_tokensfunction). There is no CLI flag to add custom tokens to the one-shot protection list.Attack Scenario
In a
pull_request_targetworkflow withbash: true, a prompt injection in PR content could instruct the agent to:env | grep TOKEN(succeeds if within the 5s window, or for unprotected tokens at any time)Proposed Solutions
1. Add
--exclude-envflag (high priority)Allow callers to exclude specific env vars from
--env-all:Implementation:
--exclude-env <name>repeatable option to CLI (src/cli.ts)excludeEnv?: string[]toWrapperConfig(src/types.ts)EXCLUDED_ENV_VARSbefore theconfig.envAllloop (docker-manager.ts:596)2. Add
--one-shot-tokensflag (high priority)Allow callers to extend the one-shot token protection list:
Implementation:
--one-shot-tokens <names>option to CLIAWF_ONE_SHOT_TOKENSenv var passed to containerentrypoint.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.shunset_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