Skip to content

Safe-outputs PR creation fails: checkout manifest not mounted into containerized safe-outputs MCP server #40018

@dsyme

Description

@dsyme

Summary

Since the safe-outputs MCP server was moved into the gh-aw-node container (#39100), create_pull_request and push_to_pull_request_branch fail for cross-repo checkouts with:

Repository '<owner>/<repo>' not found in workspace.

The agent reasoning often misattributes this to the checked-out code being invisible, but the code is mounted. The real gap is that the checkout manifest the handlers depend on is not visible inside the container.

Root cause

findRepoCheckout is manifest-first by design because the safe-outputs MCP server runs credential-less in a container (see actions/setup/js/checkout_manifest.cjs). The manifest is the authoritative source for resolving a cross-repo checkout path + base branch without network/git access.

But the manifest path and the container mounts disagree:

  • Manifest is written to ${RUNNER_TEMP}/gh-aw/checkout-manifest.json
    (actions/setup/js/build_checkout_manifest.cjs, pkg/workflow/checkout_step_generator.go).
  • The safe-outputs container only mounts:
    • ${GITHUB_WORKSPACE} (code visible)
    • ${RUNNER_TEMP}/gh-aw/safeoutputs (only this subdir)
    • /tmp/gh-aw

${RUNNER_TEMP}/gh-aw/checkout-manifest.json is a sibling of the mounted safeoutputs/ dir, so it is not mounted.

Failure chain inside the container:

  1. lookupCheckout() reads the manifest → ENOENT → returns null.
  2. Falls back to the git scan; git config --get remote.origin.url is unreliable in the credential-less container (dubious-ownership / rewritten origin), so no match.
  3. Returns Repository '<owner>/<repo>' not found in workspace.

push_repo_memory showing "directory does not exist yet" is the same class of host/container path mismatch.

Observed in

A production run where every create_pull_request attempt failed identically (default target repo and explicit repo:), 13+ consecutive runs.

Fix (option 2: relocate the manifest)

Relocate the manifest under the already-mounted safeoutputs/ directory:

${RUNNER_TEMP}/gh-aw/safeoutputs/checkout-manifest.json

Both the writer (build_checkout_manifest.cjs) and the reader (checkout_manifest.cjs) resolve to the new default path; the GH_AW_CHECKOUT_MANIFEST override continues to work for tests/local dev.

Why this is safe

  • Manifest contents are non-sensitive: { repository, path, default_branch } only — no tokens/credentials.
  • No new agent exposure: the AWF firewall already mounts the entire ${RUNNER_TEMP}/gh-aw tree read-only into the agent, so the manifest is already visible to the agent today regardless of which subdir it lives in. Relocating only adds visibility to the safe-outputs MCP container that actually needs it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingmcp

    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