This check flags Azure Container Registries with the built-in admin user enabled. That single account is a shared root credential that bypasses Azure AD, leaks easily, and cannot be tied to an individual. Disable it with az acr update --admin-enabled false and use token-based or managed identity authentication instead.
The admin user on an Azure Container Registry (ACR) is one of those features that exists for convenience and ends up being a liability. It gives you a single username and password that can push and pull every image in the registry. It is fast to set up, which is exactly why it tends to survive long past the proof of concept where someone first turned it on.
This Lensix check (acr_adminuser) looks at each registry in your subscription and reports any that have the admin account active.
What this check detects
Every Azure Container Registry ships with an optional admin user. When enabled, ACR generates a username (which matches the registry name) and two passwords. Anyone holding those credentials can authenticate to the registry over Docker login and pull or push images.
The check inspects the registry's adminUserEnabled property. If it is set to true, the check fails. You can confirm the state of any registry yourself:
az acr show --name myregistry --query adminUserEnabled --output tsv
A result of true means the admin account is live and the check will flag it.
Note: The admin user is disabled by default on newly created registries. If it is on, someone enabled it deliberately, usually to get a quick docker login working without configuring proper identity.
Why it matters
The admin account is a shared credential, and shared credentials carry a specific set of problems that no amount of password rotation fully solves.
It bypasses Azure AD entirely
Normal ACR access can go through Azure AD identities, role assignments, and conditional access policies. The admin user sidesteps all of that. It is a static username and password pair that authenticates directly against the registry. None of your tenant's MFA, IP restrictions, or sign-in risk policies apply to it.
You lose attribution
Because everyone uses the same credentials, your audit logs cannot tell you who pushed a malicious or vulnerable image. When an incident happens and you need to answer "who changed this image and when," the admin user gives you nothing useful. The actor in the logs is just the registry's own name.
The credentials spread
Admin passwords have a habit of ending up in places they should not be: a CI pipeline variable, a Helm values file, a Slack message, a forgotten .env committed to a repo. Once leaked, the credential grants full push and pull on the entire registry. An attacker who pushes a backdoored version of an image you deploy can compromise everything downstream that pulls it.
Warning: Push access is the dangerous half. A leaked admin credential lets an attacker overwrite the latest tag of a production image with a poisoned one. The next deployment, or the next pod restart, pulls the malicious image and runs it inside your cluster.
A realistic attack chain
- A developer enables the admin user to get a build working quickly.
- The password is pasted into an unencrypted CI variable or a config file.
- An attacker gains read access to the repo or pipeline through an unrelated compromise.
- They use the admin credential to push a tampered image to a tag your deployment references.
- Your orchestrator pulls and runs the image, giving the attacker code execution inside your environment.
None of this triggers an Azure AD sign-in alert, because Azure AD was never involved.
How to fix it
The fix is to disable the admin user and replace it with an authentication method tied to an identity. Do the replacement first so you do not break anything that currently depends on the admin credential.
Step 1: Find what is using the admin credential
Before disabling anything, check where the credential is referenced. Search your CI/CD variables, Kubernetes image pull secrets, and Helm charts for the registry name as a username. A common giveaway in Kubernetes:
kubectl get secrets --all-namespaces \
-o jsonpath='{range .items[?(@.type=="kubernetes.io/dockerconfigjson")]}{.metadata.namespace}{"/"}{.metadata.name}{"\n"}{end}'
Inspect any pull secret pointing at your ACR and confirm whether it carries the admin username.
Step 2: Set up a replacement
For service-to-service access, attach a managed identity to whatever pulls the images and grant it the AcrPull role. For an AKS cluster:
# Attach the registry to an existing AKS cluster
az aks update \
--name myAksCluster \
--resource-group myResourceGroup \
--attach-acr myregistry
For a specific identity that only needs to pull:
ACR_ID=$(az acr show --name myregistry --query id --output tsv)
az role assignment create \
--assignee <principal-id> \
--role AcrPull \
--scope "$ACR_ID"
For CI pipelines that need scoped, revocable credentials without a full service principal, use ACR repository-scoped tokens:
az acr token create \
--name ci-push-token \
--registry myregistry \
--repository myapp content/write content/read \
--output json
Tip: Repository-scoped tokens let you grant write access to a single repository instead of the whole registry, and you can revoke or rotate them individually. They are the cleanest replacement when a managed identity is not an option.
Step 3: Disable the admin user
Danger: Disabling the admin user immediately invalidates those credentials. Any pipeline, pull secret, or service still authenticating with them will start failing. Confirm Step 1 and Step 2 are done before running this in production.
az acr update --name myregistry --admin-enabled false
Verify it took effect:
az acr show --name myregistry --query adminUserEnabled --output tsv
# expected: false
Console steps
- Open the Azure Portal and navigate to your Container Registry.
- Under Settings, select Access keys.
- Toggle Admin user to Disabled.
How to prevent it from happening again
Disabling it once is not enough. Someone will turn it back on the next time they hit an authentication snag, so codify the rule.
Azure Policy
Assign the built-in policy "Container registries should have the admin account disabled" with a Deny effect. That blocks anyone from creating or updating a registry with the admin user enabled:
az policy assignment create \
--name "deny-acr-admin-user" \
--policy "dc921057-6b28-4fbe-9b83-f7bec05db6c2" \
--params '{"effect":{"value":"Deny"}}' \
--scope "/subscriptions/<subscription-id>"
Terraform
If you manage registries as code, make the setting explicit so a drift or a manual change is obvious in the next plan:
resource "azurerm_container_registry" "main" {
name = "myregistry"
resource_group_name = azurerm_resource_group.main.name
location = azurerm_resource_group.main.location
sku = "Premium"
admin_enabled = false
}
CI/CD gate
Run a static scan against your IaC before merge. With a tool like Checkov, fail the pipeline on the relevant rule:
checkov -d . --check CKV_AZURE_137
And keep the Lensix acr_adminuser check running on a schedule so a manually enabled admin account on an existing registry gets caught even when it never went through your IaC.
Best practices
- Prefer managed identities. For anything running in Azure, a managed identity with
AcrPullremoves credentials from the equation entirely. - Scope access to the minimum. Use repository-scoped tokens when a workload only touches one repository. Do not hand out registry-wide push access by default.
- Separate push from pull. Build pipelines need push. Runtime workloads only need pull. Grant
AcrPullto clusters and reserveAcrPushfor CI. - Rotate and audit tokens. Token-based access is revocable per credential, which makes incident response far simpler than rotating a single shared admin password that everything depends on.
- Enable registry logging. Send ACR diagnostic logs to Log Analytics so push and pull events carry a real identity you can trace.
Note: The admin user is occasionally required for legacy tooling that cannot perform Azure AD authentication. If you genuinely cannot avoid it, treat the password as a high-value secret, store it in Key Vault, and put a calendar reminder on rotating it.
The short version: the admin user trades long-term security for short-term convenience. Disable it, move to identity-based authentication, and lock the setting down with policy so it stays disabled.

