Automating GitHub tasks can save developers time. Teams use scripts and CI/CD pipelines to create pull requests, manage issues, publish releases, update repository settings, and perform routine maintenance. Many of these operations require authentication through GitHub CLI or the GitHub API.
The challenge is managing authentication securely. A script that depends on a long-lived personal access token may continue working for months, but the token can become a security risk if it is exposed in logs, configuration files, or a compromised build environment.
Expiring tokens reduce the period during which a leaked credential can be used. However, short-lived credentials also require a reliable authentication process. If a workflow expects a token that has already expired, an automated task may fail unexpectedly.
The right approach depends on where the workflow runs, which GitHub resources it needs to access, and whether the task can use GitHub's built-in authentication mechanisms.
This article explains how GitHub CLI authentication works, how to use short-lived credentials in automation, when to choose GitHub Actions' built-in token, and how to avoid common authentication failures.
Understanding GitHub CLI Authentication
The GitHub CLI, commonly called gh, provides a command-line interface for interacting with GitHub. Developers can use it to inspect pull requests, create issues, review workflow runs, and execute other repository operations.
For example, the following command lists open pull requests in the current repository:
gh pr list --state open
The command requires an authenticated GitHub CLI session with access to the repository.
For interactive use, developers can authenticate through the CLI and follow the login instructions. Automated workflows need a different approach because they cannot depend on a developer completing an interactive login every time a job runs.
What Is an Expiring Token?
An expiring token is a credential that becomes invalid after a defined period or when its authorization is revoked.
GitHub authentication can involve several credential types, including:
- GitHub Actions' built-in GITHUB_TOKEN.
- Fine-grained personal access tokens.
- Classic personal access tokens.
- GitHub App installation access tokens.
- Credentials obtained through an approved identity or authentication flow.
These credentials have different lifetimes, permissions, and operational requirements.
A fine-grained personal access token can be configured with an expiration date. A GitHub App installation access token is short-lived and is generally valid for up to one hour. GitHub Actions' GITHUB_TOKEN is created for a workflow job and is automatically limited by the job's lifecycle and configured permissions.
The distinction matters because an ordinary GitHub CLI session does not automatically renew every type of credential. The workflow must obtain and use credentials through the appropriate mechanism.
Choose the Right Token for the Workflow
Before implementing token expiration, identify the task the automation needs to perform.
A workflow that reads pull request information may require fewer permissions than one that publishes a release or modifies repository settings.
Compare Common Authentication Options
Authentication method | Typical lifetime behavior | Best suited for | Main consideration |
|---|
GITHUB_TOKEN | Created for a GitHub Actions job and expires when the job finishes or reaches its applicable expiration | Routine operations within a workflow | Access is restricted by repository and workflow permissions |
Fine-grained personal access token | Has a configured expiration date | Scripts that require access under a user's identity | Requires secure storage, renewal, and appropriate permissions |
GitHub App installation token | Short-lived, generally up to one hour | Automation operating as an installed GitHub App | Requires an App authentication and token-generation process |
Classic personal access token | Can have an expiration date depending on its configuration and organization policy | Existing integrations that still require it | Broad access can increase risk; prefer a narrower option when possible |
A token's expiration does not determine its full security profile. Its permissions, scope, owner, storage, and revocation process are equally important.
For automation running inside GitHub Actions, start by checking whether GITHUB_TOKEN can perform the required operation. If it can, using the built-in token is often simpler than maintaining a separate long-lived credential.
Use GITHUB_TOKEN for Routine GitHub Actions Tasks
GitHub Actions provides GITHUB_TOKEN to authenticate supported operations within a workflow. It can often replace a manually managed personal access token for tasks performed in the same repository.
Consider a workflow that creates or updates a pull request after running automated checks. If the operation is supported by GITHUB_TOKEN and the workflow has the required permissions, a separate personal access token may not be necessary.
Configure Minimum Permissions
The following example runs GitHub CLI in a workflow and uses GITHUB_TOKEN to read pull request information.
name: Inspect Pull Requests
on:
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
inspect:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v4
- name: Set up GitHub CLI
run: gh --version
- name: List open pull requests
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh pr list --state open
This workflow illustrates read-only pull request inspection. The action references are shown for readability; repositories with an action-pinning policy should replace version tags with verified full commit SHAs.
The GH_TOKEN environment variable allows GitHub CLI to authenticate without requiring an interactive login. The workflow's permissions determine the access available through GITHUB_TOKEN.
For operations that create or modify pull requests, the workflow may need additional permissions. Grant only the permissions required for the specific task.
Also note that GITHUB_TOKEN has limitations. For example, events caused by many operations performed using that token generally do not trigger new workflow runs, with certain exceptions. If your automation depends on a newly created pull request triggering another workflow, verify the event behavior before choosing this authentication method.
Use GitHub App Installation Tokens for Short-Lived Automation
When automation needs access beyond the capabilities of GITHUB_TOKEN, a GitHub App can provide a more controlled authentication model.
A GitHub App can be installed on selected repositories and granted specific permissions. An authorized workflow can generate an installation access token and use it for a limited period.
This approach is useful for organization-level automation, cross-repository maintenance, and integrations that should not depend on an individual developer's personal credentials.
How GitHub App Authentication Works
The general process is:
- Create a GitHub App and configure the required permissions.
- Install the app on the repositories it needs to access.
- Securely store the app's private key or use an approved mechanism to obtain credentials.
- Generate an installation access token when the workflow needs one.
- Pass the token to GitHub CLI or the relevant API client.
- Allow the token to expire and generate another when a future task requires access.
A GitHub App installation token generally lasts up to one hour. It should be treated as temporary, sensitive data.
The private key used to authenticate the app is more sensitive than the installation token because it can be used to obtain new tokens. Protect it accordingly and avoid exposing it to untrusted workflows.
Use the Token With GitHub CLI
Once the workflow has generated an installation token, GitHub CLI can use it through the GH_TOKEN environment variable.
For example:
GH_TOKEN="$INSTALLATION_TOKEN" gh api user
The command demonstrates passing a token to GitHub CLI. The actual endpoint and permissions should match the authentication method and intended operation.
For GitHub App installation tokens, some endpoints may not be available because the token represents an installed app rather than a user. Use an endpoint appropriate to the token type and the task being performed.
Do not print the token to the console or include it in diagnostic messages.
Generate and Use an Installation Token in GitHub Actions
For supported workflows, GitHub provides an official action for generating GitHub App installation tokens.
The following example demonstrates the general pattern. It assumes that the GitHub App has been created, installed on the repository, and granted the permissions needed for the intended operation.
name: GitHub App Automation
on:
workflow_dispatch:
permissions:
contents: read
jobs:
inspect:
runs-on: ubuntu-latest
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.AUTOMATION_APP_ID }}
private-key: ${{ secrets.AUTOMATION_APP_PRIVATE_KEY }}
- name: Check repository information
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api repos/${{ github.repository }}
This example uses an action version tag to keep the configuration readable. In a repository that requires SHA pinning, replace the tag with a verified full commit SHA.
The example assumes that the app's installation includes the repository and that its permissions allow the requested API operation. If the app has not been granted the required permissions, the request will fail even when token generation succeeds.
For tighter access control, configure the app token action to target only the intended repositories when that option is appropriate. Avoid granting broad organization-wide access when the workflow needs to operate on only a small set of repositories.
The generated token is available to the step that needs it through an environment variable. It should not be written to a file, printed, or persisted as a long-term workflow artifact.
Use Fine-Grained Personal Access Tokens When Necessary
Some external scripts or integrations may need to authenticate as a user. In those cases, a fine-grained personal access token can be appropriate, provided that the integration genuinely requires user-based authentication.
Create the token with access limited to the necessary repositories and permissions. Set an expiration date that matches the operational requirements and the organization's security policy.
Store the token in an approved secret manager or CI/CD secret store.
For a GitHub CLI script, the token can be supplied through an environment variable:
export GH_TOKEN="$GITHUB_AUTOMATION_TOKEN"
gh pr list --repo OWNER/REPOSITORY
Replace OWNER and REPOSITORY with the actual repository owner and name. GITHUB_AUTOMATION_TOKEN should be provided securely by the execution environment rather than hard-coded in the script.
This example assumes the token has access to the specified repository and permission to list pull requests.
Do not commit a token to a repository, include it in a shell command stored in source control, or place it in a configuration file that may be shared with other developers.
Plan for Token Expiration
A fine-grained personal access token with an expiration date does not automatically renew itself just because a script uses it regularly.
Before expiration, the responsible owner or automation process must obtain a replacement through the approved process and update the secret store.
A good renewal process should include:
- A named owner for the credential.
- A documented renewal procedure.
- A secure method for replacing the stored token.
- A way to detect authentication failures.
- A tested recovery procedure if the token expires unexpectedly.
- A revocation process when the credential is no longer needed.
For unattended automation that must run indefinitely, a GitHub App or an appropriate workload identity mechanism may be easier to maintain than a personal token.
Handle Expired Tokens and Authentication Failures
Short-lived credentials improve security, but they introduce a failure mode that automation must handle correctly.
If a token expires before an operation finishes, GitHub may reject the request. The exact response depends on the authentication method and API operation.
Do not assume that every HTTP 401 response means the token has expired. Invalid credentials, revoked tokens, incorrect token formatting, and other authentication problems can produce similar failures.
Check Authentication Before Running a Task
For GitHub CLI workflows, a simple preflight check can help identify an authentication problem early.
if ! gh auth status; then
echo "GitHub CLI authentication is unavailable." >&2
exit 1
fi
gh pr list --state open
The status command checks the configured GitHub CLI authentication state. It does not guarantee that every requested operation will succeed, because the token may lack the required permissions or access to a particular repository.
When GH_TOKEN is supplied through the environment, GitHub CLI uses that credential for authentication. Make sure the token is valid and configured for the intended host.
Avoid Blindly Retrying Failed Requests
Repeatedly retrying an expired or invalid token does not solve the underlying problem.
Use a recovery process appropriate to the authentication method:
- For GITHUB_TOKEN, verify the workflow permissions and job context.
- For a GitHub App installation token, obtain a fresh token through the approved app authentication process.
- For a personal access token, verify its status and arrange a secure replacement if necessary.
- For insufficient permissions, update the authorization configuration only after confirming that the operation legitimately requires additional access.
For operations that create releases, modify issues, or trigger deployments, also consider whether the request may have succeeded before the client reported a failure. Use an idempotent design or verify the operation's outcome before retrying to avoid duplicate effects.
Common Mistakes to Avoid
Using a Personal Access Token for Every Task
A personal access token is not always the best choice for automated workflows. GITHUB_TOKEN or a GitHub App may provide a narrower and more manageable authentication model.
Choose credentials according to the operation, required permissions, and execution environment.
Assuming Every Token Renews Automatically
Different token types have different lifecycle rules.
A GitHub App installation token is short-lived, while a personal access token follows its configured expiration and revocation rules. A script must not assume that an expired credential will be renewed automatically.
Granting Excessive Permissions
Giving a token full access to an organization when it only needs to read one repository increases the potential impact of a compromise.
Use minimum required permissions and restrict repository access wherever possible.
Printing Tokens During Troubleshooting
Debugging output can accidentally expose credentials in workflow logs.
Avoid commands that print environment variables or authentication headers. Treat tokens as secrets even when their lifetimes are short.
Forgetting Workflow Trigger Behavior
A workflow that creates a pull request using GITHUB_TOKEN may not trigger subsequent workflows in the same way as an operation performed using a different credential.
Verify the event behavior when designing multi-stage automation. Do not switch to a more privileged credential without understanding the security implications.
Best Practices for Production Automation
Use these practices to keep automated GitHub operations reliable and secure:
- Prefer GITHUB_TOKEN for supported operations within a GitHub Actions job.
- Use GitHub Apps when automation requires controlled access across repositories or needs capabilities beyond the built-in token.
- Use fine-grained personal access tokens only when user-based authentication is necessary.
- Configure the minimum required permissions and repository access.
- Store credentials in an approved secret manager or CI/CD secret store.
- Generate short-lived credentials as close as practical to the operations that need them.
- Avoid persisting installation tokens or writing them to logs.
- Establish ownership and renewal procedures for credentials that have configured expiration dates.
- Monitor authentication failures and provide a documented recovery process.
- Verify the result of operations before retrying potentially non-idempotent requests.
- Review token permissions and revoke credentials that are no longer needed.
These practices reduce the risks associated with automated authentication without making routine development tasks unnecessarily complicated.
Advantages and Limitations of Expiring Tokens
Expiring tokens reduce the period during which a leaked credential may remain usable. They also encourage teams to adopt more deliberate authentication and renewal processes.
Short-lived GitHub App installation tokens can be especially useful for automation because they avoid relying on a permanently valid access token for every run.
However, expiration alone is not a complete security control. A token can still be abused while valid, and a poorly protected private key or overly privileged workflow can create substantial risk.
Shorter lifetimes also introduce operational requirements. Automation must obtain credentials correctly, handle expiration, and recover from authentication failures without creating duplicate operations or unsafe workarounds.
The most effective design combines limited permissions, secure credential storage, appropriate token lifetimes, and a tested recovery process.
Summary
Expiring tokens can make GitHub CLI automation safer, but the implementation depends on the authentication method and the task being performed.
For routine GitHub Actions operations, start with GITHUB_TOKEN and grant only the required permissions. When automation needs broader or cross-repository access, consider a GitHub App that generates short-lived installation tokens. Use fine-grained personal access tokens when user-based authentication is genuinely necessary, and establish a secure renewal process for them.
Always keep credentials out of source control and workflow logs. Validate authentication before important operations, distinguish expired credentials from permission failures, and avoid blindly retrying requests that may already have succeeded.
A reliable automation system treats token expiration as part of its authentication design rather than as an unexpected error. This approach improves security while keeping automated development and deployment workflows maintainable.
Join the conversation! Your thoughts help the community grow.