GitHub Actions credentials are production access if the workflow can mutate production.

The safe pattern is short-lived, scoped access tied to the repository, branch, environment, and workflow that needs it. Long-lived cloud keys in repository secrets should be the exception, not the default.

Start With Permissions

Set workflow permissions explicitly:

permissions:
  contents: read

Then add only what a job needs:

permissions:
  contents: read
  id-token: write

id-token: write enables OIDC token issuance. It does not by itself grant cloud access; the cloud trust policy still decides what the token can assume.

OIDC Trust Checks

For cloud federation, review the trust boundary:

  • repository owner and name.
  • branch, tag, or environment condition.
  • workflow file path, if used.
  • audience value.
  • allowed role or service account.
  • session duration.
  • audit trail for assumed identity.

Do not trust every workflow in a repo to assume the same production role. Separate validation, non-production, and production identities.

Repository And Environment Secrets

Prefer environment-scoped secrets for deployment credentials. Protect production environments with reviewers and branch restrictions.

Review:

  • which repositories can access an organization secret.
  • whether forked PRs can reach sensitive jobs.
  • whether secrets are printed through debug output.
  • whether secrets are passed to third-party actions.
  • whether rotated credentials break old workflow runs.

If a secret can deploy production, its usage should be visible in workflow review and environment protection rules.

Self-Hosted Runner Risk

Self-hosted runners change the threat model.

Check:

  • runner group scope.
  • which repositories can schedule work there.
  • network reachability from the runner.
  • persistence between jobs.
  • cleanup behavior.
  • access to Docker socket, cloud metadata, kubeconfig, or internal networks.

A self-hosted runner reachable from pull requests is not just CI capacity. It is an execution path inside your environment.

Failure Model

The dangerous failure is broad trust:

repo secret holds production key
-> workflow condition is widened
-> PR or branch job reaches deploy step
-> audit shows GitHub Actions but not the intended change boundary

The operating rule: scope credentials to the narrowest workflow identity that can do the work, and make privileged jobs explain why they were allowed to run.