Cloud login uses a long-lived credential instead of OIDC
ID |
oidc_preferred_over_pat |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Family |
SCM |
Tags |
ASVS50:v13.3.1, cicd-sec-06, cicd-security, reachable, security, spvs10-v3.2.1, spvs10-v3.2.2, supply-chain |
Description
Does a CI workflow authenticate to a cloud provider with a long-lived stored credential where short-lived federated OIDC is available?
A stored cloud credential — an AWS access key, a GCP service-account key JSON, an Azure service-principal secret — is a standing liability: it lives in your CI secrets, can leak (logs, forks, compromised actions), is rarely rotated, and grants persistent access until someone revokes it. GitHub Actions supports OpenID Connect (OIDC): with permissions: id-token: write the runner mints a short-lived token per run that the cloud exchanges for temporary credentials — no stored secret at all.
This check parses .github/workflows/*.yml and reports a step that calls a known cloud-auth action with a long-lived-credential input:
| Cloud | Long-lived input (flagged) | OIDC alternative |
|---|---|---|
AWS ( |
|
|
Google Cloud ( |
|
|
Azure ( |
|
|
GitHub-Actions only. GitLab (native id_tokens:) and Azure Pipelines (service connections) use different mechanisms and are out of scope here. The finding records whether id-token: write is already granted — if it is, the workflow is usually half-migrated and can drop the stored key.
|
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
permissions:
id-token: write
contents: read
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/ci
aws-region: eu-west-1
Security
Federated OIDC eliminates the most common cloud-credential exposure in CI: a long-lived key sitting in repository/organization secrets. Short-lived tokens are scoped per run and expire automatically, so a leak has a minutes-long blast radius instead of an open-ended one. This is a core CICD-SEC-6 (Insufficient Credential Hygiene) control.
Mitigation / Fix
Migrate the cloud login to OIDC:
-
Add
permissions: id-token: writeto the job (or workflow). -
AWS — configure an IAM OIDC identity provider for GitHub and pass
role-to-assumeinstead of access keys. See Configuring OIDC in AWS. -
Google Cloud — configure Workload Identity Federation and pass
workload_identity_providerinstead ofcredentials_json. -
Azure — configure a federated credential on the app registration and pass
client-id/tenant-id/subscription-idinstead ofcreds. -
Delete the now-unused access-key/secret from CI secrets.