Skip to content

fix: events.jsonl not captured — chroot bind mount bypasses AWF workDir volume #1592

@lpcox

Description

@lpcox

Problem

Copilot CLI writes events.jsonl to ~/.copilot/session-state/<session-uuid>/events.jsonl, but the file is never captured in the AWF workDir and therefore never appears in workflow artifacts.

Root Cause

There are two competing volume mounts for ~/.copilot/session-state:

  1. Pre-chroot volume (line 777): ${workDir}/agent-session-state → ${HOME}/.copilot/session-state:rw
  2. Chroot bind mount (line 837): ${HOME}/.copilot → /host${HOME}/.copilot:rw

After chroot to /host, the Copilot CLI resolves ~/.copilot/session-state/ via the chroot bind mount (line 837), which maps directly to the host filesystem. The pre-chroot volume mount at line 777 is completely shadowed — events.jsonl is written to the host's ~/.copilot/session-state/ and never reaches the AWF workDir.

The same issue affects ~/.copilot/logs (line 775), but logs work because --log-dir /tmp/gh-aw/sandbox/agent/logs/ overrides the default path. No equivalent flag exists for session-state.

Security Concern

The blanket ~/.copilot chroot mount (line 837) exposes the entire ~/.copilot/ directory to the agent container read-write. While the current comment says "This is safe as ~/.copilot contains only Copilot CLI state, not credentials", the directory may contain configuration and cached auth state that should not be exposed to the sandboxed agent.

Proposed Fix

Replace the blanket ~/.copilot chroot bind mount with targeted mounts for only the subdirectories that need to be writable:

1. Remove the blanket mount (line 837)

- // Mount ~/.copilot for GitHub Copilot CLI (package extraction, config, logs)
- // This is safe as ~/.copilot contains only Copilot CLI state, not credentials
- agentVolumes.push(`${effectiveHome}/.copilot:/host${effectiveHome}/.copilot:rw`);

2. Add targeted chroot mounts for session-state and logs

// Mount AWF workDir session-state at chroot path so events.jsonl is captured
agentVolumes.push(`${config.workDir}/agent-session-state:/host${effectiveHome}/.copilot/session-state:rw`);

// Mount AWF workDir agent-logs at chroot path so logs are captured
agentVolumes.push(`${config.workDir}/agent-logs:/host${effectiveHome}/.copilot/logs:rw`);

Result

  • After chroot, ~/.copilot/session-state/ → AWF workDir (events.jsonl captured ✅)
  • After chroot, ~/.copilot/logs/ → AWF workDir (logs captured ✅)
  • ~/.copilot/ itself → empty writable dir from the empty home volume (line 828) — Copilot CLI can still create files but host's .copilot contents are NOT exposed (secure ✅)
  • The pre-chroot volume mounts (lines 775-777) remain for non-chroot mode compatibility

Testing

  • Run npm test to verify existing tests pass
  • Trigger a smoke-copilot run and verify events.jsonl appears in artifacts
  • Verify Copilot CLI still starts and runs correctly (package extraction works with empty ~/.copilot)

Related

  • See companion issue in github/gh-aw for the lock file copy step fix (flat glob misses session subdirectories)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    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