Skip to content

GH_HOST passthrough from proxy environment breaks gh pr checkout inside container #1492

@lpcox

Description

@lpcox

Problem

When gh-aw workflows run in a proxied / DIFC-style environment, the host sets GH_HOST to a local proxy hostname (e.g. localhost, 127.0.0.1, or a loopback proxy). AWF passes this proxy-rewritten GH_HOST into the agent container via --env-all, causing gh pr checkout to fail:

none of the git remotes configured for this repository correspond to the GH_HOST environment variable

The git remotes (set by actions/checkout) still reference the real GitHub host (github.com or a GHES instance), but gh refuses to operate because GH_HOST points at the proxy.

Upstream issue

github/gh-aw#23461

Root cause

In src/docker-manager.ts, the --env-all passthrough (line ~603) copies all host env vars (except EXCLUDED_ENV_VARS) into the container environment. GH_HOST is not in the excluded set (lines 467-477), so a proxy-rewritten GH_HOST flows through.

The auto-injection guard at line ~641 then preserves this bad value:

const ghHost = extractGhHostFromServerUrl(process.env.GITHUB_SERVER_URL);
if (ghHost && !environment.GH_HOST) {
  environment.GH_HOST = ghHost;  // skipped — GH_HOST already set by --env-all
}

Since --env-all already set GH_HOST to the proxy host, the !environment.GH_HOST guard prevents the correct value from being injected.

Impact

  • PR-triggered agent workflows fail before the agent even starts
  • Operators misdiagnose as permissions/token issues when the real cause is environment leakage
  • Affects any setup where a proxy rewrites GH_HOST before AWF runs (DIFC, integrity filtering, etc.)

Proposed fix

Option A: Always override GH_HOST from GITHUB_SERVER_URL (recommended)

Remove the !environment.GH_HOST guard so AWF always derives GH_HOST from the canonical GITHUB_SERVER_URL, regardless of what --env-all passed through:

// Always derive GH_HOST from GITHUB_SERVER_URL to prevent proxy-rewritten
// values from breaking gh CLI remote matching inside the container.
const ghHost = extractGhHostFromServerUrl(process.env.GITHUB_SERVER_URL);
if (ghHost) {
  environment.GH_HOST = ghHost;
  logger.debug(`Set GH_HOST=${ghHost} from GITHUB_SERVER_URL`);
}

GITHUB_SERVER_URL is set by the Actions runner and points to the real GitHub instance — it is never rewritten by proxies because it's injected by the runner itself, not inherited from the host shell.

For github.com, extractGhHostFromServerUrl returns null (no GH_HOST needed), so this only activates for GHES/GHEC. On github.com, we should also delete any proxy-rewritten GH_HOST that leaked through:

if (ghHost) {
  environment.GH_HOST = ghHost;
} else if (environment.GH_HOST) {
  // On github.com, GH_HOST should not be set. If --env-all passed through
  // a proxy-rewritten value, remove it so gh CLI uses its default (github.com).
  delete environment.GH_HOST;
  logger.debug("Removed proxy-rewritten GH_HOST (GITHUB_SERVER_URL targets github.com)");
}

Option B: Add GH_HOST to EXCLUDED_ENV_VARS

Add GH_HOST to the exclusion set so it is never passed through from the host:

const EXCLUDED_ENV_VARS = new Set([
  // ... existing entries ...
  'GH_HOST',  // Prevent proxy-rewritten GH_HOST from leaking; auto-injected from GITHUB_SERVER_URL
]);

This is simpler but less flexible — it blocks intentional GH_HOST overrides too.

Option C: Use --exclude-env (if implemented per #1481)

If --exclude-env lands, the gh-aw compiler could emit --exclude-env GH_HOST in generated workflows. This is the most flexible but requires changes in both repos.

Recommendation

Option A is the best approach because:

  • GITHUB_SERVER_URL is the canonical source of truth (injected by the runner, not the shell)
  • It handles both GHES/GHEC (override with correct value) and github.com (remove stale value)
  • No changes needed in gh-aw compiler — AWF self-heals regardless of what --env-all passes
  • Backward compatible: users who don't use proxies see no change

Additional considerations

  • GITHUB_API_URL and GITHUB_GRAPHQL_URL may also be proxy-rewritten. Consider deriving these from GITHUB_SERVER_URL as well, or adding them to EXCLUDED_ENV_VARS with auto-injection.
  • The same issue may affect GITHUB_SERVER_URL itself if the proxy rewrites it, though this is less common since the Actions runner sets it.

References

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