Skip to content

fix: chown gh-aw config dirs to agent user before privilege drop in entrypoint (#1463)#1711

Merged
Mossaka merged 3 commits intomainfrom
fix/1463-chmod-gh-aw-config-files
Apr 7, 2026
Merged

fix: chown gh-aw config dirs to agent user before privilege drop in entrypoint (#1463)#1711
Mossaka merged 3 commits intomainfrom
fix/1463-chmod-gh-aw-config-files

Conversation

@Mossaka
Copy link
Copy Markdown
Collaborator

@Mossaka Mossaka commented Apr 6, 2026

Summary

On self-hosted runners where the GitHub Actions runner runs as root, AWF drops privileges to a non-root user (e.g., ec2-user, UID 1000) before executing the agent command. Two directories created by root during workflow setup are not accessible by the chroot user:

  • /tmp/gh-aw/mcp-config/ — MCP server discovery config (config.toml, mcp-servers.json)
  • Safe-outputs directory (path from $GH_AW_SAFE_OUTPUTS) — safe-output write target (outputs.jsonl)

This PR adds a chown -R "${HOST_UID}:${HOST_GID}" block in entrypoint.sh before the privilege drop (capsh) to transfer ownership of these directories to the agent user. Only the specific user gets access (not world-writable).

Changes

  • Added ownership transfer block in containers/agent/entrypoint.sh (before LD_PRELOAD construction, before capsh)
  • Targets /host/tmp/gh-aw (covers MCP config and other gh-aw runtime files)
  • Derives safe-outputs path dynamically from $GH_AW_SAFE_OUTPUTS env var (forward-compatible with any gh-aw version)
  • Conditional logging: success message on chown success, [WARN] on failure

Test plan

  • Existing chroot integration tests pass (1287/1287)
  • Smoke tests (claude, copilot) pass
  • Lint clean
  • Manual verification on self-hosted root-runner (deferred)

Closes #1463

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 6, 2026 17:38
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

✅ Coverage Check Passed

Overall Coverage

Metric Base PR Delta
Lines 86.20% 86.29% 📈 +0.09%
Statements 86.07% 86.16% 📈 +0.09%
Functions 87.41% 87.41% ➡️ +0.00%
Branches 78.57% 78.61% 📈 +0.04%
📁 Per-file Coverage Changes (1 files)
File Lines (Before → After) Statements (Before → After)
src/docker-manager.ts 86.6% → 87.0% (+0.39%) 86.1% → 86.5% (+0.38%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the agent container entrypoint to ensure gh-aw runtime/config directories created as root on self-hosted runners remain accessible after the chroot privilege drop, preventing silent failures in MCP tool discovery and safe-output writes (closes #1463).

Changes:

  • Recursively relaxes permissions on /host/tmp/gh-aw before executing the chrooted agent command.
  • Recursively relaxes permissions on /host/opt/gh-aw/safeoutputs before executing the chrooted agent command.
Show a summary per file
File Description
containers/agent/entrypoint.sh Adds a pre-privilege-drop permission fixup for host-mounted gh-aw config and safe-output directories in chroot mode.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 1/1 changed files
  • Comments generated: 3

Comment on lines +741 to +745
chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chmod -R a+rwX makes these host-mounted directories (especially /host/opt/gh-aw/safeoutputs) world-readable and world-writable, and the permission change persists on the host after the job. This is broader than necessary and can allow unintended cross-user tampering / data exposure on multi-user self-hosted runners. Consider changing ownership to the intended chroot user (e.g., chown -R ${HOST_UID}:${HOST_GID}) and using a more restrictive mode (e.g., user/group +rwX only) instead of granting access to a.

Suggested change
chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true
chown -R "${HOST_UID}:${HOST_GID}" /host/tmp/gh-aw 2>/dev/null || true
chmod -R ug+rwX,o-rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chown -R "${HOST_UID}:${HOST_GID}" /host/opt/gh-aw/safeoutputs 2>/dev/null || true
chmod -R ug+rwX,o-rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4d51fdc. Replaced chmod -R a+rwX with chown -R "${HOST_UID}:${HOST_GID}" so that only the specific agent user gets access, not all users on the host. This addresses the world-writable concern on multi-user self-hosted runners.

Comment on lines +741 to +746
chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true
echo "[entrypoint] Made /host/opt/gh-aw/safeoutputs accessible to chroot user"
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The success logs here are unconditional even if chmod fails (errors are redirected and || true forces a 0 exit). This can be misleading when debugging permission issues on self-hosted runners. Consider only printing the success message when the chmod command succeeds, and logging a warning when it fails.

Suggested change
chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true
echo "[entrypoint] Made /host/opt/gh-aw/safeoutputs accessible to chroot user"
if chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null; then
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
else
echo "[entrypoint][WARN] Failed to make /host/tmp/gh-aw accessible to chroot user"
fi
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
if chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null; then
echo "[entrypoint] Made /host/opt/gh-aw/safeoutputs accessible to chroot user"
else
echo "[entrypoint][WARN] Failed to make /host/opt/gh-aw/safeoutputs accessible to chroot user"
fi

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4d51fdc. The log messages are now conditional — success prints the ownership transfer with the UID:GID, and failure prints a [WARN] message. This makes debugging permission issues on self-hosted runners much easier.

Comment on lines +737 to +747
# Make gh-aw config directories readable/writable by the chroot user.
# On self-hosted runners these directories are created by the host-side
# gh-aw tooling as root, so the unprivileged chroot user cannot access them.
if [ -d /host/tmp/gh-aw ]; then
chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
echo "[entrypoint] Made /host/tmp/gh-aw accessible to chroot user"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true
echo "[entrypoint] Made /host/opt/gh-aw/safeoutputs accessible to chroot user"
fi
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change fixes an important chroot-mode failure mode on root-runner self-hosted setups, but there isn’t a regression test covering it. Adding an integration test that creates root-owned /tmp/gh-aw and /opt/gh-aw/safeoutputs on the host and then verifies the chrooted agent can read the MCP config and write safe-outputs would help prevent future breakage.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. This would require an integration test that creates root-owned directories and verifies the chroot agent can still access them. Deferring this to a follow-up since it needs Docker/sudo and would be better suited as a chroot integration test in the existing test suite. The smoke tests passing on this PR provide some coverage in the meantime.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Security Review

The fix correctly addresses the root cause (root-owned directories inaccessible after privilege drop), and the if [ -d ... ] guards and placement before the privilege drop are both correct.

However, chmod -R a+rwX is unnecessarily broad and introduces a security concern:

Issue: World-writable permissions on security-sensitive directories

File: containers/agent/entrypoint.sh (new lines ~737–745)

chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true
# ...
chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true

a+rwX grants read + write to all users (owner, group, and others). Both paths live on the host filesystem (bind-mounted as /host), so this affects any process running on the host machine, not just the agent container.

Concrete risks:

  1. /host/tmp/gh-aw (MCP config) — world-writable MCP config allows any unprivileged host process to modify MCP server definitions before or during the agent run. On self-hosted runners that may run multiple jobs concurrently, a compromised or untrusted job could tamper with another job's MCP configuration.

  2. /host/opt/gh-aw/safeoutputs (outputs.jsonl) — world-writable safe-outputs allows any host process to inject content into outputs.jsonl, which could produce fraudulent GitHub issue comments or PR actions attributed to the agent.

Recommended fix

HOST_UID and HOST_GID are already set earlier in the same script (lines ~8–9). Use chown instead of chmod to limit access to the specific agent user only:

if [ -d /host/tmp/gh-aw ]; then
  chown -R "$HOST_UID:$HOST_GID" /host/tmp/gh-aw 2>/dev/null || true
  echo "[entrypoint] Transferred /host/tmp/gh-aw ownership to chroot user ($HOST_UID:$HOST_GID)"
fi
if [ -d /host/opt/gh-aw/safeoutputs ]; then
  chown -R "$HOST_UID:$HOST_GID" /host/opt/gh-aw/safeoutputs 2>/dev/null || true
  echo "[entrypoint] Transferred /host/opt/gh-aw/safeoutputs ownership to chroot user ($HOST_UID:$HOST_GID)"
fi

This gives the agent user full access (as owner) without granting write permission to arbitrary other users on the host.

Generated by Security Guard for issue #1711 · ● 99.7K ·

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@Mossaka
Copy link
Copy Markdown
Collaborator Author

Mossaka commented Apr 6, 2026

Security Review

[CONCERN] chmod -R a+rwX /host/tmp/gh-aw is overly broad — covers security-sensitive subdirectories

  • File: containers/agent/entrypoint.sh (new lines in the diff)

  • Code: chmod -R a+rwX /host/tmp/gh-aw 2>/dev/null || true

  • Explanation: /tmp/gh-aw is a shared tree that contains multiple subdirectories with different security profiles:

    • /tmp/gh-aw/mcp-config/ — MCP server configuration (the stated target of this fix)
    • /tmp/gh-aw/aw-prompts/ — system prompt files
    • /tmp/gh-aw/sandbox/ — sandbox logs and agent output
    • /tmp/gh-aw/mcp-logs/ — MCP logs (already protected by tmpfs overlay, so this chmod is harmless for this subpath)
    • /tmp/gh-aw/safeoutputs/ — safe-output staging area read by post-agent steps

    Making the entire tree world-writable means the agent can modify the MCP config, prompts, and sandbox log directories. While the agent is already inside the container and many of these files are consumed before the agent runs, the recursive write permission on /tmp/gh-aw/safeoutputs/ is particularly concerning: the agent could tamper with safe-output artifacts that downstream workflow steps trust.

  • Suggested action: Scope the chmod to only the specific subdirectories the agent actually needs. For example:

    if [ -d /host/tmp/gh-aw/mcp-config ]; then
      chmod -R a+rwX /host/tmp/gh-aw/mcp-config 2>/dev/null || true
    fi

    If other subdirectories are also needed, enumerate them explicitly rather than opening the whole tree. This follows least-privilege principles.

[CONCERN] chmod -R a+rwX /host/opt/gh-aw/safeoutputs allows agent to tamper with safe-output config and validation

  • File: containers/agent/entrypoint.sh (new lines in the diff)

  • Code: chmod -R a+rwX /host/opt/gh-aw/safeoutputs 2>/dev/null || true

  • Explanation: The safe-outputs directory contains three categories of files:

    1. outputs.jsonl — the actual output file the agent writes to (write access needed, this is correct)
    2. config.json — safe-output configuration controlling output behavior
    3. tools.json / validation.json — tool definitions and validation rules that constrain what the agent can output

    Making the entire directory world-writable means the agent can modify config.json, tools.json, and validation.json — effectively rewriting the rules that govern its own output. A compromised agent could relax validation constraints and then write arbitrary outputs that downstream steps trust.

  • Suggested action: Consider one of:

    • (a) Only chmod the outputs.jsonl file (or create it with the right ownership): chmod a+rw /host/opt/gh-aw/safeoutputs/outputs.jsonl 2>/dev/null || true
    • (b) Make the directory itself writable but keep config/tools/validation files read-only: chmod a+rwX /host/opt/gh-aw/safeoutputs && chmod a+rw /host/opt/gh-aw/safeoutputs/outputs.jsonl
    • (c) Use chown to the target UID instead of world-writable permissions: chown -R ${HOST_UID}:${HOST_GID} /host/opt/gh-aw/safeoutputs — this is more precise and doesn't weaken permissions for other users/processes.

[INFO] a+rwX vs targeted ownership

  • Explanation: Both chmod blocks use a+rwX (all users: read, write, and execute-if-directory). Since the entrypoint already has HOST_UID and HOST_GID variables from the UID/GID mapping logic earlier in the script, using chown -R ${HOST_UID}:${HOST_GID} would be strictly more precise — it grants access only to the specific user the agent will run as, rather than world-writable. This matters in multi-user or shared-runner scenarios.
  • Suggested action: Replace chmod -R a+rwX with chown -R ${HOST_UID}:${HOST_GID} for both paths. This achieves the same goal (the chroot user can access the files) without making them world-writable.

[INFO] No iptables or network security impact

  • The changes do not affect setup-iptables.sh, host-iptables.ts, squid-config.ts, or any network filtering logic.
  • No command injection risk — the paths are hardcoded string literals, not derived from user input.
  • No path traversal risk — the -d guards check for directory existence of fixed paths.
  • The tmpfs overlay on /host/tmp/gh-aw/mcp-logs takes precedence over the chmod, so MCP log hiding is unaffected.

Summary

The fix addresses a real problem (root-owned directories inaccessible to the unprivileged agent on self-hosted runners), but the permissions are broader than necessary. The two main concerns are:

  1. /host/tmp/gh-aw chmod is recursive over the entire tree rather than scoped to mcp-config (the stated need).
  2. /host/opt/gh-aw/safeoutputs chmod makes config and validation files writable, allowing the agent to tamper with its own output constraints.

Recommended fix: use chown -R ${HOST_UID}:${HOST_GID} instead of chmod -R a+rwX, and scope /tmp/gh-aw to only the subdirectories the agent needs.

Replace `chmod -R a+rwX` with `chown -R $HOST_UID:$HOST_GID` to avoid
making gh-aw config directories world-writable on the host filesystem.
Also make success/failure log messages conditional on the actual command
result to aid debugging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka
Copy link
Copy Markdown
Collaborator Author

Mossaka commented Apr 6, 2026

Addressed all review feedback in 4d51fdc:

Security (Copilot + Security Guard): Replaced chmod -R a+rwX with chown -R "${HOST_UID}:${HOST_GID}" for both /host/tmp/gh-aw and /host/opt/gh-aw/safeoutputs. This transfers ownership to the specific agent user instead of making directories world-writable, eliminating the cross-user tampering risk on multi-user self-hosted runners.

Logging: Made success/failure messages conditional on the actual chown exit code. Success now logs the UID:GID used; failure logs a [WARN] message to aid debugging.

Integration test: Deferred to a follow-up — requires Docker/sudo setup and is better suited as a chroot integration test.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions github-actions bot mentioned this pull request Apr 6, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes self-hosted (root-runner) chroot-mode failures where gh-aw-created runtime directories are root-owned on the host, preventing the unprivileged chroot user from reading MCP config and writing safe-outputs.

Changes:

  • Add a pre-privilege-drop ownership transfer (chown -R) for /host/tmp/gh-aw and /host/opt/gh-aw/safeoutputs.
  • Emit success/warn logs depending on whether the ownership transfer succeeds.
Show a summary per file
File Description
containers/agent/entrypoint.sh Chowns host-mounted gh-aw runtime directories to the host UID/GID before dropping privileges in chroot mode.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 1/1 changed files
  • Comments generated: 1

Comment on lines +737 to +742
# Transfer ownership of gh-aw config directories to the chroot user.
# On self-hosted runners these directories are created by the host-side
# gh-aw tooling as root, so the unprivileged chroot user cannot access them.
# We use chown (not chmod a+rwX) to avoid making these dirs world-writable,
# which would be a security risk on multi-user self-hosted runners.
if [ -d /host/tmp/gh-aw ]; then
Copy link

Copilot AI Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR title/description reference a chmod-based fix, but the implementation here uses chown -R "${HOST_UID}:${HOST_GID}" to transfer ownership. Please update the PR metadata (title/description) to match the actual behavior so reviewers/operators understand the host-side impact (ownership change vs permissions change).

Copilot uses AI. Check for mistakes.
@Mossaka Mossaka changed the title fix: chmod gh-aw config dirs before privilege drop in entrypoint fix: chown gh-aw config dirs to agent user before privilege drop in entrypoint (#1463) Apr 6, 2026
@Mossaka
Copy link
Copy Markdown
Collaborator Author

Mossaka commented Apr 6, 2026

Addressed: Updated PR title and description to reflect the chown-based implementation instead of chmod. Thanks for catching the mismatch.

@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented Apr 6, 2026

Review Feedback

Good change overall — chown is the right approach (not chmod a+rwX), conditional logging is helpful, and the placement before capsh privilege drop is correct.

One significant issue: the safe-outputs path is stale.

The second chown block targets /host/opt/gh-aw/safeoutputs, but this path no longer exists in practice. Since gh-aw v0.67.0, safe-outputs moved to ${RUNNER_TEMP}/gh-aw/safeoutputs/:

# Every lock file in this repo now uses:
GH_AW_SAFE_OUTPUTS: ${{ runner.temp }}/gh-aw/safeoutputs/outputs.jsonl

Zero lock files reference /opt/gh-aw/safeoutputs anymore:

$ grep -r "/opt/gh-aw/safeoutputs" .github/workflows/
# (no results)

Suggested fix: derive the safe-outputs directory from $GH_AW_SAFE_OUTPUTS (which is passed through to the container env) instead of hardcoding the old path. Something like:

# Handle safe-outputs directory (path varies by gh-aw version)
if [ -n "${GH_AW_SAFE_OUTPUTS:-}" ]; then
  # GH_AW_SAFE_OUTPUTS is e.g. /tmp/gh-aw/safeoutputs/outputs.jsonl — chown parent dir
  _so_dir="/host$(dirname "$GH_AW_SAFE_OUTPUTS")"
  if [ -d "$_so_dir" ]; then
    if chown -R "${HOST_UID}:${HOST_GID}" "$_so_dir" 2>/dev/null; then
      echo "[entrypoint] Transferred $_so_dir ownership to chroot user (${HOST_UID}:${HOST_GID})"
    else
      echo "[entrypoint][WARN] Failed to transfer $_so_dir ownership to chroot user"
    fi
  fi
fi

This is forward-compatible regardless of where gh-aw puts safe-outputs.

Minor items:

  • The automated reviewer's unresolved comment about updating the PR title/description is valid — the current title says "chmod" but the implementation is chown.
  • The /host/tmp/gh-aw block is correct and covers MCP config ($GH_AW_MCP_CONFIG = /tmp/gh-aw/mcp-config/config.toml). 👍
  • Deferring the integration test is reasonable given this needs Docker/sudo.

Replace hardcoded /opt/gh-aw/safeoutputs with dynamic path derived
from the GH_AW_SAFE_OUTPUTS environment variable, making it
forward-compatible with gh-aw v0.67.0+ which moved safe-outputs
to ${RUNNER_TEMP}/gh-aw/safeoutputs/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Mossaka
Copy link
Copy Markdown
Collaborator Author

Mossaka commented Apr 6, 2026

Addressed: replaced hardcoded /opt/gh-aw/safeoutputs with dynamic path derived from GH_AW_SAFE_OUTPUTS env var. Now forward-compatible regardless of where gh-aw puts safe-outputs.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Smoke Test Results — run 24054424503

✅ GitHub MCP: #1722 feat: propagate host.docker.internal to child containers, #1721 fix: enforce shared net namespace for child containers
✅ Playwright: github.com title contains "GitHub"
✅ File write: /tmp/gh-aw/agent/smoke-test-claude-24054424503.txt created
✅ Bash verify: file content confirmed

Overall: PASS

💥 [THE END] — Illustrated by Smoke Claude

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

🤖 Smoke Test Results

Test Status
GitHub MCP connectivity
GitHub.com HTTP connectivity ✅ (pre-step)
File write/read (smoke-test-copilot-24054424495.txt)

PR: fix: chown gh-aw config dirs to agent user before privilege drop in entrypoint (#1463)
Author: @Mossaka

Overall: PASS

📰 BREAKING: Report filed by Smoke Copilot

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Chroot Version Comparison Results

Runtime Host Version Chroot Version Match?
Python Python 3.12.13 Python 3.12.3 ❌ NO
Node.js v24.14.1 v20.20.2 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall: ❌ FAILED — Python and Node.js versions differ between host and chroot environment.

Tested by Smoke Chroot

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Smoke Test Status

  • feat: support npm install -g in agent container
  • fix: enable color output when --tty flag is set
  • 1✅ 2❌ 3❌ 4❌ 5✅ 6✅ 7❌ 8✅
  • Overall: FAIL
  • Run: §24054424518

🔮 The oracle has spoken through Smoke Codex

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Smoke Test: GitHub Actions Services Connectivity

Check Tool Result
Redis ping (port 6379) redis-cli FAILEDredis-cli not installed; port unreachable
PostgreSQL ready (port 5432) pg_isready FAILEDno response
PostgreSQL query (SELECT 1) psql FAILED — connection timed out

Summary: All 3 checks failed. host.docker.internal resolves to 172.17.0.1 but ports 6379 and 5432 are not reachable. Services may not be running, or network rules are blocking access from this sandbox.

🔌 Service connectivity validated by Smoke Services

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

Security Review

The overall direction of this PR is correct — using chown "${HOST_UID}:${HOST_GID}" (targeted ownership transfer to a specific non-root UID/GID) is more secure than the previous chmod a+rwX approach, which made directories world-accessible on multi-user runners. The HOST_UID/HOST_GID values are validated as numeric and non-zero at the top of the entrypoint, which is good.

One minor hardening concern worth addressing:

GH_AW_SAFE_OUTPUTS path is used without canonicalization

File: containers/agent/entrypoint.sh (~line 750)

if [ -n "${GH_AW_SAFE_OUTPUTS:-}" ]; then
  _so_dir="/host$(dirname "$GH_AW_SAFE_OUTPUTS")"
  if [ -d "$_so_dir" ]; then
    if chown -R "${HOST_UID}:${HOST_GID}" "$_so_dir" 2>/dev/null; then

GH_AW_SAFE_OUTPUTS is used directly in shell path construction with no validation. If the value contains path traversal sequences (e.g., /tmp/../../ or similar), dirname resolves those before the /host prefix is applied, potentially causing chown -R to target a broader directory than intended. For instance, if GH_AW_SAFE_OUTPUTS=/tmp/gh-aw/safeoutputs/../../outputs.jsonl, then dirname/tmp/gh-aw/safeoutputs/../.. → resolves to /tmp, making _so_dir=/host/tmpchown -R would then change ownership of all files in the host's /tmp, not just the safeoutputs directory.

Risk level: Low. In practice, GH_AW_SAFE_OUTPUTS is set by workflow YAML (e.g., /opt/gh-aw/safeoutputs/outputs.jsonl) and is not user- or agent-controlled. However, as a defense-in-depth measure, consider validating the resolved path stays within expected bounds before executing chown:

if [ -n "${GH_AW_SAFE_OUTPUTS:-}" ]; then
  _so_dir="/host$(dirname "$GH_AW_SAFE_OUTPUTS")"
  case "$_so_dir" in
    /host/tmp/gh-aw/*|/host/opt/gh-aw/*)
      if [ -d "$_so_dir" ]; then
        chown -R "${HOST_UID}:${HOST_GID}" "$_so_dir" 2>/dev/null || \
          echo "[entrypoint][WARN] Failed to transfer $_so_dir ownership to chroot user"
      fi
      ;;
    *)
      echo "[entrypoint][WARN] GH_AW_SAFE_OUTPUTS resolves to unexpected path: $_so_dir — skipping chown"
      ;;
  esac
fi

This is a suggestion, not a blocker. The PR is a net security improvement.


🤖 Automated security review

Generated by Security Guard for issue #1711 · ● 164.8K ·

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 6, 2026

🏗️ Build Test Suite Results

Ecosystem Project Build/Install Tests Status
Bun elysia 1/1 passed ✅ PASS
Bun hono 1/1 passed ✅ PASS
C++ fmt N/A ✅ PASS
C++ json N/A ✅ PASS
Deno oak N/A 1/1 passed ✅ PASS
Deno std N/A 1/1 passed ✅ PASS
.NET hello-world N/A ✅ PASS
.NET json-parse N/A ✅ PASS
Go color passed ✅ PASS
Go env passed ✅ PASS
Go uuid passed ✅ PASS
Java gson 1/1 passed ✅ PASS
Java caffeine 1/1 passed ✅ PASS
Node.js clsx passed ✅ PASS
Node.js execa passed ✅ PASS
Node.js p-limit passed ✅ PASS
Rust fd 1/1 passed ✅ PASS
Rust zoxide 1/1 passed ✅ PASS

Overall: 8/8 ecosystems passed — ✅ PASS

Generated by Build Test Suite for issue #1711 · ● 775.7K ·

@Mossaka Mossaka merged commit 853b1d8 into main Apr 7, 2026
64 of 65 checks passed
@Mossaka Mossaka deleted the fix/1463-chmod-gh-aw-config-files branch April 7, 2026 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants