The Problem

GitHub Releases are a popular distribution mechanism for pre-built binaries, installers, and archives. When autonomous coding agents have access to github.com through ghp, they can download arbitrary release assets — pulling in unvetted binaries from any public repository. This is a supply chain risk: an agent instructed (or tricked) into downloading and executing a release binary could compromise the host environment.

Unlike source code fetched via git clone (which is scoped to specific repositories by ghp's token system), release downloads are simple HTTPS GETs against github.com that bypass the API scope model entirely. The release controls feature closes this gap.

How It Works

The releases handler intercepts requests matching the GitHub release download path pattern:

/{owner}/{repo}/releases/download/{tag}/{asset}

When a matching request arrives, ghp evaluates it against the configured policy before the request reaches GitHub. Two modes are available:

Block Mode

Returns 403 Forbidden immediately. The request never leaves your network.

releases:
  mode: block

This is the simplest and most restrictive option. Use it when agents should never download release assets (the common case for coding agents that only need source access).

Redirect Mode

Returns a 302 Found redirect to an alternative download server. The full original path and query string are preserved.

releases:
  mode: redirect
  redirect_to: "https://releases.internal.example.com/"

A request for /cli/cli/releases/download/v2.50.0/gh_linux_amd64.tar.gz would redirect to https://releases.internal.example.com/cli/cli/releases/download/v2.50.0/gh_linux_amd64.tar.gz.

This mode is useful when your organization mirrors approved release assets on an internal server — agents are steered to the vetted copies rather than downloading directly from GitHub. The redirect_to value must be an absolute URL (scheme + host); relative paths are rejected at runtime.

HEAD Check

When the redirect target is a selective mirror that only hosts a subset of releases, agents following the redirect may receive an unfriendly error from the mirror for assets it doesn't carry. Enable redirect_head_check to have ghp issue a HEAD request to the redirect target URL before sending the 302. If the mirror returns 404, ghp serves a user-friendly HTML error page instead of redirecting.

releases:
  mode: redirect
  redirect_to: "https://releases.internal.example.com/"
  redirect_head_check: true

For any response other than 404 (including network errors), ghp proceeds with the redirect as normal — the HEAD check is purely an optimistic availability probe.

Authenticated HEAD Checks

If your mirror requires authentication, point redirect_head_check_netrc at a netrc-format file. Credentials matching the redirect target's hostname are sent as HTTP Basic auth on each HEAD probe over HTTPS. Credentials are never injected for plain http:// URLs to prevent sending them in cleartext.

Because ghp typically runs as a DynamicUser (no home directory), ~/.netrc is not available. Use an absolute path to a file the service can read — for example /etc/ghp/netrc, which is under the systemd ConfigurationDirectory:

releases:
  mode: redirect
  redirect_to: "https://releases.internal.example.com/"
  redirect_head_check: true
  redirect_head_check_netrc: "/etc/ghp/netrc"

The netrc file uses the standard format:

machine releases.internal.example.com
login deploy
password s3cret

If the netrc file cannot be read at startup, ghp logs an error and falls back to unauthenticated HEAD checks. Existing Authorization headers on a request are never overwritten.

Redirect behavior during HEAD probes

HEAD availability probes do not follow HTTP redirects. If the mirror responds with a redirect, ghp treats it as success (non-404) and proceeds with the normal client redirect. This means probe credentials are never forwarded to an unintended redirect target.

default netrc entries are intentionally ignored to prevent credential leakage to unintended hosts. Use host-specific machine entries only.

Custom 404 Template

The built-in 404 page is clean and informative, but you can replace it with your own HTML by setting redirect_not_found_template to the path of an html/template file on disk:

releases:
  mode: redirect
  redirect_to: "https://releases.internal.example.com/"
  redirect_head_check: true
  redirect_not_found_template: "/etc/ghp/404.html"

The template receives the following data:

Field Description Example
Owner Repository owner / organisation cli
Repo Repository name cli
Tag Release tag v2.50.0
Asset Asset filename gh_linux_amd64.tar.gz
URL Full redirect target URL that returned 404 https://mirror.example.com/cli/cli/releases/download/v2.50.0/gh_linux_amd64.tar.gz

If the custom template cannot be loaded (missing file, parse error), ghp logs an error and falls back to the built-in default.

Allow List

Both modes support an allow list of organisations or specific repositories that are exempt from the policy. Allowed entries pass through to GitHub unmodified.

releases:
  mode: block
  allow:
    - "myorg"              # all repos under this org are allowed
    - "external/approved"  # only this specific repo is allowed

Matching is case-insensitive. An org-level entry (e.g. myorg) allows all repositories under that organisation. An org/repo entry (e.g. external/approved) allows only that specific repository.

Non-release Traffic

Only paths matching /{owner}/{repo}/releases/download/ are affected. All other traffic — API calls, git operations, archive downloads, repository browsing — passes through completely unchanged regardless of the releases policy.

Configuration

See the Configuration Reference for the full list of environment variables and YAML fields.

releases:
  mode: "block"                    # "block", "redirect", or "" (disabled)
  redirect_to: ""                  # base URL for redirect mode
  redirect_head_check: false       # HEAD-check target before redirecting
  redirect_head_check_netrc: ""    # netrc file for HEAD check auth
  redirect_not_found_template: ""  # custom 404 HTML template path
  allow:
    - "myorg"
    - "trusted/tool"
GHP_RELEASES_MODE=block
GHP_RELEASES_REDIRECT_TO=https://releases.internal.example.com/
GHP_RELEASES_REDIRECT_HEAD_CHECK=true
GHP_RELEASES_REDIRECT_HEAD_CHECK_NETRC=/etc/ghp/netrc
GHP_RELEASES_REDIRECT_NOT_FOUND_TEMPLATE=/etc/ghp/404.html
GHP_RELEASES_ALLOW=myorg,trusted/tool

For container orchestrators that cannot pass comma-separated values reliably, use indexed environment variables:

GHP_RELEASES_MODE=block
GHP_RELEASES_ALLOW_COUNT=2
GHP_RELEASES_ALLOW_0=myorg
GHP_RELEASES_ALLOW_1=trusted/tool

Indexed entries replace the comma-separated GHP_RELEASES_ALLOW value entirely when GHP_RELEASES_ALLOW_COUNT is set.

Monitoring

When redirect_head_check is enabled, ghp records two metrics:

  • ghp_releases_redirect_head_check_total — a counter labeled by result (found, not_found, error) that tracks how often the mirror has the requested asset, is missing it, or is unreachable.
  • ghp_proxy_decision_duration_seconds with stage="redirect_head_check" — a histogram recording the latency of each HEAD probe, so you can monitor the overhead the availability check adds.

Use these to tune your mirror coverage and set alerts for elevated not_found or error rates. See Monitoring for the full metrics reference.

Limitations

  • Release pages and metadata are not blocked. Only the binary download path (/releases/download/) is intercepted. Agents can still view release pages and list releases via the API — they just cannot fetch the assets.

  • Detection is path-based. The handler matches the URL pattern used by GitHub's release download mechanism. If GitHub changes its URL structure in future, the pattern would need updating.

  • HEAD check adds latency. When redirect_head_check is enabled, each redirected request incurs an extra round-trip to the mirror before the client receives a response. This is typically fast for local mirrors but should be considered in latency-sensitive environments.