Skip to content

Artifact ZIP downloads always fail under sandbox: agent: awf with restricted network.allowed (cli-proxy egress vs. mcpg redirect passthrough) #54371

Description

@asatara

Summary

In a gh-aw workflow using sandbox: agent: awf with a restricted network.allowed list (compiled to gh-aw-firewall network-isolation mode), artifact ZIP downloads via gh api .../actions/artifacts/{id}/zip and gh run download fail inside the agent sandbox with error connecting to productionresultssaN.blob.core.windows.net. This is a consistent failure.

Minimal repro — a gh-aw workflow compiled with:

network:
  allowed:
    - defaults
    - github
    - github-actions
sandbox:
  agent: awf
tools:
  github:
    mode: gh-proxy

whose agent then runs gh api repos/{owner}/{repo}/actions/artifacts/{id}/zip or gh run download <run-id>.

We tested whether this was a version-pinning issue by bumping gh-aw-firewall from 0.27.44 to 0.28.1 (via gh aw CLI v0.87.1). The failure was identical, including timing (fails in ~350ms both before and after). Tracing the code in gh-aw-firewall and gh-aw-mcpg shows this is caused by two independent, intentional design decisions in those two repos that don't account for each other. Filing here since gh-aw resolves sandbox: agent: awf + network.allowed into this mode and pins both dependent versions; routing to gh-aw-firewall and/or gh-aw-mcpg may be appropriate.

Root cause

  1. gh-aw-mcpg PR Use ghcr.io/githubnext/serena-mcp-server Docker image with language-based container selection #10350 (fixing Fix MCP gateway parameter extraction: add missing mounts and entrypoint support #10349) changed artifact ZIP proxying to stop auto-following GitHub's 302 redirect to Azure blob storage. From its description: "Artifact ZIP GET requests are now forwarded without auto-following redirects. This preserves upstream 302 responses (and Location) so authorization is decided at the proxy boundary before any signed archive URL is followed." This means the gh client itself is expected to follow the redirect.

  2. gh-aw-firewall's cli-proxy sidecar is the only component that executes gh on behalf of the agent (via the /tmp/awf-lib/gh wrapper). In network-isolation mode it is attached only to the internal awf-net network (internal: true), with no route out except a fixed TCP tunnel to the external DIFC/mcpg gateway (host.docker.internalAWF_DIFC_PROXY_HOST:AWF_DIFC_PROXY_PORT).

    PR Remove RedHat YAML extension and yaml.* settings from VSCode configuration #7066 ("Fix cli-proxy ENETUNREACH...by dual-homing it on the external bridge") originally proposed giving cli-proxy general egress via awf-ext. This was reverted within the same PR after review feedback (commit 15cc566, "fix: keep cli-proxy isolated from external bridge"). The final merged diff only adds a test asserting cli-proxy stays off awf-ext. So cli-proxy has not had general egress at any point in this history.

  3. Combining the two: mcpg returns a Location: https://productionresultssaN.blob.core.windows.net/... header, gh (running inside cli-proxy) attempts to connect to that host directly, and cli-proxy has no route there, so the connection fails immediately.

Given this, gh api .../actions/artifacts/{id}/zip and gh run download will fail under network-isolation mode on any current gh-aw-firewall/gh-aw-mcpg version combination, since neither side's change accounts for the other's constraint.

Evidence

  • Reproduced on gh-aw-firewall 0.27.44 and 0.28.1 — same failure both times.
  • cli-proxy-logs/access.jsonl from a run:
    {"event":"exec_start","args":["api","/repos/.../actions/artifacts/9419317053/zip"], ...}
    {"event":"exec_done","args":["api","/repos/.../actions/artifacts/9419317053/zip"],"exitCode":1,"durationMs":358,"stderrPreview":"error connecting to productionresultssa18.blob.core.windows.net\ncheck your internet connection or https://githubstatus.com\n"}
  • Squid's access.log (the domain-allowlisted egress proxy, which does explicitly allow productionresultssa*.blob.core.windows.net) has no entries for the blob host in this run — the request from cli-proxy never reaches squid.
  • docker-compose.redacted.yml from the same run shows cli-proxy's networks as { awf-net: { ipv4_address: ... } } only, no awf-ext.
  • cli-proxy-service.ts at v0.28.1 (github/gh-aw-firewall) has no network-isolation-conditional attachment logic for cli-proxy.
  • The net diff of gh-aw-firewall#7066 across all 3 of its commits only adds a regression test ("keeps cli-proxy on awf-net only when it targets an attached DIFC proxy"), confirming cli-proxy's isolation is intentional and tested for.

Environment

  • gh-aw CLI: tested with v0.86.2 (stable) and v0.87.1 (pre-release)
  • gh-aw-firewall: reproduced on 0.27.44 and 0.28.1
  • gh-aw-mcpg: v0.4.8 and v0.4.9
  • Mode: network: isolation: true, tools.github.mode: gh-proxy

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions