Automated Linux Vulnerability Scanning: A Practical Guide to OpenVAS, Trivy, Vuls, and Nmap

Build a layered vulnerability scanning pipeline on Linux using OpenVAS/GVM, Trivy, Vuls, and Nmap. Covers setup, CI/CD integration, cron automation, and scanner supply chain security after the March 2026 Trivy compromise.

Why Automated Vulnerability Scanning Is Non-Negotiable in 2026

The numbers tell a pretty grim story: over 5,500 Linux kernel CVEs were reported in 2025, and 2026 is on pace to blow past that. January alone logged more than 2,800 new CVEs across all platforms. That works out to roughly 8–9 new kernel vulnerabilities every single day. Manual scanning isn't just impractical at this point — it's a liability.

And here's the part that really gets me: 79% of Linux attacks in 2025 used no malware at all. Attackers just exploited misconfigurations, unpatched services, and stolen credentials. If your vulnerability management strategy amounts to running a scan "every quarter" or "when we remember," you're almost certainly running production systems with known, exploitable flaws that automated scanners could've caught in minutes.

I've seen this firsthand — a team that hadn't scanned in six weeks got hit by a CVE that had a public exploit for over a month. Totally preventable.

So, let's dive in. This guide walks you through four powerful open-source vulnerability scanners — OpenVAS/GVM, Trivy, Vuls, and Nmap with Vulners — and shows you how to deploy them in a layered, automated scanning pipeline on Linux. Each tool covers a different slice of the attack surface: network services, installed packages, container images, and targeted CVE discovery.

Choosing the Right Scanner for Your Stack

No single scanner catches everything. Each tool excels in a specific domain, and combining them gives you comprehensive coverage with minimal blind spots.

ScannerPrimary UseScan TargetAgent RequiredBest For
OpenVAS/GVMNetwork vulnerability assessmentHosts, services, network devicesNo (network-based)Infrastructure-wide authenticated scanning
TrivyPackage and container scanningOS packages, container images, IaC, filesystemsNo (single binary)CI/CD pipelines, container security
VulsAgentless host scanningOS packages, libraries, middlewareNo (SSH-based)Multi-host fleet scanning without agents
Nmap + VulnersTargeted CVE discoveryOpen ports, service versionsNo (network-based)Quick reconnaissance and perimeter audits

The approach I'd recommend is layering these tools: use OpenVAS for deep authenticated network scans on a weekly schedule, Trivy in every CI/CD pipeline for container and dependency scanning, Vuls for daily agentless host fleet checks, and Nmap for on-demand perimeter audits. That way, you're not relying on any single tool to catch everything.

Setting Up OpenVAS/GVM with Docker

OpenVAS (now part of the Greenbone Vulnerability Manager framework) is the most comprehensive open-source network vulnerability scanner out there, with a database of over 185,000 CVEs across more than 950,000 vulnerability test plugins. The fastest way to get it running in 2026 is via Docker.

Prerequisites

OpenVAS/GVM is hungry for resources — you'll need at least 8 GB of RAM and roughly 21 GB of disk space for the full vulnerability feed. Make sure Docker and Docker Compose are installed:

sudo apt update && sudo apt install -y docker.io docker-compose
sudo systemctl enable --now docker
sudo usermod -aG docker $USER

Deploy the Greenbone Community Edition

# Download the official docker-compose file
curl -f -O https://greenbone.github.io/docs/latest/_static/docker-compose-22.4.yml

# Start the full GVM stack
sudo docker-compose -f docker-compose-22.4.yml -p greenbone-community-edition up -d

# Monitor the feed sync progress (this takes 30-60 minutes on first run)
sudo docker-compose -f docker-compose-22.4.yml -p greenbone-community-edition \
  logs -f gvmd

Once the feeds finish syncing, access the web interface at https://localhost:9392. The default credentials are admin/admin — change them immediately (seriously, don't skip this):

# Change the admin password via CLI
sudo docker-compose -f docker-compose-22.4.yml -p greenbone-community-edition \
  exec gvmd gvmd --user=admin --new-password='YourStr0ngP@ssword!'

Automate Daily Feed Updates

Vulnerability feeds get updated multiple times per week. Schedule a daily sync so you don't fall behind:

# /etc/cron.d/gvm-feed-sync
0 3 * * * root docker-compose -f /opt/gvm/docker-compose-22.4.yml \
  -p greenbone-community-edition exec -T gvmd greenbone-feed-sync \
  >> /var/log/gvm-feed-sync.log 2>&1

Running Authenticated Scans

Unauthenticated scans only see what's exposed on the network. Authenticated scans log into targets via SSH and inspect installed packages, which yields dramatically more accurate results. Honestly, the difference in detection quality is night and day.

In the Greenbone web UI, navigate to Configuration → Credentials and create an SSH credential with a dedicated scan account. Then create a target that uses those credentials:

# On each target host, create a restricted scan user
sudo useradd -m -s /bin/bash gvm-scan
sudo mkdir -p /home/gvm-scan/.ssh
# Copy the GVM public key
echo "ssh-ed25519 AAAA... gvm-scanner" | sudo tee /home/gvm-scan/.ssh/authorized_keys
sudo chmod 700 /home/gvm-scan/.ssh
sudo chmod 600 /home/gvm-scan/.ssh/authorized_keys
sudo chown -R gvm-scan:gvm-scan /home/gvm-scan/.ssh

For maximum detection without giving the scan account root access, grant it read access to the package manager database. On Debian/Ubuntu, the gvm-scan user can already run dpkg -l without privileges. On RHEL-based systems, rpm -qa also runs unprivileged. No sudo needed for basic package enumeration.

Scanning Linux Hosts and Containers with Trivy

Trivy is a fast, versatile scanner developed by Aqua Security that can scan container images, filesystem packages, IaC templates, and Git repositories. It runs as a single binary with zero dependencies — no database server, no middleware, nothing. Just download and go.

Critical Security Notice: March 2026 Supply Chain Attack

This one stung. On March 19, 2026, the official aquasecurity/trivy-action GitHub Action was compromised in a supply chain attack. The attacker force-pushed 75 out of 76 version tags, injecting a credential stealer that targeted CI/CD secrets across over 10,000 workflows globally. The compromised Docker Hub images (versions 0.69.4, 0.69.5, 0.69.6, and latest between March 19–23) attempted to dump process memory and exfiltrate SSH keys, cloud credentials, and Docker configurations.

Mitigation steps: Pin GitHub Actions to full commit SHA hashes — never mutable tags. The last known clean release is 0.69.3. If you pulled affected images during that window, rotate all credentials immediately. This incident is a stark reminder that even security tools themselves are supply chain targets. Always verify integrity.

Install Trivy

# Install via the official repository (Debian/Ubuntu)
sudo apt install -y wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
  gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | \
  sudo tee /etc/apt/sources.list.d/trivy.list
sudo apt update && sudo apt install -y trivy

# Verify the installed version
trivy version

Scan the Local Filesystem for OS Vulnerabilities

# Scan the running host for package vulnerabilities
trivy rootfs / --severity HIGH,CRITICAL --format table

# Scan and output machine-readable JSON for automation
trivy rootfs / --severity HIGH,CRITICAL --format json -o /var/log/trivy-host-scan.json

Scan Container Images Before Deployment

# Scan an image before pushing to production
trivy image nginx:1.27-bookworm --severity HIGH,CRITICAL

# Fail the build if critical vulnerabilities are found (CI/CD gate)
trivy image --exit-code 1 --severity CRITICAL myapp:latest

That --exit-code 1 flag is the magic here — it turns Trivy into a proper CI/CD gate that blocks deployments with critical vulns.

Scan Infrastructure as Code

# Scan Terraform, Kubernetes manifests, Dockerfiles for misconfigurations
trivy config ./infrastructure/ --severity HIGH,CRITICAL

Agentless Multi-Host Scanning with Vuls

Vuls is an open-source, agentless vulnerability scanner written in Go. It connects to remote hosts via SSH, checks installed packages against multiple vulnerability databases (NVD, OVAL, distribution advisories), and generates comprehensive reports — all without installing anything on the targets. If you manage a fleet of Linux servers, this one's a game-changer.

Install Vuls and Its Dependencies

# Install Go (required for Vuls)
sudo apt install -y golang-go git

# Set up the Vuls workspace
mkdir -p ~/vuls && cd ~/vuls

# Install vulnerability databases
go install github.com/vulsio/go-cve-dictionary/cmd/go-cve-dictionary@latest
go install github.com/vulsio/goval-dictionary/cmd/goval-dictionary@latest
go install github.com/vulsio/go-exploitdb/cmd/go-exploitdb@latest

# Install Vuls itself
go install github.com/future-architect/vuls/cmd/vuls@latest

# Fetch CVE data from NVD (this takes several minutes)
go-cve-dictionary fetch nvd --dbpath ~/vuls/cve.sqlite3

# Fetch OVAL data for your target distributions
goval-dictionary fetch ubuntu 22 24 --dbpath ~/vuls/oval.sqlite3
goval-dictionary fetch redhat 8 9 --dbpath ~/vuls/oval.sqlite3

Fair warning: the initial NVD fetch can take a while. Grab some coffee.

Configure Scan Targets

Create a config.toml file in your Vuls workspace:

# ~/vuls/config.toml
[servers]

[servers.web-prod-01]
host = "192.168.1.10"
port = "22"
user = "vuls-scan"
keyPath = "/home/admin/.ssh/vuls_ed25519"
scanMode = ["fast"]

[servers.db-prod-01]
host = "192.168.1.20"
port = "22"
user = "vuls-scan"
keyPath = "/home/admin/.ssh/vuls_ed25519"
scanMode = ["fast-root"]
[servers.db-prod-01.optional]
  sudo = true

The fast scan mode doesn't require root and works by checking package versions. The fast-root mode uses sudo for deeper inspection — use it on hosts where you need more thorough coverage (database servers, for instance).

Run a Scan and Generate Reports

# Validate the configuration
vuls configtest -config ~/vuls/config.toml

# Run the scan
vuls scan -config ~/vuls/config.toml

# Generate a terminal report
vuls report -config ~/vuls/config.toml -format-full-text

# Generate JSON for integration with other tools
vuls report -config ~/vuls/config.toml -format-json -to-localfile \
  -output-path ~/vuls/results/

Automate Daily Scans with Cron

# /etc/cron.d/vuls-daily-scan
PATH=/usr/local/go/bin:/usr/local/bin:/usr/bin:/bin
GOPATH=/home/admin/go

# Update vulnerability databases at 1 AM
0 1 * * * admin go-cve-dictionary fetch nvd --dbpath /home/admin/vuls/cve.sqlite3 > /var/log/vuls-cve-update.log 2>&1

# Run scan at 2 AM and send report to Slack
0 2 * * * admin /home/admin/go/bin/vuls scan -config /home/admin/vuls/config.toml && \
  /home/admin/go/bin/vuls report -config /home/admin/vuls/config.toml \
  -to-slack -cvss-over=7.0 > /var/log/vuls-scan.log 2>&1

Targeted CVE Discovery with Nmap and Vulners

Nmap combined with the Vulners NSE script gives you a lightweight way to discover known CVEs in exposed network services. Unlike the comprehensive scanners above, Nmap is perfect for quick perimeter audits and on-demand reconnaissance of specific targets. Think of it as the "quick check" in your toolkit.

Install and Run a Vulners Scan

# Install Nmap (comes with the vulners script included)
sudo apt install -y nmap

# Scan a single host — service version detection is required (-sV)
sudo nmap -sV --script vulners -oA /tmp/scan-webserver 192.168.1.10

# Filter for high-severity CVEs only (CVSS >= 7.0)
sudo nmap -sV --script vulners --script-args mincvss=7.0 192.168.1.10

# Scan an entire subnet for critical vulnerabilities
sudo nmap -sV --script vulners --script-args mincvss=9.0 \
  -oX /var/log/nmap-subnet-scan.xml 192.168.1.0/24

Offline Scanning with Vulscan

The vulners script queries an external API, which isn't ideal for air-gapped environments. The vulscan NSE script provides an offline alternative that uses locally downloaded vulnerability databases:

# Install vulscan
cd /usr/share/nmap/scripts/
sudo git clone https://github.com/scipag/vulscan.git
sudo nmap --script-updatedb

# Run an offline vulnerability scan
sudo nmap -sV --script vulscan/vulscan.nse -oA /tmp/offline-scan 192.168.1.10

Automate Weekly Perimeter Audits

# /etc/cron.d/nmap-weekly-audit
0 4 * * 1 root nmap -sV --script vulners --script-args mincvss=7.0 \
  -oX /var/log/nmap/perimeter-$(date +\%F).xml \
  -iL /etc/nmap/perimeter-targets.txt >> /var/log/nmap/scan.log 2>&1

Integrating Vulnerability Scanning into CI/CD Pipelines

Shifting vulnerability scanning left into the build pipeline catches issues before they ever reach production. The key principle is simple: fail the build on critical vulnerabilities, warn on high-severity ones, and report everything to a centralized dashboard.

Getting this right saves you from so many 2 AM incidents. Trust me on that one.

GitHub Actions Example with Trivy

After the March 2026 supply chain attack on the official Trivy action, you'll want to either pin to a verified commit SHA or (my preference) just install Trivy directly:

# .github/workflows/security-scan.yml
name: Security Scan
on:
  push:
    branches: [main]
  pull_request:
  schedule:
    - cron: "0 6 * * 1"  # Weekly Monday 6 AM rescan

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Trivy (direct binary — no third-party action)
        run: |
          sudo apt-get install -y wget
          wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
            gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
          echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] \
            https://aquasecurity.github.io/trivy-repo/deb generic main" | \
            sudo tee /etc/apt/sources.list.d/trivy.list
          sudo apt-get update && sudo apt-get install -y trivy

      - name: Scan container image
        run: |
          docker build -t myapp:${{ github.sha }} .
          trivy image --exit-code 1 --severity CRITICAL \
            --format sarif -o trivy-results.sarif \
            myapp:${{ github.sha }}

      - name: Upload SARIF to GitHub Security
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: trivy-results.sarif

GitLab CI Example

# .gitlab-ci.yml
stages:
  - build
  - scan

vulnerability-scan:
  stage: scan
  image: aquasec/trivy:0.69.3  # Pinned to last known clean version
  script:
    - trivy image --exit-code 0 --severity HIGH --format json -o gl-container-scanning-report.json $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  artifacts:
    reports:
      container_scanning: gl-container-scanning-report.json
  allow_failure: false

Building a Unified Scanning Pipeline

The real power comes from combining all four tools into a coordinated workflow. Here's a practical architecture that maximizes coverage while keeping operational overhead manageable:

Layered Scanning Schedule

LayerToolFrequencyTriggerScope
Build-timeTrivyEvery commitCI/CD pipelineContainer images, dependencies, IaC
Daily host scanVulsDaily at 2 AMCronAll Linux servers via SSH
Weekly deep scanOpenVAS/GVMWeeklyGVM schedulerFull authenticated network scan
Weekly perimeterNmap + VulnersWeeklyCronInternet-facing services

Centralized Reporting with a Webhook Aggregator

Feed scan results from all four tools into a central location. Here's a straightforward approach using a shared directory and a script that consolidates findings:

#!/bin/bash
# /opt/vuln-reports/aggregate.sh
# Consolidate scan results and send a daily digest

REPORT_DIR="/var/log/vuln-scans"
TIMESTAMP=$(date +%F)
DIGEST="${REPORT_DIR}/digest-${TIMESTAMP}.txt"

echo "=== Vulnerability Scan Digest: ${TIMESTAMP} ===" > "$DIGEST"

# Vuls summary
echo -e "\n--- Vuls (Host Packages) ---" >> "$DIGEST"
vuls report -config /home/admin/vuls/config.toml -format-short-text 2>/dev/null >> "$DIGEST"

# Trivy host scan
echo -e "\n--- Trivy (Local Filesystem) ---" >> "$DIGEST"
trivy rootfs / --severity HIGH,CRITICAL --format table 2>/dev/null >> "$DIGEST"

# Nmap perimeter findings
echo -e "\n--- Nmap (Perimeter) ---" >> "$DIGEST"
if [ -f "${REPORT_DIR}/nmap/perimeter-${TIMESTAMP}.xml" ]; then
  nmap -oG - "${REPORT_DIR}/nmap/perimeter-${TIMESTAMP}.xml" 2>/dev/null >> "$DIGEST"
fi

# Send via webhook (Slack, Teams, or email)
curl -X POST -H "Content-type: application/json" \
  -d "{\"text\": \"Daily vulnerability digest generated. $(grep -c CVE "$DIGEST") CVEs found.\"}" \
  "${SLACK_WEBHOOK_URL}"

It's not fancy, but it works. You can always swap in something more sophisticated (like DefectDojo or Faraday) down the road once your process matures.

Hardening Your Scanners Themselves

The March 2026 Trivy supply chain compromise proved something uncomfortable: vulnerability scanners are high-value targets. Think about it — a compromised scanner runs with privileged access across your entire infrastructure. That's basically the keys to the kingdom.

Here's what you should do to protect them:

  • Isolate the scanning infrastructure. Run OpenVAS and Vuls on a dedicated management VLAN with strict firewall rules. The scanner should be able to reach targets, but targets shouldn't be able to reach back into the scanner.
  • Pin versions and verify checksums. Never use latest tags for scanner images. Pin to specific versions and verify SHA256 checksums against official release pages. Yes, it's tedious. Do it anyway.
  • Use dedicated scan credentials. Create purpose-built accounts with minimal privileges for each scanner. Never reuse admin or service account credentials.
  • Monitor the scanners. Watch for unexpected outbound connections, elevated CPU usage, or changes to scanner binaries. Treat scanner hosts with the same rigor as production systems.
  • Keep scanners updated. Scanners themselves have vulnerabilities. Subscribe to security advisories for OpenVAS, Trivy, Vuls, and Nmap, and patch promptly.

Frequently Asked Questions

What is the best open-source vulnerability scanner for Linux servers?

There isn't a single "best" scanner — the most effective approach combines multiple tools. OpenVAS/GVM is the most comprehensive for network vulnerability assessment with over 185,000 CVE checks. Trivy excels at container and dependency scanning in CI/CD pipelines. Vuls provides efficient agentless scanning across large server fleets via SSH. For quick perimeter checks, Nmap with the Vulners script offers fast, targeted CVE discovery. Layer all four for maximum coverage.

How often should I run vulnerability scans on Linux production servers?

At minimum: continuous scanning in CI/CD pipelines (every commit), daily lightweight host scans with Vuls or Trivy, weekly deep authenticated scans with OpenVAS, and weekly perimeter audits with Nmap. Critical infrastructure may warrant even more frequent scanning. The key is that scanning should be automated — if it depends on someone remembering to run it, it won't happen consistently.

What is the difference between vulnerability scanning and compliance scanning?

Vulnerability scanning identifies known CVEs in installed software, open services, and dependencies — it answers "what can an attacker exploit?" Compliance scanning (using tools like OpenSCAP against CIS Benchmarks) checks whether system configurations meet a predefined security standard — it answers "does this system meet policy?" Both are essential but address different risks. A system can pass every CIS benchmark check while still running an unpatched version of OpenSSH with a critical CVE.

Is Trivy safe to use after the March 2026 supply chain attack?

Yes, absolutely. The attack targeted the GitHub Action wrapper (aquasecurity/trivy-action) and specific Docker Hub image tags, not the core Trivy binary. To use Trivy safely: install it directly from the official APT/YUM repository or download the binary and verify its checksum, pin to version 0.69.3 or a confirmed clean later release, never use mutable Docker tags like latest, and pin any GitHub Actions to full commit SHA hashes instead of version tags.

Can I run OpenVAS vulnerability scans without root access on target hosts?

Yes. OpenVAS performs network-based scanning from its own host, so it doesn't need root on targets for unauthenticated scans. For authenticated scans (which detect significantly more vulnerabilities), you need an SSH user on the target — but this user doesn't require root either. Package listing commands like dpkg -l (Debian/Ubuntu) and rpm -qa (RHEL/CentOS) run without elevated privileges. Only grant sudo if you need deep scan features like checking running process versions or reading protected configuration files.

About the Author Editorial Team

Our team of expert writers and editors.