Part 1 – Quick look at CICD Integration in Azure Security Center to scan your docker image

If you are working in a cyber-security field where DevOps is involved, you probably heard about shift-left security. Shift-left security is just basically to move security assessment or verification sooner in the development process so you wouldn’t waste time to remediate security findings before the product or application is released to the production environment.

Specific to Azure, the new CI/CD integration to scan container images in Azure Security Center has come to my attention. In this article, let’s explore this feature and how to perform a PoC to demonstrate it to your team or customer. The article will also provide step-by-step guidance on how to make the PoC done.


As containerization is getting involved heavily these days building a safe docker image for your DevOps team is very important. The question is – how do we ensure that the docker image is assessed before it is published to a container registry.

The above diagram provides a very high-level overview of the docker image vulnerability scanning pipeline. The docker is scanned by a vulnerability scanner. Depending on the result (e.g. no High and Medium severity is considered Safe) the docker image is re-routed to the relative repositories.

In this article, what we will be doing is as follows:

You need basic knowledge of Azure Security Center, Azure CLI, and GitHub Workflow to complete this PoC deployment.

Step 1 – Create an Azure Container Registry

You can create a new Azure Container Registry (ACR) from Azure Portal. For quick deployment, use Azure CLI:

az group create --name $RG_NAME --location $LOCATION
az acr create --resource-group $RG_NAME --name $ACR_NAME --sku Basic

If you haven’t registered Microsoft.ContainerRegistry provider yet Azure will help do that for you.

Step 2 – Enable Azure Defender for Container 

Again you can enable Azure Defender from Azure Portal. However, for quick deployment let’s use Azure CLI:

az security pricing create -n ContainerRegistry \
                           --tier 'standard'

Step 3 – Create a vulnerable docker image

This is an important step. In this step, you are going to need to create a vulnerable docker image by composing a bad Dockerfile. You won’t build and publish to the newly created ACR. Instead, you only need to prepare a Dockerfile first.

One of the very common findings most commercial vulnerability assessment tools list is out-of-date/vulnerable packages. In this sample, I will install a vulnerable Firefox version 88.0.1 in an Ubuntu 18:04. Below is the sample Dockerfile:

FROM ubuntu:18.04

ARG firefox_version="88.0.1"

RUN apt-get update \
    && apt-get install -y wget \
    && rm -rf /var/lob/apt/lists/*
## Install Firefox 88.0.1
RUN apt-get purge firefox \
    && apt-get purge firefox \
    && apt-get install libgtk-3-0 -y \
    && apt-get install libx11-xcb1 -y \
    && apt-get install libdbus-glib-1-2 -y \
    && apt-get install libxt6 -y \
    && wget${firefox_version}/linux-$(uname -m)/en-US/firefox-${firefox_version}.tar.bz2 \
    && tar xvf firefox-${firefox_version}.tar.bz2 \
    && mv firefox /opt/ \
    && ln -s /opt/firefox/firefox /usr/bin/firefox

CMD ["bash"]

The goal here is to see if the vulnerability assessment result includes both Ubuntu and Firefox 88.0.1 packages.

Step 4 – Set up required secrets

You can use plain text for testing purposes but I’d recommend following best practices in using and securing secrets. In this article, we are going to need 4 secrets:


For the first two, you can retrieve from Azure Portal or by using the following Azure CLI command:

az acr credential show -n $ACR_NAME

You can get authentication token and connection string from Azure Security Center > Pricing & settings > your subscription. On the Settings page, click Integrations > Configure CI/CD integration. On the right panel select the ASC default workspace region and copy the authentication token and connection string:

Once you have all value needed, go to create secret in GitHub. You can refer to this article for information about creating and managing Github Secret.

Step 5 – Create GitHub Action

In this step, we are going to build a single job that does the following things:

To achieve that, we will use the following Github actions:

To know more details of what each action does, just go to each link.

Here is the pipeline file you’d need for the PoC.

# This is a basic workflow to help you get started with Actions

name: Sample workflow to scan image and publish to Azure Container Registry

# Controls when the workflow will run
  # Triggers the workflow on push or pull request events but only for the master branch
    branches: [azsec-patch-1]
    branches: [azsec-patch-1]

    runs-on: ubuntu-latest
      ACR_REPO_NAME: azsec-firefox
      - name: Checkout sample Dockerfile
        uses: actions/checkout@v2
          ref: azsec-patch-1
      - name: Build a sample Docker image with Firefox 
        run: |
          docker build -t ${{ env.ACR_SERVER }}/${{ env.ACR_REPO_NAME }}:${{ github.sha }} --file Dockerfile
      - name: Scan Docker image using Azure Container Scan action
        uses: Azure/container-scan@v0
        id: container-scan
        continue-on-error: true
          image-name: ${{ env.ACR_SERVER }}/${{ env.ACR_REPO_NAME }}:${{ github.sha }}
          # run-quality-checks provides CIS benchmark assessment
          run-quality-checks: true
      - name: Login to Azure Container Registry
        uses: Azure/docker-login@v1
          username: ${{ secrets.ACR_USERNAME }}
          password: ${{ secrets.ACR_PASSWORD }}
      - name: Push scanned image to ${{ env.ACR_REPO_NAME }}
        run: |
          docker push ${{ env.ACR_SERVER }}/${{ env.ACR_REPO_NAME }}:${{ github.sha }}
      - name: Post result status to Azure Security Center
        uses: Azure/publish-security-assessments@v0
          artifact-type: containerImage
          scan-provider: trivy
          connection-string: ${{ secrets.ASC_CONNECTION_STRING }}
          subscription-token: ${{ secrets.ASC_AUTH_TOKEN }}
          # Do not modify ${{ steps.container-scan.outputs.scan-report-path }} as it uses this path by default in Version 0.1
          scan-results-path: ${{ steps.container-scan.outputs.scan-report-path }}

If you aren’t familiar with Github Action, here is the quickstart for GitHub Actions you can quickly set up a GitHub repository and create a workflow then use the pipeline file above. Once the first commit is created it will trigger the pipeline and you will see all the tasks run.

Below is the screenshot that shows you the vulnerability assessment result from the sample docker image:

Step 6 – Verify and review vulnerability assessment results.

Until now you have done the PoC. But you still would want to show your team and manager how the integration looks like.  Now go to Azure Security Center > Recommendations. Search for Vulnerabilities in Azure Container Registry images should be remediated (powered by Qualys). Note that there is nothing to do with Qualys in this article. The scanner we use in our work is Trivy – an open-source container vulnerability assessment built by Aqua.

From the Azure Security Center recommendation page, click your Azure Container Registry there is a column named CI/CD Critical Finding which tells you that images in those repositories have been scanned using the GitHub actions.

Click a repository you will see CI/CD Scan Findings column which tells you that there is a finding found in the respective image.

And when you click a specific image, look for a tooltip icon next to CI/CD Scan Finding there’s information about the scan result.

Step 7 – Upload the vulnerability assessment result to an Azure Storage Account

[Updated 07/31 4:00 PM PST] You may need to store vulnerability assessment result in an Azure Storage account for the following reasons:

  • Storage vulnerability assessment results as records for further review
  • Trigger Azure Function or Azure Logic App for notification to DevOps or SecOps team.
  • Decide what to do next for the scanned docker image (e.g. move them to another repository/container registry where they need reviewing)

Check it out this article for completing step 7


As you can see from the demonstration the CI/CD integration kind of supports your container pipeline. There are several limitations at this moment. For example, you can’t see the findings from Azure Security Center. Remember that Qualys and Trivy are two different tools. We don’t know whether they share a similar scanning engine or vulnerability database or not. Also, to find the result or reference link you must go to Qualys’s recommendation.

Another issue would be that the vulnerability assessment result doesn’t meet my expectation. I thought it would list security vulnerabilities of my Firefox packages. I will dig into it more and will have an update if I find something.

There are some references for you to read further:

This entry was posted in Secure Development and tagged , . Bookmark the permalink.

2 Responses to Part 1 – Quick look at CICD Integration in Azure Security Center to scan your docker image

  1. Pingback: Upload container vulnerability assessment result to Azure Storage Account -Microsoft Azure Security Randomness

  2. Pingback: Notify container image vulnerability assessment result to email using Azure Logic App -Microsoft Azure Security Randomness

Leave a Reply

Your email address will not be published. Required fields are marked *