Skip to main content
Cynative’s GitHub connector is built for read-oriented source-control and repository security research. It uses an in-process per-request classifier to resolve each request to its API category and required access level, then allows it only within the configured ceiling — read-only by default, with certain sensitive categories blocked. Connector id: github
Fixed host: api.github.com (GitHub Enterprise Server is not supported)

Quick start

Authenticate the GitHub CLI, then run Cynative from the same environment:
No YAML configuration is required for the default read-only mode.

Credential discovery

Cynative asks the GitHub CLI auth library (go-gh) for a token for github.com. Cynative does not read these variables itself; go-gh does. Because Cynative always queries the literal github.com host, go-gh’s enterprise / GH_HOST branches never apply.
  • GH_TOKEN — highest-precedence GitHub token; read by go-gh for github.com.
  • GITHUB_TOKEN — second-precedence token (also the GitHub Actions built-in token).
  • GH_PATH — path to the gh executable go-gh shells out to for the keyring-fallback token lookup.
  • GH_CONFIG_DIR — directory go-gh reads the gh auth login token (hosts.yml) from.
Registration and validation: If no token is available, the connector is not registered and nothing is printed. When a token is present, Cynative eagerly validates it at startup with a hardened GET /user request (yielding the @login identity shown in the startup inventory). When /user is inconclusive — a GitHub App installation token, an Actions GITHUB_TOKEN, or a rate-limit condition — Cynative falls back to GET /rate_limit, a universally-accessible, rate-limit-exempt endpoint. References:

Target selection

The GitHub connector always targets the public GitHub REST API at api.github.com — the host is hardcoded. It additionally authorizes the GitHub-owned download hosts codeload.github.com, release-assets.githubusercontent.com, and objects.githubusercontent.com (GET/HEAD only) so release-asset and tarball redirects can be followed. Change the identity by changing the token: run gh auth login, or export GH_TOKEN (highest precedence) or GITHUB_TOKEN. The host is not configurable.

Request usage

Use auth_provider: "github". No connector-specific auth object is required.

Hardening

Host pinning

Host pinning allows only api.github.com and the three GitHub-owned download hosts. The download hosts are GET/HEAD-only, regardless of the configured permissions. Redirects are never followed — a 3xx is returned to the model, which must request the Location URL explicitly (re-entering host pinning and action authorization on each hop).

Category + access-level classification

The in-process classifier resolves each REST request to its GitHub category/subcategory and the required access level (read or write), then allows it only when the configured connectors.github.permissions ceiling permits that level for that category.
  • The check runs before the token is attached, so a disallowed request is rejected without the credential ever leaving the process.
  • The classifier is backed by GitHub’s first-party OpenAPI description, distilled into a category routing table, fetched anonymously and cached from raw.githubusercontent.com.
  • A REST request that cannot be classified fails closed. The secret-scanning category is denied by the secure baseline even for reads, because its read endpoints can leak secret material.
  • The GraphQL API (/graphql) is not supported and is always denied.

Secret-scanning protection

Secret-scanning protection is layered: the table admission guard rejects any fetched spec that maps a secret-scanning template to another category; the secret-scanning: none baseline in the default exposure blocks all such requests at the ceiling; and unknown routes fail closed.

Cynative configuration

connectors.github.permissions is a category[/subcategory] → read|write|none ceiling. Omit it entirely for the secure default (read everything except secret-scanning). The most-specific match wins (category/subcategory → category → default). write implies read; none denies even reads.
Set from the environment as a compact comma-separated list:
A non-empty environment value replaces the config-file map wholesale. A blank value is treated as unset. Duplicate keys are rejected at load time. When the ceiling is widened (default=write, an opened secret-scanning, or any category:write override), the startup inventory line is loud (⚠) and names exactly what was widened.

Defense at a glance

Limitations

  • The connector supports api.github.com and the listed download hosts. GitHub Enterprise Server hosts are not supported.
  • Actions-artifact downloads are not supported: GitHub redirects them to per-account Azure blob endpoints, which are outside the GitHub-owned host invariant.
  • A configured permissions ceiling never expands the GitHub token’s own scopes — the effective capability is the intersection of the two. Setting issues: write does nothing if the gh token cannot write issues.
  • There is no client-side credential downscoping. A PAT, gh, or OAuth token has its scopes fixed at creation.
  • The category routing table requires egress to raw.githubusercontent.com. With no network and no local cache, the connector fails closed — every api.github.com request is denied with a github_hardening: category table not ready error.