Grant a scanner only the Git operations it needs, on only the repositories you intend to assess, for only as long as that connection remains approved. For a GitHub App, review three different limits: the app's registered permissions, the repositories selected at installation, and the repositories and permissions allowed on each installation token. A fourth question sits outside GitHub: what the scanner does with source after reading it. A read-only Git grant prevents repository modification; it does not prevent copying source into a broad log, model request or backup.
There is no universal “scanner permission set.” A tool that only reads a pinned revision needs different API calls from one that comments on pull requests, publishes check runs or creates fix branches. Build the grant from the exact API operations and webhook events the integration uses. GitHub recommends the minimum permissions needed when an app is registered and permits further restriction when a token is minted (GitHub App best practices). Treat a vendor's broad install prompt as a question to resolve, not as a default to accept.
Begin with the scanner's actions
Ask the vendor to list every GitHub API operation and webhook event used for each enabled feature. Group them by read source, track changes, publish feedback and write code. Map the operations to GitHub's permission-to-endpoint reference. Review actual requested repository, organization and account permissions on the install screen. A permission name alone may cover more endpoints than the feature description suggests; the endpoint list makes the grant reviewable.
Then decide whether the feature belongs in this connection. A read-only assessment does not need code push permission merely because the vendor also sells automated fixes. An optional PR comment or check-run feature may need a write permission even when repository contents remain read-only. You can defer that feature and request a new review later. GitHub says installations must approve newly requested repository or organization permissions before those changes take effect (approving updated permissions). Record who can approve that escalation.
Illustrative case: billing repository, no write-back
Illustrative case; these repositories and workflow choices are invented. A platform team wants a two-week assessment of billing-api, a private repository. It does not want the vendor to see identity-core or customer-data-migration. The scanner will read a pinned commit and show results in its own application. It will not comment on PRs, create GitHub checks, open fix PRs or push code during this pilot.
The team asks for a GitHub App installation limited to billing-api, with only the API permissions needed to read its metadata and contents. The exact displayed permissions must be checked against the endpoints the vendor uses; this article is not a substitute for that check. The team declines repository administration, workflows and write grants for this pilot unless the vendor can name a necessary operation. It also distinguishes the app installation from any separate user authorization prompt: GitHub notes that authorizing an app to act on a person's behalf and installing it for repository access are different actions (third-party installation guide).
The install owner chooses Only select repositories and names billing-api. GitHub offers that choice for apps that request repository permissions, and lets an owner later review or change it (installation guide, reviewing installed apps). The selected-repositories control limits private organizational access; GitHub's installation documentation also notes that an app has at least read-only access to public repositories. If a public repository has sensitive business meaning, assess that separately rather than claiming the selection makes it invisible to the app.
Build the grant from an endpoint map
For this pilot, the source reader starts from an approved commit and traverses Git objects. The following map uses GitHub's documented endpoint permissions; it is deliberately specific to this acquisition method:
| Operation | Endpoint family | Permission / decision |
|---|---|---|
| Enumerate pinned tree and subtrees | GET /repos/{owner}/{repo}/git/trees/{tree_sha} |
Contents read; Trees API. |
| Read authorized regular-file object | GET /repos/{owner}/{repo}/git/blobs/{file_sha} |
Contents read; Blobs API. |
| Publish a check run | POST /repos/{owner}/{repo}/check-runs |
Checks write; Checks API. Disabled in this pilot. |
| Push a fix branch or modify source | Write endpoints chosen by that future feature | Outside this grant; requires a separate endpoint/permission review. |
Resolving a user-entered branch, reading pull-request data or subscribing to events can introduce other operations. Add them if the integration actually uses them; do not claim this table is sufficient for every scanner. Tree enumeration must also handle truncation. A permission sufficient to call the endpoint does not establish complete source acquisition.
Narrow the token as well as the installation
The first phase installs the app for billing-api only. Later, after a separate approval, the team adds reports-api for a different job. At that point the installation can access both, but a billing job still needs only billing. A token request with no repository restriction would inherit the installation's wider repository set.
The intended issuance body for the billing job is illustrated below. Repository ID 101 is fictional; credentials and the signing JWT are intentionally omitted.
{
"repository_ids": [101],
"permissions": { "contents": "read" }
}
GitHub documents repository_ids and permissions as narrowing parameters and returns the resulting scope and expiry in the issuance response. If omitted, the token receives the installation's granted repositories and permissions; it cannot exceed that grant. Installation tokens expire after one hour. Check the returned record, not only the requested body. Apply the same narrowing and current-job authorization when a token is renewed; an SDK that refreshes with installation-wide defaults can undo the initial restriction. Token expiry also does not stop an issuer that remains authorized to mint replacements. GitHub token-generation documentation.
The platform's filled acceptance sheet distinguishes provider authority from scanner policy:
| Attempt with billing-job credential | Expected result | Which boundary establishes it? |
|---|---|---|
| Read approved billing tree/blob | Allowed | GitHub repository and contents grant. |
| Read private reports repository | Denied | Per-token repository restriction, even though installation now includes reports. |
| Create a check run | Denied | No checks write grant for this job. |
| Read another billing branch | Token may allow it | Commit pin is the scanner's acquisition rule; repository permission is not a branch allowlist. |
| Read a file excluded from analysis within billing | Token may allow it | Acquisition/path policy must enforce the intended data boundary; analysis exclusion alone may not stop retrieval. |
These are expected checks, not executed results. The final two rows prevent an overclaim: repository-scoped read access is broader than “only these files at this commit.” The vendor must enforce and record that narrower workflow itself.
Separate the issuer from the content-reading task
A narrowly scoped job token loses value if the same task also holds the app private key and can mint a wider one. Ask which trusted component holds issuance authority, how it authenticates the job and binds its repository, and which credential reaches source-processing code. The reviewable result is a short-lived billing token in the job, with issuance authority retained by a separately controlled component. This is an architecture requirement to verify, not an assertion that GitHub forces a particular vendor design.
At job end, the vendor can use GitHub's installation-token revocation endpoint for that token and discard it. Removing the repository from the installation addresses future authority more broadly. Neither operation deletes source already acquired; the cleanup record remains a separate obligation. Never request a live token or private key in the evidence packet.
Review issuance failure as carefully as successful narrowing
The billing job should have an explicit response when the issuer cannot confirm the installation, repository selection or current work authorization. A request that lacks a validated repository binding should not fall back to an installation-wide token. Keep the failure visible to the operator with a bounded reason code and enough metadata to locate the job, without logging the token or app signing material.
Consider a queued job approved before billing-api is removed. At execution time, the issuer should reconcile the current connection and job state with the requested repository. A stored installation ID is a locator, not a permanent authorization decision. The same check matters at renewal: the original narrow token may have been issued correctly while the connection has since been removed or the job canceled.
The evidence packet should therefore include the successful narrow issuance and the denied or stopped branch. It can show requested repository IDs, effective permissions, expiry and the job's authorization state in redacted form. It should not require the buyer to hold a usable credential. If a task already fetched source, its subsequent handling belongs to the separate job and retention controls; provider issuance checks cannot recall those bytes.
Finally, inspect optional integration features for hidden credential substitution. If a check-publishing operation fails because the source token lacks writes, the application should use an explicitly approved separate route or leave that feature unavailable. It should not silently retry with a broader personal token. A narrowly documented token is valuable only when it is the credential that actually governs the source-reading task and its failure paths.
Watch for access widening after approval
An organization owner can modify repository selection. GitHub also documents circumstances in which repository administrators can add their repositories to an installed app, even when the owner approved its permissions (GitHub organization app-access controls). Decide who is allowed to make that change under your policy. Review the installation after the pilot begins and after the vendor ships a feature update. GitHub's organization audit-event reference includes repository-added, repository-removed and installation-version-updated events for GitHub Apps (audit events). Those events can help find a change; they do not replace a current installation review.
If the tool uses an OAuth app, personal access token, deploy key or self-hosted runner instead of a GitHub App, the same questions remain but the mechanisms differ. Ask which human or service identity owns the credential, what it can access, where it is stored, when it expires, and whether one user's departure breaks or silently broadens the integration. Do not describe a personal token as repository-limited without checking its actual authorization. The visible installation screen for a GitHub App cannot establish the scope of a second token or runner deployed elsewhere.
Check removal and downstream copies
At the end of the approved period, remove the repository from the installation or suspend or uninstall the app as policy requires. GitHub documents these controls in the installed-app review guide. Observe whether a new source request fails and whether an already scheduled scan stops. Record any previously fetched source, derived index, model input, report, log or backup under the vendor's separate retention policy. Revoking a GitHub grant stops future provider access; it cannot retrieve plaintext already delivered.
If the vendor cannot state which permission enables an operation, defer that operation. If a selected-repository pilot fails because the scanner assumes organization-wide access, record that as a product limitation rather than broadening access without review. A scanner can still produce useful partial results if it labels missing cross-repository dependencies honestly. A clean scan of billing-api alone does not establish safety of identity-core or of the application that calls both.
Next action: request the vendor's endpoint-and-event list, compare it with the install prompt, and approve one selected repository for a bounded trial. Continue with a pilot that does not share every repository and the tenant-isolation evaluation before expanding source access.