GitHub Actions OIDC: Short-Lived Cloud Credentials Without Repository Secrets
How GitHub's OIDC tokens, cloud trust policies, audience and subject claims replace static CI keys while keeping workflows and environments constrained.
GitHub Actions can request a short-lived OpenID Connect identity token during a job and exchange it for temporary credentials at a cloud provider. This removes a long-lived cloud access key from repository secrets, but it does not automatically make the workflow trustworthy. The cloud trust policy must bind token claims to a specific repository, ref or environment, workflow context, and audience.
The token is an assertion, not a cloud credential
GitHub operates an OIDC provider. A job with id-token: write can request a signed JWT containing claims such as issuer, audience, repository, repository owner, ref, workflow, actor, and a structured sub (subject). The cloud security-token service validates that JWT and returns its own short-lived role session or access token.
permissions:
contents: read
id-token: write
id-token: write means the job may request an OIDC token; it does not grant write access to cloud resources by itself. Cloud authorization comes from the role or identity mapped by the provider’s trust configuration.
Constrain issuer, audience, and subject
The issuer should be GitHub’s documented token service. The audience identifies the intended recipient and is often set by the official cloud login action. The sub claim can represent a branch, tag, pull-request context, or protected GitHub Environment.
A trust policy that accepts every subject from repo:example/payments:* lets more workflows and refs request the same cloud role than one restricted to a production environment. Prefer a protected environment with required reviewers and deployment-branch rules for production. Test the exact claims from the supported integration; do not invent a subject string from memory.
Reusable workflows add another trust question: which calling repository and which reusable workflow file should be accepted? GitHub exposes additional claims and supports subject customization in some configurations. Bind both caller and trusted workflow where the platform permits, and review changes to that workflow like cloud IAM changes.
Pin the code that receives the identity
Any step in the job after token permission is available may be able to request or misuse credentials within process boundaries. Keep the credential-bearing job small, pin third-party actions to reviewed commit SHAs, minimize checkout credentials, and avoid running untrusted pull-request code in it.
jobs:
deploy:
environment: production
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@<reviewed-commit-sha>
- uses: cloud-provider/login@<reviewed-commit-sha>
with:
role: production-deployer
An action tag such as @v2 can move. Commit pinning makes the reviewed code immutable, while dependency-update automation can propose controlled upgrades.
Separate trust from authorization
The OIDC trust relationship answers who may assume a role. The role’s permissions answer what that session may do. Use one narrowly scoped role per environment and workload rather than a shared organization-wide deployer. Apply session duration limits, resource conditions, and cloud audit logging.
Do not put static keys back into the workflow as an “emergency fallback.” Define a separate, strongly authenticated break-glass role with approval, monitoring, expiry, and post-use review. Otherwise a dormant secret silently restores the credential risk OIDC was meant to remove.
Forks, pull requests, and environments change the subject
Workflows triggered from forks have different secret and permission behavior, but treating that as the sole boundary is unsafe. Never let untrusted PR code flow into a privileged pull_request_target deployment job. Separate build/test artifacts from promotion, verify artifact digest and provenance, and require a trusted event for the credential-bearing stage.
GitHub Environments can require approval before a job starts and can restrict branches. Cloud policy should still validate claims; UI approval is one layer, not a substitute for the provider’s trust conditions.
Verify and monitor the exchange
Test expected success plus wrong repository, branch, tag, environment, workflow, audience, and fork contexts. Confirm sessions expire, permissions are least-privilege, and revoking the trust relationship stops new exchanges. Correlate GitHub run IDs with cloud audit sessions using supported session names or tags.
OIDC reduces secret lifetime from months to minutes. Its security comes from a narrow, testable federation contract—not from the absence of a value in the repository’s Secrets page.
Related:
- How to Back Up and Restore Kubernetes etcd Without Creating a False Recovery Plan
- Fixing Prometheus Cardinality Explosions Before They Exhaust Memory and Storage
Sources: