How it works
The explanation, with examples you can run.
How secrets behave in CI
Repository, organisation and environment secrets are encrypted at rest and injected into jobs that ask for them. Known values are masked in logs. That is useful, but it is not a security boundary: any step in the job, including a third-party action, can read the value and send it anywhere. So give secrets only to the jobs that need them, and never to workflows that run untrusted code, such as builds of pull requests from forks.
How OIDC works
- The job has
permissions: id-token: write. - It asks GitHub's OIDC provider for a token. The token is a signed JWT whose claims describe the run, for example
sub: repo:my-org/my-app:environment:production, plusrepository,ref,environmentandaud. - The job sends that token to the cloud (AWS STS, Azure, Google Cloud workload identity federation, HashiCorp Vault and others).
- The cloud verifies the signature against GitHub's published keys and checks the claims against the role's trust policy.
- If they match, it returns temporary credentials for that role.
jobs: deploy: runs-on: ubuntu-latest environment: production # approval rules and environment secrets apply permissions: contents: read id-token: write # allow this job to request an OIDC token steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd # v6.3.0 with: role-to-assume: arn:aws:iam::123456789012:role/my-app-deploy-production aws-region: eu-west-1 - run: ./scripts/deploy.sh # uses the temporary credentialsWriting the trust policy
The trust policy is where the security lives. Match the audience (sts.amazonaws.com on AWS) and match sub as narrowly as you can: one repository, and for production one environment or branch. A wildcard over the whole organisation lets any repository, including a forgotten experiment, assume your production role. Give the role itself only the permissions the deploy needs.
Environments
A job that names an environment picks up that environment's secrets and protection rules: required reviewers, a wait timer, or a rule that only main may deploy. Because the environment name appears in the OIDC sub claim, the cloud role can require it, so a job that skipped the approval can't get production credentials.
When a secret leaks anyway
Revoke or rotate it at the source first, then remove it from logs and history, then check the provider's audit logs for use. More on that in the security path.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.