Container security is a critical aspect of modern application deployment. Vulnerable container images can expose your applications to serious security risks, making regular vulnerability assessment essential for maintaining a secure infrastructure.
Microsoft Defender for Cloud provides powerful built-in capabilities to scan and assess vulnerabilities in container images stored in Azure Container Registry (ACR). This guide will walk you through the process of identifying vulnerabilities, understanding their impact, and automating the review process using Kusto queries.
Prerequisites
Before you can effectively monitor container vulnerabilities, you need to configure Microsoft Defender for Cloud properly:
1. Enable Microsoft Defender for Cloud
First, ensure Microsoft Defender for Cloud is enabled on your Azure subscription. Defender for Cloud provides the vulnerability assessment capabilities we’ll be using throughout this guide.
2. Configure the appropriate Defender plan
To scan container images in Azure Container Registry, you need one of the following plans:
- Microsoft Defender for Containers (recommended): Provides comprehensive container security including vulnerability assessment, runtime protection, and Kubernetes security
- Microsoft Defender CSPM: Includes agentless container vulnerability assessment as part of cloud security posture management
3. Enable agentless container vulnerability assessment
Navigate to Microsoft Defender for Cloud > Environment Settings > Your Subscription > Settings & monitoring and ensure the Enables agentless vulnerability assessment for registry images is enabled.
Understanding vulnerability data structure
Microsoft Defender for Cloud stores vulnerability assessment results in the Azure Resource Graph, which you can query using Kusto Query Language (KQL).
Each vulnerability is stored as a sub-assessment under the main security assessment, containing details about:
- CVE information: Common Vulnerabilities and Exposures identifiers and descriptions
- Affected packages: Software components with vulnerabilities
- Severity levels: Critical, High, Medium, or Low
- Fix information: Available patches or version upgrades
- Image metadata: Registry, repository, and tag information
Query ACR image vulnerabilities
Here’s a Kusto query to retrieve vulnerability information from your Azure Container Registry:
securityresources
| extend tags = properties.additionalData.artifactDetails.tags[0]
| extend artifactDetails = properties.additionalData.artifactDetails
| extend image = strcat(artifactDetails.registryHost, '/', artifactDetails.repositoryName, ':', tags)
| where type == 'microsoft.security/assessments/subassessments'
| where properties.resourceDetails.ResourceName == 'acrmydev001'
| where properties.status.code <> 'Healthy'
| project image,
displayName = properties.displayName,
cveDescription = properties.additionalData.cveDescriptionAdditionalInformation,
severity = properties.additionalData.vulnerabilityDetails.severity,
packageName = properties.additionalData.softwareDetails.packageName,
version = properties.additionalData.softwareDetails.version,
fixedVersion = properties.additionalData.softwareDetails.fixedVersion,
lastModifiedDate = properties.additionalData.vulnerabilityDetails.lastModifiedDate
replace
'acrmydev001'with the name of your Azure Container Registry.

Correlate vulnerabilities with deployed applications
Identifying vulnerabilities is only the first step. Understanding which applications are actively using vulnerable images is crucial for prioritizing remediation efforts. While Microsoft Defender for Cloud provides built-in monitoring for Azure Kubernetes Service (AKS) clusters, Azure Container Apps require a custom approach.
Query vulnerable images in Azure Container Apps
The following query joins vulnerability data with Azure Container Apps to identify active security risks in your deployed applications:
securityresources
| extend tags = properties.additionalData.artifactDetails.tags[0]
| extend artifactDetails = properties.additionalData.artifactDetails
| extend image = strcat(artifactDetails.registryHost, '/', artifactDetails.repositoryName, ':', tags)
| join kind=inner (resources
| where type == 'microsoft.app/containerapps'
| extend image = tostring(properties.template.containers[0].image))
on `$left.image == `$right.image
| where type == 'microsoft.security/assessments/subassessments'
| where properties.resourceDetails.ResourceName == 'acrmydev001'
| where properties.status.code <> 'Healthy'
| project image,
app = name1,
displayName = properties.displayName,
cveDescription = properties.additionalData.cveDescriptionAdditionalInformation,
severity = properties.additionalData.vulnerabilityDetails.severity,
packageName = properties.additionalData.softwareDetails.packageName,
version = properties.additionalData.softwareDetails.version,
fixedVersion = properties.additionalData.softwareDetails.fixedVersion,
lastModifiedDate = properties.additionalData.vulnerabilityDetails.lastModifiedDate
replace
'acrmydev001'with the name of your Azure Container Registry.

Automating vulnerability monitoring
Regular monitoring of container vulnerabilities is essential for maintaining security. You can automate this process using Azure CLI and GitHub Actions to run scheduled vulnerability assessments.
Setting up automated monitoring with GitHub Actions
Here’s a GitHub Actions workflow that monitors ACR vulnerabilities nightly:
| |
This workflow logs into Azure, runs the Kusto query to check for vulnerabilities, and fails the job if any are found, providing a initial report.
Cheers,
Lucas