GitHub’s Credential Inventory Is a Relationship Dataset, Not a Breach Meter
Key Takeaways
- The inventory is a relationship dataset, not a breach count or automatic revocation queue.
- Authorization state, credential lifecycle, and observed audit activity answer different questions and must remain separate.
- CSV rows represent credential-to-organization relationships, so row count is not necessarily unique-credential count.
- REST pagination and asynchronous CSV export have different completion rules; read access also remains separate from remediation authority.
GitHub’s enterprise credential inventory gives security teams a consolidated view of credentials associated with GitHub Enterprise Cloud. That is a meaningful visibility improvement—but it is not a ready-made exposure count, compromise detector, or revocation queue.
The reason is structural. The inventory combines different credential families, distinguishes ownership from current authorization, and repeats credentials across organization relationships. Its identifiers and expiration fields also vary by credential type. Used carefully, the export supports investigations and access reviews. Flattened into a single count or severity score, it can manufacture false precision.
Decision rule: preserve GitHub’s authorization, lifecycle, identity, and relationship semantics before deriving metrics or remediation actions.
What GitHub released—and where it is available
GitHub announced credential inventory exports on September 21, 2026 for GitHub Enterprise Cloud. Enterprise owners and users assigned the fine-grained View enterprise credentials permission can access the inventory through enterprise settings or the REST API.
The user-interface path is Settings → Authentication security → Credentials → Export CSV. GitHub’s administrator documentation says the UI export contains the full inventory and cannot be filtered before export; filtering by credential type, access state, owner, organization, or application happens after download. The REST operations support programmatic filtering. (GitHub Changelog; credential-review documentation; versioned REST API)
The overview covers:
- fine-grained personal access tokens;
- personal access tokens (classic);
- OAuth App user access tokens;
- GitHub App user access tokens;
- GitHub App installation access;
- user SSH keys; and
- federated credentials in the export.
GitHub represents GitHub App installation access through the installation that can issue tokens, rather than listing every short-lived installation token as an independent credential. (GitHub credential-review documentation)
The GitHub Enterprise Server boundary remains open
The launch announcement says GitHub Enterprise Server support will arrive in “upcoming releases,” without naming a version or date. A public roadmap issue is labeled GHES 3.23, but the issue remains open and has no milestone. That label is planning evidence, not a shipping confirmation.
The checked GitHub Enterprise Server 3.22.0 release notes are dated September 8, 2026—before the cloud launch announcement—and do not establish availability of this feature on Enterprise Server. Until GitHub publishes a release note or supported-version document confirming shipment, the defensible status is: available for GitHub Enterprise Cloud; planned for GitHub Enterprise Server.
Read the export as evidence with separate layers
The inventory records ownership, credential type, scopes or permissions, repository selection, lifecycle metadata, authorization relationships, and supported correlation identifiers. It does not export a usable token secret: GitHub says the CSV never includes the token value. Depending on credential type, it may include a token identifier, a Base64-encoded SHA-256 hashed_token, or an SSH-key fingerprint. (GitHub credential-review documentation)
Those fields describe different kinds of evidence:
- Inventory metadata describes a credential’s owner, state, permissions, and potential targets.
- Authorization relationships show whether and where the credential is authorized.
- Audit events record observed actions and authentication context.
- Remediation controls revoke authorizations or remove credentials through separate, higher-impact workflows.
A matching audit event can establish that a supported credential was used for an observed action. It does not, by itself, establish malicious use or compromise. Likewise, broad permissions describe potential reach, not proof that the credential exercised that reach.
Illustrative evidence-flow diagram, not a benchmark: credential inventory metadata connects to enterprise audit events through supported token IDs, hashes, or SSH fingerprints. No path represents export of a raw token secret, and neither layer alone proves compromise.
Five ways an implementation can misread the data
1. Inventory presence is not the same as current enterprise authorization
The list endpoint returns two explicitly different populations:
currently_authorized: credentials currently authorized to access the enterprise; andmember_owned_only: credentials owned by enterprise members that have no current enterprise authorization.
(GitHub REST API, version 2026-03-10)
A record’s presence therefore means it is relevant to enterprise credential review—not necessarily that it currently exposes enterprise resources. Combining both populations into one “credentials with access” number would erase GitHub’s documented distinction.
Lifecycle is separate. The CSV’s credential_state can identify states such as active, expired, revoked, or deleted. GitHub defines active credentials in the overview as credentials that have not expired, been revoked, or been deleted. (GitHub credential-review documentation)
Editorial inference from the documented schema: authorization and lifecycle are independent analytical dimensions. A current-access measure should not substitute credential_state for authorization_state, or vice versa.
A practical model should retain at least:
- member-associated credentials;
- currently authorized credentials;
- currently authorized and active credentials; and
- historical or inactive records retained for investigation.
The labels must make clear which population each metric includes.
2. A CSV row is a credential-organization relationship
GitHub’s CSV contains one row for each combination of a credential and an authorizing organization. If one credential is authorized for several organizations, its credential columns repeat while organization_id and organization change. A credential with no organization authorization appears once with empty organization fields. (GitHub credential-review documentation; REST export specification)
That row model supports two legitimate views:
- a relationship view, preserving every credential-to-organization edge; and
- a credential view, deriving one logical record per credential where the schema provides a defensible identity rule.
Illustrative relationship model, not a measured result: one credential authorized for two organizations produces two CSV rows. The repeated rows preserve authorization topology but must not automatically be reported as two unique credentials.
Editorial inference—not a GitHub benchmark: counting CSV rows as credentials can overstate the unique-credential population when credentials have multiple organization authorizations. The amount of overstatement depends on each enterprise’s authorization topology and has not been measured here.
Dropping duplicates during ingestion is not the answer, because it can erase the organization relationships that the export is designed to preserve. Store the raw rows, then build derived views for specific questions.
3. Credential families do not share one universal identity or expiry rule
GitHub warns that credential_id is unique only when combined with credential_type, and only for credential types that populate the field. In the CSV specification:
- classic and fine-grained PATs, OAuth App user tokens, and GitHub App user tokens can populate
credential_id; - SSH keys use a SHA-256
fingerprint; - GitHub App installations and federated JTIs have no unique per-row column; and
owner_idmust be interpreted withowner_type.
(GitHub REST export specification)
The export can also include a Base64-encoded SHA-256 hashed_token for supported token types, but GitHub documents that this field is empty for fine-grained PATs. The raw token value is never included. (GitHub credential-review documentation)
The implementation consequence is straightforward: identity must be credential-type-aware. A pipeline should not coalesce every category into a synthetic universal key and then claim stable cross-export matching. For categories without a documented persistent per-row identifier, longitudinal matching remains an implementation assumption unless GitHub documents a guarantee.
Expiry requires similar discipline. GitHub defines expiry_status as:
expires;never; orunknown.
A blank expires_at does not, by itself, mean “never expires.” Empty CSV cells can indicate that a value is unavailable, unknown, or inapplicable; expiry_status carries the relevant distinction. (GitHub REST export specification; CSV field documentation)
4. One API response—or one 202—does not prove complete collection
Under API version 2026-03-10, the list operation is:
GET /enterprises/{enterprise}/credentials
The endpoint defaults to 30 records per page, accepts at most 100 records per page, and uses an opaque cursor from the HTTP Link header. GitHub explicitly says the response provides no total count. (GitHub REST API)
A collector therefore cannot prove completeness by comparing an observed count with a server-supplied total. For the list operation, completion means following the documented cursor chain until GitHub supplies no next-page link.
CSV automation has a separate asynchronous contract:
POST /enterprises/{enterprise}/credentials/exports
GitHub says this operation starts an asynchronous export and returns an opaque export ID to poll. A successful submission returns HTTP 202 Accepted. Documented creation responses also include 404 Resource not found, 422 Validation failed, 429 Too many requests, and 500 Internal error. GitHub describes the quota only as a “small number” of exports per enterprise per day; the checked specification does not publish an exact number. (GitHub REST API)
Illustrative collection state model, not a performance test: REST listing follows each opaque Link cursor to exhaustion, while CSV export creation moves from request acceptance to export-ID polling and completed-file retrieval. Error states remain distinct from completion.
The operational rule is that 202 confirms acceptance, not possession of a complete, validated CSV. A client should distinguish submission, polling, successful retrieval, validation failure, throttling, and server failure in its own collection records.
5. Read access is not remediation authority
GitHub describes the credential inventory as read-only. Remediation happens through separate enterprise, organization, application, or user controls, depending on credential type. (GitHub credential-review documentation)
That boundary is reflected in two different fine-grained permissions:
- View enterprise credentials permits inventory review and export.
- Manage enterprise credentials permits supported revocation and deletion actions.
GitHub’s remediation documentation limits those actions by account and authentication model. Revoking SSO authorizations is available for Enterprise Managed Users or enterprises using SAML SSO; deleting user keys and tokens at enterprise level is restricted to Enterprise Managed Users. (GitHub remediation guidance)
GitHub warns that bulk actions are high impact, are likely to break automation, and may require months of work to restore the original state. An inventory record should therefore trigger review—not automatic containment.
Before disruptive action, responders should preserve the authorization and lifecycle fields, review permissions and target organizations or repositories, and correlate supported identifiers with audit evidence. GitHub documents these matching paths:
- compare inventory
credential_idwith audit-logtoken_id; - search for the inventory’s
hashed_token; or - compare SSH-key fingerprints.
(GitHub credential-review documentation; audit-log token guidance)
Audit correlation strengthens evidence about observed activity. It does not prove intent, and the absence of a match does not prove that a credential is safe.
A proposed validation plan—not a reported test
Tech Trend Insight has not performed the following experiment. It is a proposed validation for teams building collectors, dashboards, or incident workflows:
- Create a controlled mix of PATs, SSH keys, application credentials, and federated credentials.
- Include both
currently_authorizedandmember_owned_onlyrecords. - Authorize one credential for multiple organizations and compare the raw CSV rows with a derived credential view.
- Compare the UI overview, CSV export, and REST list without assuming identical aggregation semantics.
- Run one client that stops after the first REST page and another that exhausts every
Linkcursor. - Submit an asynchronous CSV export, preserve its export ID, and distinguish
202 Acceptedfrom completed retrieval. - Generate controlled audit events and test only the correlation identifiers GitHub documents for each credential family.
- Confirm that a reviewer with View enterprise credentials cannot perform actions reserved for Manage enterprise credentials.
The resulting observations would validate a specific implementation. They should not be presented as GitHub-wide performance, completeness, or incident-response benchmarks.
The implementation standard
GitHub’s credential inventory is suitable for enterprise-wide evidence gathering: it can show ownership, authorization relationships, lifecycle metadata, permissions, targets, and supported audit-correlation keys.
It should not become an exposure dashboard or automated revocation queue until the implementation can demonstrate that:
currently_authorizedremains distinct frommember_owned_only;- lifecycle state remains separate from authorization state;
- relationship rows are preserved alongside any derived unique-credential view;
- identity and expiry logic varies by credential type where GitHub’s schema varies;
- every REST cursor is exhausted, or the asynchronous CSV export is completed and validated;
- audit evidence is reviewed before asserting observed use or compromise; and
- investigative access remains separate from disruptive remediation authority.
The inventory closes a visibility gap. Its value depends on preserving the data contract rather than compressing it into a number the source does not actually contain.