Safeguard
Security Guides•

What does a GitHub Actions OIDC sub claim look like?

The sub claim in a GitHub Actions OIDC token names the repo plus a branch, environment or pull request. See each format and how to pin a cloud role to it.

Safeguard Security Team
4 min read

The sub claim is the subject line of a GitHub Actions OIDC token. It names the repository and the trigger, such as a branch, an environment or a pull request. Your cloud role trust policy compares it to a pattern you wrote, so the exact format decides who can assume the role.

What is the sub claim?

When a workflow job asks GitHub for an OIDC token, GitHub signs a short JWT that carries several claims. Two matter most for access: aud, which says who the token is for, and sub, which says who is asking. GitHub's documentation describes sub as the subject the cloud provider checks against the conditions on the cloud role.

Think of it as a label your cloud account reads before it hands out temporary credentials. If the label is loose, many jobs can match. If it is exact, only one kind of job can.

The formats, side by side

GitHub documents three default shapes. Which one you get depends on how the job was triggered and whether it references an environment.

Triggersub format
Job references an environmentrepo:ORG/REPO:environment:NAME
Pull request event (no environment)repo:ORG/REPO:pull_request
Branch push (no environment)repo:ORG/REPO:ref:refs/heads/BRANCH

Note the precedence. When a job references an environment, the environment name appears in the claim. The branch name appears only if the job does not reference an environment. A deploy job that targets a protected environment therefore presents a different subject than the same repository's test job on the same branch.

Newer repositories use an immutable format

GitHub's docs state that repositories created after 15 July 2026 use an immutable default subject that includes the owner and repository IDs, for example repo:OWNER@OWNER-ID/REPO@REPO-ID:ref:refs/heads/BRANCH. Repositories created before that date keep the earlier format unless you opt in. Renames and transfers after that date also move to the immutable format. GitHub Enterprise Server is not part of that rollout.

The practical point: copy the trust condition from a real token or from the current docs, not from an old blog post or a template written for the older format.

How to pin a role to the right subject

  1. Decide what should be allowed to deploy: one branch, one environment, or release tags.
  2. Prefer an environment for deploy jobs, because environments can carry protection rules. GitHub recommends adding protection rules that restrict which branches and tags can deploy when you use environments in OIDC policies.
  3. Write the trust condition as an exact match on sub, not a wildcard.
  4. Keep the audience condition too. For AWS with the official action, the audience is sts.amazonaws.com.
  5. Test with a throwaway workflow and read the assume role result before you rely on it.

For AWS, a condition limiting access to one branch looks like this:

"Condition": {
  "StringEquals": {
    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
    "token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:ref:refs/heads/main"
  }
}

Why wildcards deserve a second look

GitHub's AWS guide shows a StringLike example with repo:octo-org/octo-repo:*. It notes that this allows any branch, pull request merge branch or environment in that repository to assume the role. That may be what you want for a read only role. It is rarely what you want for a role that can write to production. The same guide says you must define at least one condition so untrusted repositories cannot request access tokens.

Quick check

Does the sub claim include the branch when I use an environment?

No. Per GitHub's documentation, the branch name appears only if the job does not reference an environment. With an environment, the claim carries the environment name.

Is a wildcard in the sub condition ever fine?

Sometimes, for roles with narrow read access. Treat it as a deliberate choice, since it lets every branch, pull request and environment in the repository match.

Safeguard does not manage your cloud accounts. It scans your code and dependencies, applies policies and gates on pull requests, and automates compliance evidence. You can try a free scan at gold.safeguard.sh/scan.

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.