Description
The azureManagedIdentity auth provider in Ratify v1.4.0 panics with a nil pointer dereference on every verification request. This means any cluster using azureManagedIdentity for the ORAS store auth provider will have Ratify in a CrashLoopBackOff state, causing Gatekeeper's ExternalData calls to time out and — depending on the failurePolicy — silently admit all images including unsigned/unverified ones.
Affected Versions
- Ratify
v1.4.0 (Helm chart 1.15.0)
Steps to Reproduce
- Install Ratify on AKS using the Helm chart with
azureManagedIdentity auth:
spec:
name: oras
parameters:
authProvider:
name: azureManagedIdentity
clientID: <kubelet-identity-client-id>
- Deploy a Gatekeeper
ConstraintTemplate that calls the ratify-provider ExternalData provider.
- Apply any Kubernetes workload (Deployment, Pod, etc.) — triggering Ratify verification.
- Ratify crashes immediately.
Observed Behavior
Ratify pod enters CrashLoopBackOff after the first admission webhook is triggered. Logs show:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x...]
goroutine ... [running]:
github.com/notaryproject/ratify/pkg/common/oras/authprovider/azure.(*MIAuthProvider).Provide(...)
pkg/common/oras/authprovider/azure/azureidentity.go:159
Line 159 is:
registryHost, err := d.registryHostGetter.GetRegistryHost(artifact)
Root Cause
The MIAuthProvider struct declares a registryHostGetter field:
type MIAuthProvider struct {
registryHostGetter RegistryHostGetter // declared here
tenantID string
clientID string
// ...
}
However, the Create() factory function never initializes registryHostGetter:
func (s MIAuthProviderFactory) Create(authProviderConfig AuthProviderConfig) (AuthProvider, error) {
conf, ok := authProviderConfig.(AzureMIAuthProviderConf)
// ...
return &MIAuthProvider{
tenantID: tenantID,
clientID: clientID,
// registryHostGetter is MISSING — left nil
}, nil
}
When Provide() is called, d.registryHostGetter is nil, causing the panic at line 159.
Expected Behavior
Create() should initialize registryHostGetter with the default implementation:
return &MIAuthProvider{
tenantID: tenantID,
clientID: clientID,
registryHostGetter: &defaultRegistryHostGetterImpl{}, // ADD THIS
}, nil
Security Impact
While Ratify is in CrashLoopBackOff, the Gatekeeper ExternalData provider ratify-provider is unreachable. If the ConstraintTemplate or the ExternalData Provider CR has failurePolicy: Ignore (the default), all images — including unsigned, unverified, or malicious ones — will be admitted to the cluster without any signature verification. This completely defeats the purpose of deploying Ratify.
Workaround
Switch the ORAS store to use k8Secrets auth instead:
# Get an ACR token (valid ~3h)
ACR_TOKEN=$(az acr login --name <acr-name> --expose-token --output tsv --query accessToken)
# Create a Kubernetes docker-registry secret
kubectl create secret docker-registry ratify-acr-secret \
--namespace gatekeeper-system \
--docker-server=<acr-name>.azurecr.io \
--docker-username=00000000-0000-0000-0000-000000000000 \
--docker-password="$ACR_TOKEN" \
--dry-run=client -o yaml | kubectl apply -f -
# Recreate the Store CR with k8Secrets
kubectl delete store store-oras -n gatekeeper-system --ignore-not-found
kubectl apply -f - <<EOF
apiVersion: config.ratify.deislabs.io/v1beta1
kind: Store
metadata:
name: store-oras
namespace: gatekeeper-system
spec:
name: oras
parameters:
authProvider:
name: k8Secrets
secrets:
- registryUri: <acr-name>.azurecr.io
secretName: ratify-acr-secret
EOF
Note: the k8Secrets token expires after ~3h and must be refreshed.
Additional Context
- This affects any AKS deployment using Ratify with
azureManagedIdentity for ACR authentication.
- The bug is not related to the
clientID value or any environment variable — it is a structural omission in the factory function.
- Setting
AZURE_CLIENT_ID as an environment variable on the Ratify deployment does not fix the panic.
Description
The
azureManagedIdentityauth provider in Ratify v1.4.0 panics with a nil pointer dereference on every verification request. This means any cluster usingazureManagedIdentityfor the ORAS store auth provider will have Ratify in aCrashLoopBackOffstate, causing Gatekeeper'sExternalDatacalls to time out and — depending on thefailurePolicy— silently admit all images including unsigned/unverified ones.Affected Versions
v1.4.0(Helm chart1.15.0)Steps to Reproduce
azureManagedIdentityauth:ConstraintTemplatethat calls theratify-providerExternalData provider.Observed Behavior
Ratify pod enters
CrashLoopBackOffafter the first admission webhook is triggered. Logs show:Line 159 is:
Root Cause
The
MIAuthProviderstruct declares aregistryHostGetterfield:However, the
Create()factory function never initializesregistryHostGetter:When
Provide()is called,d.registryHostGetterisnil, causing the panic at line 159.Expected Behavior
Create()should initializeregistryHostGetterwith the default implementation:Security Impact
While Ratify is in
CrashLoopBackOff, the GatekeeperExternalDataproviderratify-provideris unreachable. If theConstraintTemplateor the ExternalDataProviderCR hasfailurePolicy: Ignore(the default), all images — including unsigned, unverified, or malicious ones — will be admitted to the cluster without any signature verification. This completely defeats the purpose of deploying Ratify.Workaround
Switch the ORAS store to use
k8Secretsauth instead:Note: the
k8Secretstoken expires after ~3h and must be refreshed.Additional Context
azureManagedIdentityfor ACR authentication.clientIDvalue or any environment variable — it is a structural omission in the factory function.AZURE_CLIENT_IDas an environment variable on the Ratify deployment does not fix the panic.