Skip to content

Installer fails behind rate-limited IPs: api.github.com called without auth (60 req/hr) #1156

Description

@tbontb-iaq

Problem

All three installers call the GitHub REST API unauthenticated when resolving the latest release tag:

  • scripts/install.sh:290curl -fsSL "https://api.github.com/repos/${REPO}/releases/latest"
  • scripts/install.ps1:102Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest"
  • scripts/install.cmd:211curl -fsSL "https://api.github.com/repos/!REPO!/releases/latest" -o ...

Unauthenticated api.github.com requests are capped at 60/hour per source IP (not per user). This makes curl -fsSL https://plannotator.ai/install.sh | bash fail for:

  • Users behind NAT / corporate proxies / CGNAT (many users share one egress IP — one person burns the quota for everyone)
  • Anyone retrying/debugging an install within the same hour
  • CI runners on shared cloud IP ranges

The failure is opaque: curl -f returns non-zero, the installer prints Failed to fetch latest version / Failed to get latest version and exits, with no hint that rate limiting is the cause.

The CDN release-asset downloads (github.com/.../releases/download/...) and git clone are not subject to the 60/hr REST limit, so only the api.github.com call needs fixing.

Proposed fix (generic, cross-installer)

Add a small, reusable token-detection block to each installer that attaches an Authorization: Bearer header to the api.github.com request. Precedence (matches gh conventions):

  1. GITHUB_TOKEN env var
  2. GH_TOKEN env var
  3. gh auth token (if the gh CLI is installed and authenticated)

When no token is available the header is omitted and behavior is unchanged (anonymous, 60/hr) — fully backward compatible.

# install.sh sketch
GH_AUTH_HEADER=()
if [ -n "${GITHUB_TOKEN:-${GH_TOKEN:-}}" ]; then
    GH_AUTH_HEADER=(-H "Authorization: Bearer ${GITHUB_TOKEN:-${GH_TOKEN}}")
elif command -v gh >/dev/null 2>&1; then
    if _gh_token="$(gh auth token 2>/dev/null)" && [ -n "$_gh_token" ]; then
        GH_AUTH_HEADER=(-H "Authorization: Bearer ${_gh_token}")
    fi
fi
latest_tag=$(curl -fsSL "${GH_AUTH_HEADER[@]}" "https://api.github.com/repos/${REPO}/releases/latest" ...)

Parity equivalents for install.ps1 (-Headers @{ Authorization = "Bearer $token" }) and install.cmd (a -H "Authorization: Bearer %TOKEN%" arg splatted into the curl call).

This raises the effective limit from 60/hr to 5000/hr for anyone with a token or gh auth login, and leaves everyone else exactly where they are today.

Docs

Add a short note to the installation + troubleshooting docs describing the GITHUB_TOKEN/GH_TOKEN env vars for rate-limited environments.

Out of scope

  • Release-asset downloads and git clone are intentionally left unauthenticated — they are not subject to the 60/hr REST limit, and authing large binary downloads would expose the token in the process list for longer than necessary.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions