Skip to main content
cd ../config-traps
risk/register/renamed-github-repos-inherit-azures-oidc-trust.html
Azure Workload Identitycritical severityAzure AD Workload Identity Federation

Renamed GitHub Repos Inherit Azure's OIDC Trust

Severity
critical
Reviewed
12 Jul 2026
Remediation
~20 minutes
Overview

A Federated Identity Credential on an Azure Managed Identity keeps trusting a GitHub repository subject string long after that repository name is freed and reclaimed by an unrelated account. Azure AD's token exchange endpoint checks only the issuer, subject and audience tuple — not ownership continuity — so the new owner's workflow mints a valid OIDC token and inherits the identity's RBAC grants undetected.

Operational summary

At a glance

Symptom
The original GitHub organisation or repository is renamed or deleted and the freed name is re-registered by a different account.
Likely cause
A Federated Identity Credential's subject claim is bound to a mutable GitHub org/repo name rather than an immutable repository ID.
Impact
The new repository owner's Actions workflow mints an OIDC token matching the stale subject and exchanges it for the Managed Identity's Azure access token.
Verification signal
Re-run the detection test and a controlled negative-path test.
Safe correction
Pin trust to job_workflow_ref with a fixed commit SHA and audit federated credentials against GitHub's numeric repository_id, not display name.
Rollback or recovery
Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

The Trap

Federated Identity Credential subject binding to a GitHub repository by name rather than by its immutable repository ID.

The Default State

When you create a Federated Identity Credential on a User-Assigned Managed Identity or App Registration for GitHub Actions OIDC, the portal wizard writes the Subject identifier as repo:<org>/<repo>:ref:refs/heads/<branch> or repo:<org>/<repo>:environment:<name>. The Issuer is fixed at https://token.actions.githubusercontent.com and the Audience defaults to api://AzureADTokenExchange. Azure AD stores this as a static three-field tuple — issuer, subject, audience — and performs an exact string match against the sub, iss and aud claims presented in the client_assertion JWT during the OAuth2 exchange at /oauth2/v2.0/token. Nothing in that tuple references GitHub’s internal repository_id, and nothing re-validates ownership after the credential is created.

The Blast Radius

GitHub permits an organisation or repository name to be freed and immediately re-registered by an unrelated account the moment the original is renamed or deleted — a documented repojacking pattern. If your Federated Identity Credential still contains the old literal subject string, any new owner of that org/repo name — a different GitHub tenant, a separate business unit, or an external actor — can push a workflow run that mints an OIDC token with an identical sub claim. Azure AD’s token exchange endpoint has no visibility into GitHub’s repository lifecycle; it only checks the tuple match, so it issues a valid access token scoped to whatever role assignments the Managed Identity carries. The new owner inherits that RBAC, Key Vault access, or storage permission set, and Azure AD sign-in logs show nothing more suspicious than a routine federated token exchange from a trusted issuer.

The Lead Mechanic Fix

Audit every credential with az ad app federated-credential list –id <app-id> and cross-reference each subject string’s repository name against GitHub’s numeric repository_id via the REST API, not the display name. Where the workflow supports it, bind trust to the job_workflow_ref claim pinned to a specific reusable workflow path and commit SHA instead of a mutable branch ref, and scope Audience to a per-environment value rather than the shared default. Run a scheduled Azure Resource Graph query against federatedIdentityCredentials to flag any subject referencing a repository that no longer resolves under its original owner, and make credential removal a mandatory step in the repository transfer and deletion runbook, not an optional cleanup task.

03

Apply the safer control

Before you change production

Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.

Control to implement

Pin trust to job_workflow_ref with a fixed commit SHA and audit federated credentials against GitHub's numeric repository_id, not display name.

Validate the vendor-specific syntax in official documentation before applying it.

04

Verify, roll back or escalate

Verify

Re-run the detection test and a controlled negative-path test. Confirm the unsafe behaviour is blocked while approved traffic still succeeds.

Rollback

Restore the exported configuration if the new control blocks required production traffic, then narrow the policy before redeployment.

Escalate

Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.

After remediation

Further reading stays below the corrective workflow and is selected by platform, category and shared technical keywords.

Discover more

Connected KBY resources