Skip to content

agent-container: root-owned gh-aw config files unreadable by chroot user on self-hosted runners; chmod before privilege drop in [Content truncated due to length] #1463

@lpcox

Description

@lpcox

Problem

On self-hosted runners where the GitHub Actions runner service runs as root, AWF drops privileges to the non-root host user (e.g., ec2-user, UID 1000) before executing the agent command. The following files are created by root after the runner user's pre-steps and are therefore not readable by the chroot user:

  • /tmp/gh-aw/mcp-config/config.toml ($GH_AW_MCP_CONFIG) — MCP server discovery config; without read access, the agent has no knowledge of add_comment/noop/other safe-output tools.
  • /opt/gh-aw/safeoutputs/outputs.jsonl ($GH_AW_SAFE_OUTPUTS) — Safe-output write target; without write access, tool calls produce no output.

The agent completes with exit code 0, but no comments, labels, or safe-output actions are posted to the PR. The "Process Safe Outputs" step reports Output file does not exist: /opt/gh-aw/safeoutputs/outputs.jsonl.

Context

Original report: github/gh-aw#21432

Confirmed:

  • Without AWF chroot (sandbox.agent: false): Codex runs as root, reads MCP config, posts comment — ✅ works.
  • With AWF chroot (v0.60.0+): Codex runs as ec2-user (UID 1000), cannot read root-owned files — ❌ fails silently.

On GitHub-hosted runners this is typically not an issue because the runner user owns /tmp and /opt.

Root Cause

In containers/agent/entrypoint.sh, the privilege drop via capsh --user=${HOST_USER} happens before the agent command runs, but the gh-aw setup steps (running as root on the host) create the MCP config and safe-outputs files after the Docker container is already started and chroot is prepared. The entrypoint does not chmod these paths.

The entrypoint already does similar ownership fixes for the agent home:

chown -R awfuser:awfuser /home/awfuser 2>/dev/null || true

The same pattern needs to be applied to gh-aw runtime files.

Proposed Solution

In containers/agent/entrypoint.sh, add a permission fix block after the DNS configuration section and before the capsh/chroot block. Insert approximately after line 430 (before privilege drop):

# Make gh-aw runtime files readable/writable by the chroot user.
# These files are created by root during workflow setup steps.
# Required for MCP tool discovery (config.toml) and safe-output writing (outputs.jsonl).
for gh_aw_dir in /host/tmp/gh-aw /host/opt/gh-aw/safeoutputs; do
  if [ -d "$gh_aw_dir" ]; then
    echo "[entrypoint] Setting permissions on $gh_aw_dir for chroot user (UID: ${HOST_UID})"
    chmod -R a+rX "$gh_aw_dir" 2>/dev/null || true
    # safeoutputs dir needs write access for the agent to record tool calls
    chmod -R a+rwX "$gh_aw_dir" 2>/dev/null || true
  fi
done
if [ -f /host/tmp/gh-aw/mcp-config/config.toml ]; then
  chmod a+r /host/tmp/gh-aw/mcp-config/config.toml 2>/dev/null || true
fi

Additionally, apply chmod a+rX recursively to the entire /host/tmp/gh-aw/ tree so that any other path-based configs added in the future are automatically accessible.

Add integration test in tests/ simulating a non-root chroot user reading /tmp/gh-aw/mcp-config/config.toml created by root, verifying the entrypoint permission fix resolves the EACCES error.

Generated by AWF Issue Auditor ·

Metadata

Metadata

Labels

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