Something has to be the first credential.
"Just put it in Vault" is circular the moment you ask how the app authenticates to Vault. The fix: trust an identity the platform already vouches for.
CI → Vault via OIDC, no stored credential
1
CI requests an OIDC tokenfor this specific run
2
Issuer signs a JWTclaims: repo, branch, environment
3
Vault verifies claims
bound_claims: exact repo + branch4
Scoped token issuednothing was ever stored as a CI secret
One source of truth, many references
Vault→ GitHub Actions (OIDC)→ GitLab CI (ID tokens)→ Azure Pipelines (Key Vault link)→ Bitbucket (oidc: true)
Every platform holds a reference, never a copy — rotate once, correct everywhere instantly.
Secret zero should never be a secret you manage — it should be an identity the platform already establishes and vouches for automatically.