If an AWS deployment workflow works in an older GitHub repository but fails in a newly created one, inspect the OIDC subject before adding broader permissions. GitHub’s current documentation says repositories created after 15 July 2026 use a default subject that includes immutable owner and repository IDs.
That change makes a copied, name-only trust condition a possible mismatch. It is not evidence that OpenID Connect is unreliable, and replacing the condition with an unrestricted wildcard is the wrong repair. This guide describes a controlled diagnostic workflow, not a tested configuration for your AWS account.
Understand the two permissions decisions
GitHub Actions can request an OIDC token that AWS validates before granting a role session. This removes the need to store a long-lived AWS access key as a GitHub deployment secret.
There are still two separate gates. The role’s trust policy decides which identity may assume it. The role’s permissions decide what that session may do afterward. A successful sign-in with an overpowered role is not a secure outcome.
The official GitHub AWS OIDC guide specifies the provider URL as token.actions.githubusercontent.com and the audience as sts.amazonaws.com when using the official AWS credentials action.
Compare the subject formats exactly
For a branch-based workflow using the older default, a subject could look like this:
repo:example-org/example-api:ref:refs/heads/main
The immutable format adds the owner and repository IDs. The following values are fictional placeholders, not usable account details:
repo:example-org@123456/example-api@456789:ref:refs/heads/main
GitHub says repositories created before 15 July retain the previous format unless they opt in. Repository renames and transfers after that date also move to the immutable format. The rollout does not include GitHub Enterprise Server, so do not apply the public GitHub rule indiscriminately to a server installation.
Review your repository’s OIDC configuration and the expected identity context. If diagnostics are necessary, handle the JWT as a credential: never paste the raw token into a public issue, chat or build log. Record only the non-secret claim information needed to explain the policy mismatch.
Make the smallest trust-policy correction
For a deployment restricted to main, use an exact subject match alongside the expected audience. This illustrative condition fragment is not a complete IAM policy:
{
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub":
"repo:example-org@123456/example-api@456789:ref:refs/heads/main"
}
}
Replace all example names and IDs with the verified values for your repository. The surrounding trust policy must reference the correct AWS account’s OIDC provider and the appropriate role-assumption action. Separately limit the role’s permissions to the deployment resources it actually requires.
If the job uses a GitHub environment, its subject uses environment context rather than the branch-context example above. Match that actual subject and protect the environment with appropriate branch and approval restrictions. Do not copy a branch condition and assume it covers an environment job.
Diagnose failures in the right order
- No token request: confirm the deployment job has id-token: write. That permission enables token issuance; it does not itself grant permission to modify AWS resources.
- Role cannot be assumed: compare the provider, audience and complete subject, including IDs and environment context.
- Role assumed, deployment denied: review the resource action, resource identifier and role permissions rather than weakening the trust policy.
- Unexpected access succeeds: stop and tighten the trust boundary before expanding the migration.
Migrate without keeping a permanent back door
Start with a narrowly scoped test role and an approved workflow. Verify the caller identity and a harmless permitted operation. Then confirm that an unapproved branch or context cannot obtain the same deployment access. A positive test alone cannot demonstrate the restriction.
Inventory every consumer of the old access key before revoking it. An overlooked scheduled workflow may still depend on it. Once the approved consumers have moved and the replacement works, remove the obsolete secret and retire the key through your normal change process.
The related DevSecOps workflow evaluation is useful when assigning ownership across repositories, deployment tooling and security review. Keep the final evidence concise: expected subject, role scope, allowed and denied test results, and the old key’s retirement status.
Keep access evidence useful after a repository change
Consider a fictional agency with separate staging and production roles. An approved staging deployment should not gain production rights just because both workflows live in the same repository. Write down the expected identity context for each job and the exact resources its role can change. Test the two boundaries separately before moving both away from stored keys.
Keep the role name, repository identity, environment name, workflow reference and policy revision together in the change record. Those are operational identifiers, not a reason to retain the bearer token. A later repository rename or environment change can then be compared with the previously approved conditions without exposing credentials.
When a workflow fails, first identify whether it failed before role assumption or after receiving a session. Reproducing a harmless operation in the approved context is more informative than repeatedly retrying the full deployment. Record the denied action and resource, then ask the role owner for the minimum correction.
Finally, make one person responsible for reviewing old fallback keys and exceptional trust conditions. A migration is not complete while a forgotten credential still offers an unrelated route into the same resources.




