Skip to content

[awf] agent/entrypoint: E2BIG when prompt+envp exceed ARG_MAX with --env-all and large inlined prompts #1965

@lpcox

Description

@lpcox

Problem

When the AWF sandbox is used with --env-all and a compiled workflow that inlines large prompt content (e.g., many imports: or inlined-imports: true), the agent step fails with:

/bin/bash: line 1: /usr/local/bin/node: Argument list too long

Exit code 126. The Linux kernel rejects the execve() call before node can even start. Two factors combine to exceed ARG_MAX (~2 MB):

  1. Shell-expanded --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" — compiled lock files pass the entire prompt as a single argv[] element. With inlined-imports: true and 10+ imported skill/reference files, this can reach 100–200 KB.
  2. --env-all env passthrough — AWF's --env-all flag forwards the complete GitHub Actions runner environment (~1.5–2 MB of GITHUB_*, tool-cache, matrix, and runner variables) into the container's envp[].

The failure manifests in the agent container's execve() call inside containers/agent/entrypoint.sh.

Context

Original report: github/gh-aw#26045

Pattern visible in compiled lock files (e.g., .github/workflows/copilot-token-optimizer.lock.yml:678, .github/workflows/claude-token-usage-analyzer.lock.yml:666):

-- /bin/bash -c 'node \$\{RUNNER_TEMP}/gh-aw/actions/copilot_driver.cjs /usr/local/bin/copilot \
  --add-dir /tmp/gh-aw/ ... \
  --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"'  # ← shell expansion into argv

The GH_AW_PROMPT env var (/tmp/gh-aw/aw-prompts/prompt.txt) is already set in the container environment (see .github/workflows/smoke-claude.lock.yml:179), so the prompt file path is available — only the expansion pattern needs to change.

Root Cause

Two independent AWF-side contributions:

1. --env-all bloats envp[] (src/docker-manager.ts:790-855)

src/docker-manager.ts builds the Docker Compose environment block by iterating process.env when config.envAll is set. There is no size cap or filtering of large/non-essential variables. On GitHub-hosted runners the runner environment routinely exceeds 1 MB; combined with even a modest prompt, ARG_MAX is breached.

2. Compiled lock files use shell expansion into argv[]

The gh-aw compiler emits --prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)" for Copilot and Claude drivers. The shell expansion happens after execve() of /bin/bash, so bash itself starts, but the subsequent execve() of node (with the expanded prompt in argv) fails with E2BIG.

Proposed Solution

Primary fix (gh-aw compiler side, tracked here for AWF awareness)

Change compiled commands from:

--prompt "$(cat /tmp/gh-aw/aw-prompts/prompt.txt)"

to a file-based flag (if the driver supports it):

--prompt-file /tmp/gh-aw/aw-prompts/prompt.txt

or stdin pipe:

cat /tmp/gh-aw/aw-prompts/prompt.txt | node copilot_driver.cjs ... --prompt -

AWF-side mitigation: smarter --env-all filtering (src/docker-manager.ts:790-855)

Add size-based filtering when config.envAll is true:

  • Log a warning when a single env var value exceeds a configurable threshold (e.g., 64 KB)
  • Provide --max-env-value-size <bytes> option to drop oversized vars from passthrough (with a warning)
  • Consider excluding well-known large-but-agent-irrelevant vars by default (e.g., RUNNER_TOOL_CACHE, GITHUB_EVENT_PATH, long matrix vars)

This is a complementary fix — even if the prompt injection is resolved, a runner with an unusually large environment could still trigger E2BIG for other reasons.

Files to modify

File Change
src/docker-manager.ts:790-855 Add maxEnvValueSize filter in --env-all passthrough block
src/types.ts Add optional maxEnvValueSize?: number to WrapperConfig
src/cli.ts:1389-1395 Add --max-env-value-size <bytes> CLI option alongside --env-all
.github/workflows/*.lock.yml Re-compile after gh-aw compiler fix to remove $(cat ...) expansion (see scripts/ci/postprocess-smoke-workflows.ts)

Workaround

Reduce total imported content size in .md workflow files, or manually exclude large env vars with --exclude-env VAR_NAME (existing flag, src/cli.ts:1395).

Generated by Firewall Issue Dispatcher · ● 1.3M ·

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions