Container image security with Wazuh and Trivy

Maintaining the security of containerized environments is an important part of modern IT infrastructure. Vulnerabilities in container images and runtime environments expose organizations to significant risks, which makes proactive vulnerability scanning an essential practice.
Trivy is an open source vulnerability scanner designed for containers, filesystems, and software dependencies. It supports a range of targets including Git repositories, Kubernetes deployments, and programming language dependencies (npm, pip, etc.).
Integrating Trivy with Wazuh enhances container security by detecting vulnerabilities in images and runtime environments, ensuring safer Kubernetes and Docker deployments. It also strengthens CI/CD pipelines by identifying security risks early in development, preventing vulnerable code from reaching production.
In this blog post, we explore how to leverage Trivy and Wazuh to implement effective container vulnerability scanning.
Infrastructure
To demonstrate the integration of Trivy and Wazuh for container vulnerability scanning, we use the following infrastructure:
Configuration
To configure this integration, we perform the following:
On the Ubuntu endpoint:
On the Wazuh server:
On the Wazuh dashboard:
Perform the following steps on the Ubuntu endpoint.
Follow the steps below to install Docker Engine and deploy container images on the Ubuntu endpoint.
Note: You need root user privileges to execute all the commands described below.
1. Update the list of available packages and their versions, and install the cURL package:
# apt update && apt install curl -y
2. Run the following commands to download and run the Docker installation script:
# curl -sSL https://get.docker.com/ | sh
3. Create and switch into a project directory ~/container_env
for the container environment using the following command:
# mkdir -p ~/container_env && cd ~/container_env
4. Create a configuration file docker-compose.yml
in the container_env
directory:
# touch docker-compose.yml
5. Copy and paste the configuration below into the docker-compose.yml
file. This configuration file defines a test environment with three services – a Python (FastAPI) service, a PostgreSQL database, and a Redis cache:
services: api: image: python:3.9-alpine db: image: postgres:alpine redis: image: redis:alpine
Note: You can configure the services further, however in this example, the focus is on pulling the base images python:3.9-alpine
, postgres:alpine
, and redis:alpine
. Trivy will scan these container images for vulnerabilities.
6. Run the command below to pull the container images using Docker Compose:
# docker compose pull
7. Verify that the container images are present:
# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE Postgres alpine 2bf60600670f 8 days ago 278MB Redis alpine ee33180a8437 5 weeks ago 41.4MB Python 3.9-alpine 8831b2c8c07c 2 months ago 49.1MB
Run the commands below to install Trivy on the Ubuntu endpoint.
1. Install the required dependencies:
# sudo apt-get install -y wget apt-transport-https gnupg lsb-release
2. Import the Trivy repository key:
# wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
3. Add the Trivy APT repository:
# echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
4. Update package lists:
# sudo apt-get update
5. Install the Trivy package:
# sudo apt-get install trivy
6. Verify that Trivy has been installed:
# trivy --version
Version: 0.59.1
Follow the steps below to create a bash script and configure the Wazuh Command module on the Ubuntu endpoint. The script detects existing container images on the endpoint and runs a vulnerability scan on each image using Trivy. The Wazuh Command module periodically executes the script at predefined intervals. Wazuh monitors the script output and treats it as log content for further analysis.
1. Create a custom script directory /var/ossec/custom-script/
and create a new file trivy_scan.sh
using the following command:
# mkdir /var/ossec/custom-script/ && touch /var/ossec/custom-script/trivy_scan.sh
2. Copy and paste the code below into the /var/ossec/custom-script/trivy_scan.sh
file:
#!/bin/bash # Copyright (C) 2015-2025, Wazuh Inc. # Directory to save the custom output template TEMPLATE_DIR="/tmp" TEMPLATE_FILE="$TEMPLATE_DIR/trivy-custom.tmpl" # Create the custom output template cat <<EOL > "$TEMPLATE_FILE" "Package","Version Installed","Vulnerability ID","Severity" {{- range \$ri, \$r := . }} {{- range \$vi, \$v := .Vulnerabilities }} "{{ $v.PkgName }}","{{$v.InstalledVersion }}","{{ $v.VulnerabilityID }}","{{$v.Severity }}","{{$v.Title }}" {{- end}} {{- end }} EOL # Retrieve list of container images (including both repository and tag) images=$(docker images --format "{{.Repository}}:{{.Tag}}") if [ -z "$images" ]; then echo "No images found. Exiting..." exit 1 fi # Loop through each container image and run Trivy scan for image in $images; do # Run Trivy scan on the current image using the custom output template trivy_output=$(trivy --scanners vuln i -q --format template --template "@/tmp/trivy-custom.tmpl" "$image") # Check if the scan was successful if [ $? -ne 0 ]; then echo "Error running Trivy scan on image $image. Skipping..." continue fi # Process Trivy output for the current image while IFS= read -r line; do # Prepend image name with "Trivy:", followed by image name and a comma formatted_line="Trivy:\"$image\",$line" # Print the formatted line with quoted image name echo "$formatted_line" done <<< "$trivy_output" done # Clean up the custom output template rm -f "$TEMPLATE_FILE"
This script sets up a custom output template for Trivy. Then, it retrieves a list of container images and executes a Trivy scan on each container image. Subsequently, it formats the output by adding “Trivy:
” at the start of each line. Finally, it cleans up the temporary output template file.
3. Add the executable permission for the owner and group to the /var/ossec/custom-script/trivy_scan.sh
file:
# chmod 750 /var/ossec/custom-script/trivy_scan.sh
4. Change the ownership of the /var/ossec/custom-script/trivy_scan.sh
file and the directory where it is located:
# chown root:wazuh /var/ossec/custom-script/ -R
5. Edit the Wazuh agent /var/ossec/etc/ossec.conf
file and add the following configuration within the <ossec_config>
block:
<!-- Trivy container vulnerability scanner script --> <wodle name="command"> <disabled>no</disabled> <command>/var/ossec/custom-script/trivy_scan.sh</command> <interval>3d</interval> <ignore_output>no</ignore_output> <run_on_start>yes</run_on_start> <timeout>0</timeout> </wodle>
Where:
disabled
specifies that the command is set to active.command
specifies the location of the trivy_scan.sh
script to be executed.interval
specifies the time interval for the execution of the configured script. In this blog post, the set value executes the trivy_scan.sh
every 3 days. Set this value to your preferred time interval.ignore_output
determines whether the output of the command execution should be ignored. Setting it to no
means that the output will be processed and logged by Wazuh.6. Restart the Wazuh agent to apply the above changes:
# systemctl restart wazuh-agent
Perform the steps below on the Wazuh server to create and configure custom decoders and rules for processing and monitoring logs generated from the Trivy scan.
Note: You need root user privileges to execute all the commands described below.
1. Create a file trivy_decoders.xml
in the /var/ossec/etc/decoders/
directory.
# touch /var/ossec/etc/decoders/trivy_decoders.xml
2. Add the following decoders to the /var/ossec/etc/decoders/trivy_decoders.xml
file to parse the Trivy logs received from the Wazuh agent:
<decoder name="trivy-decoder"> <prematch>^Trivy:</prematch> </decoder> <decoder name="trivy-decoder-fields"> <parent>trivy-decoder</parent> <regex offset="after_parent">"(\.+)","(\.+)","(\.+)","(\.+)","(\.+)","(\.+)"</regex> <order>image, package, version, vulnerability_id, severity, description</order> </decoder>
3. Create a file trivy_rules.xml
in the /var/ossec/etc/rules/
directory:
# touch /var/ossec/etc/rules/trivy_rules.xml
4. Add the following Wazuh rules to the /var/ossec/etc/rules/trivy_rules.xml
file to detect the Trivy scan results:
<group name="trivy,"> <!-- Parent Rule for Trivy alerts --> <rule id="100201" level="0"> <decoded_as>trivy-decoder</decoded_as> <description>Trivy alert detected.</description> </rule> <!-- This rule detects a critical severity vulnerability in a container image --> <rule id="100202" level="14"> <if_sid>100201</if_sid> <field name="severity">CRITICAL</field> <description>Trivy alert [CRITICAL]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a high severity vulnerability in a container image --> <rule id="100203" level="12"> <if_sid>100201</if_sid> <field name="severity">HIGH</field> <description>Trivy alert [HIGH]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a medium severity vulnerability in a container image --> <rule id="100204" level="7"> <if_sid>100201</if_sid> <field name="severity">MEDIUM</field> <description>Trivy alert [MEDIUM]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects a low severity vulnerability in a container image --> <rule id="100205" level="4"> <if_sid>100201</if_sid> <field name="severity">LOW</field> <description>Trivy alert [LOW]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> <!-- This rule detects an unknown severity vulnerability in a container image --> <rule id="100206" level="7"> <if_sid>100201</if_sid> <field name="severity">UNKNOWN</field> <description>Trivy alert [UNKNOWN]: Vulnerabilty '$(vulnerability_id)' detected in package '$(package)' version '$(version)' on container image '$(image)'.</description> </rule> </group>
Where:
100201
detects the output of the Trivy vulnerability scan. This rule will not generate alerts on the Wazuh dashboard, because, by default, alerts with levels below 3 do not appear on the Wazuh dashboard.100202
detects critical severity vulnerabilities from the Trivy scan.100203
detects high severity vulnerabilities from the Trivy scan.100204
detects medium severity vulnerabilities from the Trivy scan.100205
detects low severity vulnerabilities from the Trivy scan.100206
detects vulnerabilities with unknown severity ratings from the Trivy scan.5. Modify the ownership and permissions for the trivy_decoders.xml
and trivy_rules.xml
:
# chown wazuh:wazuh /var/ossec/etc/rules/trivy_rules.xml /var/ossec/etc/decoders/trivy_decoders.xml # chmod 660 /var/ossec/etc/rules/trivy_rules.xml /var/ossec/etc/decoders/trivy_decoders.xml
6. Restart the Wazuh manager to apply the above changes:
# systemctl restart wazuh-manager
We perform the following to visualize the Trivy vulnerability alerts on the Wazuh dashboard:
Perform the following steps to view the alerts and create Discover searches on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy
in the filter bar and hit the Enter button on your keyboard.
3. Under Available fields on the left pane, add the following fields as columns by hovering over each field and clicking the + icon beside it: agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
.
4. Click Save in the top right to save the query and enter “Trivy vulnerabilities” in the Title textbox.
Note: If you do not see the fields under Available fields, refresh the fields list from the Index Patterns page. To do this, navigate to Dashboard management > Dashboards Management > Index Patterns. Select wazuh-alerts-* from the list then click the refresh icon ⟳.
We filter further to identify and visualize alerts for each vulnerability severity.
Perform the following steps to view the critical severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy and rule.id:100202
in the filter bar and click Update.
3. Under Available fields on the left pane, add the following fields as columns by hovering over each field and clicking the + icon beside them: agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
.
4. Click Save in the top right to save the query and enter “Trivy [Critical vulnerabilities]” in the Title textbox.
Perform the following steps to view the high severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy
and rule.id:100203
in the filter bar and click Update.
3. Under Available fields on the left pane, add the following fields as columns by hovering over each field and clicking the + icon beside them: agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
.
4. Click Save in the top right to save the query and enter “Trivy [High vulnerabilities]” in the Title textbox.
Perform the following steps to view the medium severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy and rule.id:100204
in the filter bar and click Update.
3. Under Available fields on the left pane, add the following fields as columns by hovering over each field and clicking the + icon beside them: agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
.
4. Click Save in the top right to save the query and enter “Trivy [Medium vulnerabilities]” in the Title textbox.
Perform the following steps to view the low severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy and rule.id:100205
in the filter bar and click Update.
3. Under Available fields, add the following fields as columns by hovering on each field agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
and clicking the + icon beside it.
4. Click Save in the top right to save the query and enter “Trivy [Low vulnerabilities]” in the Title textbox.
Perform the following steps to view the unknown severity vulnerability alerts on the Wazuh dashboard.
1. Navigate to Explore > Discover.
2. Type rule.groups:trivy and rule.id:100206
in the filter bar and click Update.
3. Under Available fields on the left pane, add the following fields as columns by hovering over each field and clicking the + icon beside them: agent.name
, data.image
, data.vulnerability_id
, data.severity
, data.package
, data.version
, and data.description
.
4. Save the query as “Trivy [Unknown severity vulnerabilities]”.
Note: Sometimes Trivy generates vulnerabilities with “unknown” severity. This can arise from incomplete data, zero-day vulnerabilities, or differing vendor classifications and does not mean no risk exists. Investigate these findings using the provided details (ID, package, version) to assess potential impact.
Perform the following steps to create visualizations that will be used to create custom dashboards. We create a pie chart visualization and a vertical bar visualization.
1. Navigate to Explore > Visualize.
2. Click Create new visualization or Create visualization and select the Pie visualization format. Select Trivy vulnerabilities
.
3. Set the following value in the Data section, on the Slice size
, in Metrics:
Aggregation
= Count
4. Add a Split slices
in Bucket and set the following values:
Aggregation
= Terms
Field
= data.severity
Order by
= Metric: Count
Order
= Descending
Size
= 10
5. Customize the pie chart by toggling on show label
in the Options section.
6. Click the Update button.
7. Click save and save as “Trivy container vulnerabilities overview”.
1. Navigate to Explore > Visualize.
2. Click Create visualization and select the Vertical bar visualization format. Select Trivy vulnerabilities
.
2. Set the following value in the Data section, on the Y-axis
, in Metrics:
Aggregation
= Count
3. Add an X-axis
in Buckets and set the following values:
Aggregation
= Terms
Field
= data.image
Order by
= Metric: Count
Order
= Descending
Size
= 10
4. Customize the Vertical bar by toggling on the Show values on chart
in the Panel settings section.
5. Click the Update button.
6. Click Save and save as “Vulnerabilities by container image overview”.
Create a custom dashboard using the pie chart and vertical bar visualizations.
1. Navigate to Explore > Dashboards > Create New Dashboard.
2. Select Add an existing link and click the saved visualizations (Trivy container vulnerabilities overview and Vulnerabilities by container image overview). This will add the visualizations to the new dashboard.
3. Save the dashboard as “Trivy container image vulnerabilities dashboard”.
Next, we create another dashboard that contains the Discover searches we created previously.
1. Navigate to Explore > Dashboards > Create New Dashboard.
2. Select Add an existing link and click the saved visualizations (Trivy [Critical vulnerabilities], Trivy [High vulnerabilities], Trivy [Medium vulnerabilities], Trivy [Low vulnerabilities]). This will add the visualizations to the new dashboard. Follow this link to create the visualizations.
3. Save the dashboard as “Trivy container image vulnerabilities”.
Conclusion
By combining the vulnerability scanning capabilities of Trivy with the monitoring and alerting features of Wazuh, organizations can strengthen security in containerized environments. This integration not only helps identify and mitigate risks but also makes security an integral part of development and deployment. With automated scans and centralized visibility through the Wazuh dashboard, teams can proactively address threats and maintain a secure CI/CD pipeline.
Wazuh offers container security capabilities that when used with a container image scanning tool like Trivy, provide a comprehensive approach to securing containerized workloads. To learn more about Wazuh, explore our other blog posts and join the growing community.
References