Safeguard
Security Guides•

How long does a GITHUB_TOKEN last, and what about long jobs?

The GITHUB_TOKEN expires when the job ends or at its maximum lifetime. Why that is good for security and what to do for jobs that outlast it.

Safeguard Security Team
4 min read

A GITHUB_TOKEN expires when the job finishes or at its maximum lifetime, whichever comes first. On GitHub-hosted runners that maximum is six hours. On self-hosted runners it can be refreshed for up to 24 hours. Long jobs should not swap it for a long-lived personal token without thinking through the risk.

What GitHub documents

GitHub's concept page on the token says three things relevant here.

  • Before each job begins, GitHub fetches an installation access token for the job. Each job gets its own.
  • The token's permissions are limited to the repository that contains the workflow.
  • It expires when the job finishes or after its effective maximum lifetime. For GitHub-hosted runners the maximum is six hours. For self-hosted runners it can be refreshed for up to 24 hours. For jobs that run longer, GitHub recommends a personal access token or another authentication method.

Why short life is a security feature

A token that dies with the job is a poor prize for an attacker. If an action leaks it into a log or sends it out, the value is useless once the job ends. Compare that with a personal access token or a stored key, which can live for months and often carries more access than any single job needs.

That is the strongest argument for keeping the built in token wherever it is enough, and for limiting its permissions with the permissions key. See GitHub Actions token permissions and least privilege.

What to do when a job outlasts the token

SituationBetter approach
A single step is slow, such as a large test suiteSplit the job so the step that needs the token runs in a short job
A pipeline waits for human approvalUse environments and separate jobs, so the job that needs access starts after approval
A long job must call the API near the endFetch a fresh credential at that point, from a short-lived source
A long job needs repository write at the endHand artifacts to a short final job that has the token

The common thread is to avoid carrying one credential across a long span. Break the work into jobs, each with its own token and its own permissions.

If you must use another credential

GitHub recommends a personal access token or another authentication method for jobs that run past the limit. If you go that way, narrow it as far as you can.

  1. Prefer a token from a GitHub App over a personal one, because it is not tied to a person and can be scoped to chosen repositories. See GITHUB_TOKEN vs GitHub App token vs PAT.
  2. Give it the fewest permissions and the fewest repositories.
  3. Set a short expiry and rotate it.
  4. Store it as an environment secret behind approval, not as a repository secret every workflow can read.
  5. Use it only in the step that needs it.

Cloud credentials follow the same logic

For cloud access, OIDC gives you a short-lived credential per job instead of a stored key. If a job exceeds the credential's lifetime, request a new one at the point of use rather than extending the first. See GitHub Actions OIDC to replace long-lived cloud secrets.

Quick check

Is the six hour figure also the job time limit?

Not necessarily. The six hours is the documented maximum lifetime of the token on GitHub-hosted runners. Check the current job limits in GitHub's documentation for your plan and runner type.

Should I replace GITHUB_TOKEN with a PAT to be safe?

No. A personal token usually lasts longer and carries more access. Keep the built in token unless a job genuinely outlasts it.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.