Find Vulnerabilities with Trivy and Publish Them in Azure DevOps

Onur Yaşar
adessoTurkey
Published in
4 min readJun 24, 2022

What is Trivy?

Trivy (tri pronounced like trigger, vy pronounced like envy) is a simple and comprehensive scanner for Container Images, Rootfs, Filesystem, and Git Repositories to detect vulnerabilities.

Why We Need Trivy?

A short-term problem we face is checking vulnerabilities in our container images, Git Repos and Filesystems. Some research needed to be done to find a suitable open source vulnerability scanner. And we met Trivy after a couple of research.

What Can Trivy Do?

In a simple way of explanation, Trivy can detect vulnerabilities of OS Packages and language-specific packages. Aside from that, it can also scan IaC files like Terraform and Kubernetes, and it can be pretty handy to detect risky configurations that can open the deployments for attacks.

How to Install Trivy?

Install Script
This script downloads Trivy binary based on your OS and architecture.

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s — -b /usr/local/bin v0.29.2

Homebrew
You can use homebrew on macOS and Linux.

brew install aquasecurity/trivy/trivy

Debian/Ubuntu
Add repository setting to /etc/apt/sources.list.d.

sudo apt-get install wget apt-transport-https gnupg lsb-release wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update sudo apt-get install trivy

You can find more installation types in Trivy documentation.

How to Use Trivy?

Scan images for vulnerabilities and secrets
Simply specify an image name (and a tag).

trivy image <image>

to make it more specific.

trivy image --severity=HIGH,CRITICAL <image>

After implementing the Trivy in our deployment pipelines, we realized we need to make it more developer-friendly. Every time we had to check vulnerabilities for images, we had to find the relevant deployment and check the result of Trivy in the command prompt until we found a method which is to tell Trivy to output the results in a specific format i.e. JUnit. (Thanks to Liam Gulliver)

An example of the command prompt table.

Let’s make it eye-catching!
The azure pipeline can be like the screenshot below, but it can be modified optionally though.

In the first step, we have to specify the severity.

#you can change severity or add another level of vulnerability like LOW,MEDIUM if it's needed.
trivy image --severity HIGH,CRITICAL --format template --template "@template/junit.tpl" -o junit-report-high-crit.xml <image>

In the second step, we generate a task that creates the output as a result.

- task : PublishTestResult@2
inputs:
testResultsFormat: 'JUnit'
testResultsFiles: **/junit-report-high-crit.xml
mergeTestResults: true
failTaskOnFailedTests: false
testRunTitle: 'Trivy - Low and Medium Vulnerabilities'
condition: 'always()'

When the build is done, there will be a tab called Tests. It will show all the pre-defined vulnerability levels on Azure DevOps.

Details of a critical vulnerability can be shown below. It can be achieved just a simply clicking on one of them.

There is one last step for the job’s done. A template file should be added to get the output. You can find all the templates in the Trivy repository in its documents.

We put the junit.tpl file below in a template folder in our repository.

<?xml version="1.0" ?>
<testsuites>
{{- range . -}}
{{- $failures := len .Vulnerabilities }}
<testsuite tests="1" failures="{{ $failures }}" time="" name="{{ .Target }}">
{{- if not (eq .Type "") }}
<properties>
<property name="type" value="{{ .Type }}"></property>
</properties>
{{- end -}}
{{ range .Vulnerabilities }}
<testcase classname="{{ .PkgName }}-{{ .InstalledVersion }}" name="[{{ .Vulnerability.Severity }}] {{ .VulnerabilityID }}" time="">
<failure message={{escapeXML .Title | printf "%q" }} type="description">{{escapeXML .Description | printf "%q" }}</failure>
</testcase>
{{- end }}
</testsuite>
{{- end }}
</testsuites>

You can find report formats here: https://aquasecurity.github.io/trivy/v0.18.3/examples/report/#default-templates

Briefly, making the Trivy result is shown in a better way as easier as implementing it in your build pipelines.

References:

https://lgulliver.github.io/trivy-scan-results-to-azure-devops/

--

--