Back to blog
AzureBest PracticesCloud SecurityCompute & ContainersOperations & Compliance

Azure Container Registry Allows Anonymous Pull: Risks and Remediation

Learn why anonymous pull access on Azure Container Registry is a security risk, how to disable it with CLI, Terraform, and Bicep, and how to prevent it with policy.

TL;DR

This check flags Azure Container Registries that have anonymous pull access enabled, which lets anyone on the internet download your container images without authentication. Disable it with az acr update --name <registry> --anonymous-pull-enabled false unless you are intentionally hosting public images.

Azure Container Registry (ACR) supports an anonymous pull mode that allows unauthenticated clients to pull images from your registry. It exists for a legitimate reason: distributing public images, sample apps, or open source artifacts where you do not want to force consumers to log in. The problem is that this setting is registry-wide, so once it is on, every repository in that registry becomes readable by anyone who knows or can guess the registry name.

This Lensix check, acr_anonymouspull, fires when a registry has anonymous pull enabled. For most teams this is a misconfiguration rather than a deliberate choice, and it is worth treating as a high-priority finding.


What this check detects

The check inspects the anonymousPullEnabled property on each Azure Container Registry in scope. When that property is set to true, the registry permits pull operations without any credentials or token. No Azure AD identity, no admin user, no scope-bound token is required.

Note: Anonymous pull is only available on the Standard and Premium ACR tiers. Push operations always require authentication regardless of this setting, so anonymous access is strictly read-only. That limits the blast radius but does not eliminate it.

You can confirm the current state of a registry with a single CLI call:

az acr show \
  --name myregistry \
  --query "anonymousPullEnabled" \
  --output tsv

A return value of true means the check should be failing for that registry.


Why it matters

Container images are not just inert binaries. They frequently contain far more than the application code you intended to ship, and anonymous pull hands all of it to anyone who asks.

Leaked secrets and configuration

Build pipelines routinely bake things into images that should never leave your environment: hardcoded API keys, database connection strings, internal hostnames, private CA certificates, and .env files copied in during a careless COPY . .. With anonymous pull enabled, an attacker can pull the image, run docker history and docker save, and extract every layer to comb through your filesystem at leisure.

Reconnaissance and supply chain mapping

Even a clean image reveals your tech stack, base images, internal package registries, dependency versions, and naming conventions. That is a gift to an attacker who is trying to find a foothold. Knowing you run a specific outdated framework version turns a broad scan into a targeted exploit.

Guessable registry names

ACR login servers follow the predictable <name>.azurecr.io pattern. Many organizations name registries after the company, product, or environment, so acmeprodregistry.azurecr.io is not hard to guess. Once anonymous pull is on, you are relying on obscurity, and obscurity is not a control.

Warning: Anonymous pull is enabled at the registry level, not per repository. You cannot expose a single public image while keeping the rest private. If even one repository in the registry holds sensitive images, enabling anonymous pull exposes all of them.

Image tampering through cache poisoning

While anonymous users cannot push images, a publicly readable registry feeds into broader risks. If downstream consumers pull images by mutable tag and you have weak content trust, an attacker who later compromises any push credential can swap the contents of a tag your customers already trust. Public readability makes it trivial for them to study exactly which tags and digests are in use.


How to fix it

The fix is straightforward in the common case: disable anonymous pull. Before you do, confirm the registry is not intentionally serving public content, because turning this off will break unauthenticated pulls immediately.

Danger: Disabling anonymous pull breaks any client that currently pulls without credentials, including public CI jobs, customer environments, or open source users. Check who consumes the registry before flipping this, or you may cause an outage outside your own walls.

Option 1: Azure CLI

az acr update \
  --name myregistry \
  --anonymous-pull-enabled false

Verify the change took effect:

az acr show \
  --name myregistry \
  --query "anonymousPullEnabled" \
  --output tsv
# expected output: false

Option 2: Azure Portal

  1. Open the Container registries blade and select the affected registry.
  2. Under Settings, choose Properties.
  3. Find the Anonymous pull access toggle and set it to Disabled.
  4. Click Save.

Option 3: Terraform

If you manage ACR with Terraform, set anonymous_pull_enabled explicitly so drift does not creep back in:

resource "azurerm_container_registry" "main" {
  name                = "myregistry"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  sku                 = "Premium"

  anonymous_pull_enabled = false
}

Option 4: Bicep

resource registry 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
  name: 'myregistry'
  location: location
  sku: {
    name: 'Premium'
  }
  properties: {
    anonymousPullEnabled: false
  }
}

If you genuinely need public images

Sometimes anonymous pull is the right call, for example when distributing open source images. In that case, do not put public images in the same registry as private ones. Create a dedicated registry that contains only images you have explicitly cleared for public release, and harden your build process so secrets never reach those images.

Tip: For public distribution, consider Microsoft Artifact Registry patterns or a separate ACR that is reviewed and scanned on every push. Keep one registry public and intentional, and keep everything else private by default.


How to prevent it from happening again

Fixing one registry is fine, but the goal is to make anonymous pull impossible to enable by accident across the whole estate.

Azure Policy

Use Azure Policy to audit or deny registries that have anonymous pull turned on. A custom policy targeting the anonymousPullEnabled field gives you continuous enforcement:

{
  "policyRule": {
    "if": {
      "allOf": [
        {
          "field": "type",
          "equals": "Microsoft.ContainerRegistry/registries"
        },
        {
          "field": "Microsoft.ContainerRegistry/registries/anonymousPullEnabled",
          "equals": "true"
        }
      ]
    },
    "then": {
      "effect": "deny"
    }
  }
}

Assign it at the management group level so it covers every subscription, including ones created in the future. Start with an audit effect if you want visibility before you start blocking, then switch to deny once you have confirmed no legitimate registries depend on it.

CI/CD gates with policy-as-code

Catch the misconfiguration before it ever reaches Azure. If you deploy infrastructure through Terraform or Bicep, scan the plan in your pipeline. Tools like Checkov, tfsec, and OPA Conftest can fail a build when anonymous_pull_enabled is true.

# Run Checkov against Terraform plan output
checkov -d ./infra --framework terraform

Wire that into a required status check on your pull requests so no one can merge a registry definition that opens anonymous access.

Tip: Lensix continuously evaluates acr_anonymouspull across your subscriptions, so even configuration changes made outside your IaC pipeline (someone clicking the toggle in the portal during an incident) get caught and surfaced quickly.


Best practices

  • Private by default. Treat every registry as private unless there is a documented, reviewed reason for it to be public.
  • Separate public and private registries. Never mix images intended for public consumption with internal ones in the same ACR.
  • Use Azure AD authentication and tokens. Prefer Azure AD identities and scope-bound repository tokens over the admin user, and disable the ACR admin account entirely where you can.
  • Scan images for secrets and vulnerabilities. Run secret scanning and vulnerability scanning on every push so sensitive material never lands in an image in the first place.
  • Restrict network access. On Premium registries, use private endpoints and firewall rules to limit who can reach the registry at the network layer, adding defense in depth even if an access control is misconfigured.
  • Enable content trust and signing. Sign images and verify signatures on pull so consumers can detect tampering.
  • Audit registry settings continuously. Configuration drifts. Monitor anonymousPullEnabled and other registry properties on an ongoing basis rather than at deploy time alone.

Anonymous pull is a small toggle with an outsized impact. For the vast majority of registries it should be off, enforced by policy, and verified continuously. Reserve it for the rare case where you are deliberately publishing public images, and keep those images in a registry built for exactly that purpose.