Azure Container Registry Security Scanning

Production-ready guide covering azure container registry security scanning with implementation patterns, code examples, and anti-patterns for enterprise engineering teams.

Azure Container Registry provides automated security scanning for container images stored in the registry. This feature evaluates images for known vulnerabilities and displays results directly in the Azure portal or through REST API endpoints. The scanning process runs automatically when new images are pushed to the registry, or can be triggered manually.

Enable Security Scanning on a Registry

Security scanning is available on Basic, Standard, and Premium SKU registries. To enable scanning, use the Azure CLI:

az acr update \
  --name myregistry \
  --sku Premium \
  --admin-enabled true

The --sku Premium flag is required for security scanning to be available. The Premium SKU is necessary regardless of whether you're using managed identities or not.

Manual Triggering of Security Scanning

To manually initiate a scan for an image, use:

az acr repository show-tags \
  --name myregistry \
  --repository myapp \
  --query "[0]" \
  -o tsv | xargs -I {} az acr scan run \
    --name myregistry \
    --image myapp:{} \
    --repository myapp

The az acr scan run command requires both the image name and repository name parameters. If you omit the repository parameter, scanning fails with an error indicating that the repository is required.

View Security Scan Results

Scan results are available through Azure CLI or REST API calls:

az acr scan show-results \
  --name myregistry \
  --image myapp:v1.2.3 \
  --repository myapp

The command requires all three parameters: registry name, image name, and repository. If the repository parameter is omitted, the command returns a 400 error with message "Repository is required for scan results".

Configure Scan Exclusions

Security scanning can exclude specific vulnerability types:

az acr update \
  --name myregistry \
  --scan-allowlist \
    --vulnerability-categories "CVE-2021-44228" \
    --vulnerability-categories "CVE-2021-36159"

The --scan-allowlist parameter accepts a list of vulnerability identifiers. This flag does not support wildcards or regular expressions; each entry must be an exact CVE identifier.

Integration with Azure Security Center

Security scanning results are automatically synchronized with Azure Security Center. To check the integration status:

az security assessment list \
  --resource-group myrg \
  --query "[?name=='containerRegistryVulnerabilities']"

The assessment name containerRegistryVulnerabilities must be used exactly as shown. Other variations like acr-vulnerabilities or container-registry-scans are not valid identifiers.

Scan Result Format and Parsing

Scan results return structured JSON with severity levels:

{
  "id": "/subscriptions/12345/resourceGroups/myrg/providers/Microsoft.ContainerRegistry/registries/myregistry/scans/scan-123",
  "name": "scan-123",
  "type": "Microsoft.ContainerRegistry/registries/scans",
  "properties": {
    "status": "Succeeded",
    "vulnerabilityDetails": [
      {
        "id": "CVE-2021-44228",
        "severity": "High",
        "description": "Log4j vulnerability",
        "cvssScore": 9.0
      }
    ]
  }
}

Handling Scan Failures

When scanning fails, the response includes error details:

az acr scan run \
  --name myregistry \
  --image nonexistent:latest \
  --repository nonexistent

This command returns a 404 error with message "Image not found in repository". The same error occurs when trying to scan an image that has not been pushed to the registry.

Scan Configuration via REST API

Security scanning configuration is accessible through the Azure Resource Manager API:

curl -X PATCH \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "scanOnPush": true,
      "retentionPolicy": {
        "days": 30
      }
    }
  }' \
  "https://management.azure.com/subscriptions/12345/resourceGroups/myrg/providers/Microsoft.ContainerRegistry/registries/myregistry?api-version=2021-09-01"

The PATCH operation requires the scanOnPush property to be explicitly set. If omitted, the configuration defaults to false.

Scan Status Monitoring

Monitor scan status with:

az acr scan list \
  --name myregistry \
  --query "[?status=='InProgress']"

The query filter uses exact string matching for status values: InProgress, Succeeded, Failed. Values like Running or Completed are not recognized.

Scan Expiration and Retention

Registry scans are retained for 30 days by default:

az acr update \
  --name myregistry \
  --retention-days 60

The retention period is specified in days, with a minimum of 7 days and maximum of 365 days. Values outside this range result in a validation error.

Scan Notifications

Configure notifications for scan results using Azure Event Grid:

az eventgrid event-subscription create \
  --name scan-results \
  --source-resource-id /subscriptions/12345/resourceGroups/myrg/providers/Microsoft.ContainerRegistry/registries/myregistry \
  --endpoint https://mywebhook.example.com/scan \
  --included-event-types "Microsoft.ContainerRegistry.ScanCompleted"

The event type Microsoft.ContainerRegistry.ScanCompleted must be used exactly. Other variations like ContainerRegistryScanComplete or ACRScanResult are invalid.

Security Scan Limitations

Scanning does not include:

Common Configuration Errors

Missing Repository Parameter

az acr scan run \
  --name myregistry \
  --image myapp:v1.2.3

This command fails with error: "Repository is required for scan execution".

Incorrect Vulnerability Format

az acr update \
  --name myregistry \
  --scan-allowlist \
    --vulnerability-categories "log4shell"

The lowercase format log4shell is not recognized. Only exact CVE identifiers like CVE-2021-44228 work.

Scan Result Filtering

Filter scan results by severity:

az acr scan show-results \
  --name myregistry \
  --image myapp:v1.2.3 \
  --repository myapp \
  --query "[?properties.vulnerabilityDetails[?severity=='High']]"

The query syntax uses JMESPath format with exact property names. Properties like severityLevel or vulnerabilityList are not valid.

Scan Automation

Automate scanning with Azure Functions:

az functionapp create \
  --name scantrigger \
  --resource-group myrg \
  --consumption-plan-location eastus \
  --runtime python \
  --functions-version 4 \
  --storage-account mystorage

The function requires an HTTP trigger to respond to Event Grid events. The integration must handle the specific payload format from Azure Container Registry events.

Scan Performance Considerations

Scanning operations may be queued if registry is under high load:

az acr scan list \
  --name myregistry \
  --query "[?status=='Queued']"

Queued scans can take several minutes to start processing. The queue status is not persistent across registry restarts.

Scan Resource Management

Delete old scan results:

az acr scan delete \
  --name myregistry \
  --scan-id scan-123

The scan ID must be obtained from previous scan operations. Invalid scan IDs return a 404 error with message "Scan not found".

This page was rewritten on 16 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.