8000
Skip to content

MCP safe-output tools not accessible to Codex in AWF chroot on self-hosted runners (file permission issue) #21432

@Rubyj

Description

@Rubyj

Bug: MCP safe-output tools not invoked when Codex runs inside AWF chroot on self-hosted runners

Summary

When using the Codex engine with the AWF sandbox enabled on self-hosted runners running as root, Codex never invokes MCP safe-output tools (add_comment, add_labels, noop). The workflow completes successfully with exit code 0 but no comment or label is posted to the PR.

Evidence

  • gh-aw v0.58.0 + sandbox.agent: false (no AWF chroot): Codex runs as root on the host → reads MCP config → c 8000 alls add_commentworks correctly
  • gh-aw v0.60.0 + sandbox enabled (AWF chroot): Codex runs as ec2-user (UID 1000) inside chroot → can't read root-owned MCP config → MCP tools invisible → no tool calls → no output

Root Cause

The AWF chroot drops privileges to a non-root host user (e.g. ec2-user, UID 1000) before executing Codex. However, the following files are created by root during compiler-generated setup steps and are not readable by the chroot user:

  1. /tmp/gh-aw/mcp-config/config.toml (GH_AW_MCP_CONFIG) — Codex reads this to discover MCP servers. When unreadable, Codex has no knowledge of add_comment/add_labels/noop tools and falls back to built-in tools only (exec_command, file reads, etc.).

  2. /opt/gh-aw/safeoutputs/outputs.jsonl (GH_AW_SAFE_OUTPUTS) — Even if Codex could call tools, the output file path is under root-owned /opt/gh-aw/.

These files are created after any user-defined steps: run (e.g. Write Safe Outputs Config, Start Safe Outputs MCP HTTP Server), so workflow-level chmod workarounds cannot fix them.

The MCP gateway tools/list responses seen in gateway logs come from the gateway's own startup (running as root on the host), not from Codex inside the chroot. Codex inside the chroot never connects to the MCP gateway because it cannot read the config file.

Why This Only Affects Self-Hosted Runners

On GitHub-hosted runners, the runner user has broader filesystem permissions. On self-hosted runners configured to run as root (common pattern for AWS EC2 runners), the AWF chroot drops to a non-root user that cannot read root-owned files under /tmp/gh-aw/ and /opt/gh-aw/.

Observed Symptoms

# MCP gateway ingestion step:
Error reading agent output file: ENOENT: no such file or directory, open '/tmp/gh-aw/agent_output.json'
No agent output available - nothing to process

# Safe outputs step:
Output file does not exist: /opt/gh-aw/safeoutputs/outputs.jsonl
No agent output available - nothing to process

Workflow job exits with code 0 (success) but the conclusion job logs:

No no-op message found, skipping

Agentic Implementation Plan

File to modify: containers/agent/entrypoint.sh

Before the capsh --user=${HOST_USER} privilege drop, add a chmod to make gh-aw files accessible to the chroot user. Insert after the DNS configuration section (~line 430) and before the chroot /host /bin/bash -c "..." block:

# Ensure gh-aw temp files are accessible by the chroot user (UID: )
# These files are created by root during setup steps and must be readable
# by the non-root chroot user for MCP config discovery and safe-output writing.
echo "[entrypoint] Setting gh-aw directory permissions for chroot user..."
chmod -R a+rX /host/tmp/gh-aw 2>/dev/null || true
chmod -R a+rwX /host/tmp/gh-aw/mcp-config 2>/dev/null || true
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true

This mirrors how the entrypoint already handles awfuser home directory ownership:

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

Tests to add in src/docker-manager.test.ts or a new integration test:

  • Verify that a workflow using Codex engine on a self-hosted runner (simulated with a non-root chroot user) can invoke MCP safe-output tools after the permission fix

Environment

  • gh-aw CLI: v0.60.0
  • AWF: v0.24.2
  • Engine: codex (@openai/codex v0.115.0)
  • Model: gpt-5.3-codex (via internal OpenAI-compatible LLM router using --openai-api-target)
  • Runner: Self-hosted (Amazon Linux 2023), runner service runs as root, AWF chroot drops to ec2-user (UID 1000)

Related

Metadata

Metadata

Assignees

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

    0