Skip to content
FreeNo sign-up

OIDC trust policy builder for GitHub, GitLab and Bitbucket

Pick your CI system and cloud, fill in the repository, and get the trust policy, provider settings or federated credential, plus the CI snippet that asks for the token. Covers GitHub's new subject format for repositories created after July 15, 2026.

Runs in your browser. Nothing you type is sent anywhere.

The tool is code on this page. It makes no network requests while you use it, stores nothing in cookies or local storage, and keeps working if you go offline after the page loads.

OIDC trust policy builder

Runs in your browser

CI system
Cloud

Repository

Subject format

Numeric IDs: gh api repos/OWNER/REPO --jq '.owner.id, .id'

Allow

Cloud settings

Result: GitHub Actions → AWS

Result: GitHub Actions, AWS

Before you apply it

  • Words in capitals, such as ACCOUNT_ID or PROJECT_ID, are placeholders: fill in the fields above or replace them before you apply the result.

IAM role trust policy

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
          "token.actions.githubusercontent.com:sub": "repo:kiteline/web-app:ref:refs/heads/main"
        }
      }
    }
  ]
}

GitHub Actions workflow

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: aws-actions/configure-aws-credentials@v6.3.0
        with:
          role-to-assume: arn:aws:iam::ACCOUNT_ID:role/web-app-deploy
          aws-region: us-east-1
      - run: aws sts get-caller-identity

Example values use Kiteline, a fictional company.

How to use it

  1. Choose the CI system and the cloud. The fields change to what that combination needs.
  2. Fill in the repository or project and, if you have them, the numeric IDs. Leave a field empty to get a placeholder in capitals.
  3. Read the notes under the result. They point out the settings that are easy to get wrong for this combination.
  4. Copy each block to where it belongs: the trust policy or credential to your cloud, the snippet to your CI file. Deploy from a test branch first.

The same without a browser

The values the builder asks for, looked up from a terminal.

GitHub: owner and repository IDs
gh api repos/OWNER/REPO --jq '.owner.id, .id'
GitHub: the subject format a repository uses now
gh api repos/OWNER/REPO/actions/oidc/customization/sub
Google Cloud: project number
gcloud projects describe PROJECT_ID --format='value(projectNumber)'
AWS: your account ID
aws sts get-caller-identity --query Account --output text

What the cloud checks in the token

Every CI system signs a short-lived token for the job. The cloud accepts it only if three things match: who issued it, who it was issued for, and what it describes.

  • iss

    Issuer

    Who signed the token: https://token.actions.githubusercontent.com for GitHub, your GitLab address, or a Bitbucket address that includes your workspace. The cloud trusts the issuer's published keys, not a stored password.

  • aud

    Audience

    Who the token is for. AWS expects sts.amazonaws.com, Azure recommends api://AzureADTokenExchange, and Google expects the provider's own address unless you allow another. A separate audience per receiving service keeps a token minted for one from working at another.

  • sub

    Subject and other claims

    Which job asked: repository, branch, tag or environment. This is the part to keep narrow. Prefer IDs over names where the cloud can check them, because a deleted name can be registered again by someone else.

GitHub's new subject format

GitHub now puts numeric IDs in the subject: repo:kiteline@123456/web-app@456789:ref:refs/heads/main instead of repo:kiteline/web-app:ref:refs/heads/main. Repositories created after July 15, 2026 use it automatically, as do repositories renamed or transferred after that date and those that opt in; older repositories keep the name-based format until then. A trust policy that only lists the old string fails on a new repository with Not authorized to perform sts:AssumeRoleWithWebIdentity. Choose Accept both while you switch, and add the IDs so the policy no longer depends on the name.

Read the full write-up

How Crunu handles this

The same check for secrets that aren't cloud keys

A Crunu service token can carry a CI binding (OIDC). The server then accepts the token only together with a JWT from GitHub Actions, GitLab CI or Bitbucket Pipelines whose claims match your rules for repository, branch and environment. GitHub rules match individual claims, so the new subject format doesn't break them, and adding the repository and owner IDs pins a token to one repository. A replayed JWT is refused.

Read about CI bindings
Example. Kiteline is a fictional company.

Questions about this tool

Found a case the tool gets wrong? Write to support@crunu.com

Why does a new repository fail with Not authorized to perform sts:AssumeRoleWithWebIdentity?

A likely cause is GitHub's new subject format. Repositories created after July 15, 2026 get a sub with numeric IDs, so a policy that lists only repo:OWNER/REPO:… no longer matches. Choose the new or both formats here, or match repository_id and repository_owner_id instead.

Can I use a wildcard like repo:my-org/*?

It makes the error go away and gives the role to every repository, branch, pull request run and workflow in the organization, including ones created later. For anything that can deploy, match one repository by ID and a protected branch or an environment with reviewers.

Branch or deployment environment?

For production, an environment. A branch subject matches any workflow run on that branch, including a workflow file someone changed there; an environment can require reviewers before a job that uses it starts.

Does the builder create anything in my cloud account?

No. It only produces text in your browser. Nothing is sent to AWS, Google, Microsoft or us; you apply the result yourself.

Why can't Bitbucket Pipelines sign in to Azure here?

Bitbucket's subject includes a step UUID that changes on every run, and Azure federated credentials accept only one exact subject. AWS and Google Cloud can match patterns or individual claims, so they work.

When the values need a home

Crunu is a vault for your team's environment variables and keys. Values are encrypted on your devices, so the server stores them only as ciphertext. Free during early access.