GCP Workload Identity Federation abuse
TL;DR: GCP Workload Identity Federation (WIF) lets external identities (OIDC tokens from GitHub Actions, AWS, Azure, or arbitrary OIDC providers) impersonate GCP service accounts without a long-lived JSON key. The trust decision is made by
attribute_conditionCEL expressions. Misconfigured conditions — e.g.,attribute.repository != ""instead ofattribute.repository == "org/repo"— let any identity matching the loose condition impersonate the service account. Pattern: identity-layer compromise of GCP without ever phishing a user. Companion to gha-oidc-sub-claim-wildcards and gcp-metadata-token-theft.
Why this matters
- WIF is the modern recommended way to authenticate CI/CD into GCP — rapidly replacing long-lived keys.
- The trust gate is a CEL expression the admin writes by hand. Easy to get wrong.
- Wrong WIF policies expose service-account-level access to anyone who can present a matching token.
- The blast radius is whatever IAM the service account has — often broad in CI/CD usage.
How WIF works
The flow:
- External workload (e.g., GitHub Actions) obtains an OIDC token from its identity provider (
token.actions.githubusercontent.com). - Workload presents the token to GCP’s STS endpoint with a target workload-identity-pool / provider.
- GCP validates the JWT signature against the provider’s JWKS.
- GCP evaluates the
attribute_conditionagainst the token claims. - If the condition passes, GCP issues a federated STS token.
- The STS token is exchanged for a service-account access token (if the SA’s IAM allows the
serviceAccountTokenCreatorfor the federated principal).
Two gates: the condition in WIF, and the IAM binding on the service account.
Common misconfigurations
Pattern A — Empty / too-loose condition
1
2
# Misconfigured
attribute_condition = "attribute.repository != ''"
Any GitHub repo can present a token with a non-empty repository attribute — i.e., every GitHub Actions runner. Combined with a service account that has any useful permission, anyone on GitHub can take over the SA.
Correct:
1
attribute_condition = "attribute.repository == 'my-org/my-repo'"
Pattern B — Wildcarded repository owner
1
attribute_condition = "attribute.repository.startsWith('my-org/')"
Any repo in my-org can impersonate, including fork-PRs that run workflows with elevated tokens. See gha-oidc-sub-claim-wildcards.
Pattern C — IAM binding too permissive
The SA’s IAM binding might be:
1
2
serviceAccount:my-sa@p.iam.gserviceaccount.com
-> principalSet://iam.googleapis.com/projects/.../locations/global/workloadIdentityPools/.../*
The /* allows any federated principal. Should be:
1
2
serviceAccount:my-sa@p.iam.gserviceaccount.com
-> principalSet://iam.googleapis.com/projects/.../locations/global/workloadIdentityPools/.../attribute.repository/my-org/my-repo
Pattern D — Audience misconfiguration
The audience parameter (Google’s WIF expects a specific audience). If the workload identity pool accepts the default audience without enforcement, tokens from other workloads that happen to target the same default can impersonate.
Recon approach
With read-only access in the target GCP project:
gcloud iam workload-identity-pools listgcloud iam workload-identity-pools providers list --workload-identity-pool=X- Examine each provider’s
attributeConditionandattributeMapping. gcloud iam service-accounts listand check IAM policy forprincipalSet://...bindings.
External recon: organisations sometimes publish WIF setup in Terraform on public GitHub. Search for google_iam_workload_identity_pool_provider configs.
Exploit shape
- Identify a target project’s WIF provider trusting GitHub.
- Observe the
attribute_condition. - Create a fork-PR or a new repo matching the condition.
- CI workflow uses
google-github-actions/authwith the target’s WIF config. - Obtain federated STS token, then SA access token.
- Operate as the SA.
Pacu and similar tools now have WIF audit modules.
Defensive baseline
- Conditions must be exact-match on
attribute.repository(andattribute.refif needed for branch-protection). - IAM bindings use principal, not
principalSet://, when targeting one repo. - Service account permissions are least privilege — don’t make CI SAs project-owner.
- WIF events appear in Cloud Audit Logs as
iamcredentials.googleapis.com/GenerateAccessTokenwith the federated subject. - Alert on first-time federated subjects per service account.
Workflow to study
- Create a GCP project, configure WIF pool + provider for GitHub Actions.
- Bind a SA with low-priv permissions.
- Author a GitHub Actions workflow using the WIF config.
- Run, observe the federated impersonation.
- Loosen the condition to
attribute.repository != ''; observe that any repo can now impersonate. - Read the audit log entries.
Related cloud federation attacks
- AWS IAM Roles Anywhere — see aws-iam-roles-anywhere-abuse.
- AWS OIDC federation for GitHub Actions — same misconfig class.
- Azure federated identity credentials — same shape; less well audited.
tj-actions/changed-filesstyle supply chain — see tj-actions-tag-mutation — touches WIF indirectly when the action is used as the WIF-token producer.