How to Build a Mock Trivy Image Scan Gate in Python

Simulate a Trivy image scan and enforce a security gate that fails the pipeline when vulnerabilities meet or exceed a severity threshold.

Easy Python 3.9+ Aug 9, 2026 Production deployment patterns 13 views 0 copies

Python code

46 lines
Python 3.9+
import json
import sys


def mock_trivy_scan(image_name, severity_threshold="HIGH"):
    """Simulate a Trivy image scan result."""
    mock_vulnerabilities = [
        {"ID": "CVE-2023-1234", "Severity": "HIGH", "Package": "openssl", "FixedVersion": "3.0.9"},
        {"ID": "CVE-2024-5678", "Severity": "CRITICAL", "Package": "libcurl", "FixedVersion": "7.88.1"},
        {"ID": "CVE-2022-9999", "Severity": "MEDIUM", "Package": "zlib", "FixedVersion": "1.2.13"},
    ]
    severity_rank = {"LOW": 0, "MEDIUM": 1, "HIGH": 2, "CRITICAL": 3}
    threshold_rank = severity_rank[severity_threshold.upper()]

    failures = [
        v
        for v in mock_vulnerabilities
        if severity_rank[v["Severity"]] >= threshold_rank
    ]

    result = {
        "image": image_name,
        "threshold": severity_threshold.upper(),
        "passed": len(failures) == 0,
        "vulnerabilities": mock_vulnerabilities,
        "blocking_findings": failures,
    }
    return result


def gate(scan_result):
    """Enforce the gate: exit non-zero if scan fails."""
    if scan_result["passed"]:
        print(f"GATE PASSED: {scan_result['image']} meets {scan_result['threshold']} threshold.")
        return 0
    print(f"GATE FAILED: {scan_result['image']} has blocking vulnerabilities:")
    for vuln in scan_result["blocking_findings"]:
        print(f"  - {vuln['ID']} ({vuln['Severity']}) {vuln['Package']} -> fix in {vuln['FixedVersion']}")
    return 1


if __name__ == "__main__":
    image = "myapp:latest"
    scan = mock_trivy_scan(image, severity_threshold="HIGH")
    print(json.dumps(scan, indent=2))
    sys.exit(gate(scan))

Output

stdout
{
  "image": "myapp:latest",
  "threshold": "HIGH",
  "passed": false,
  "vulnerabilities": [
    {
      "ID": "CVE-2023-1234",
      "Severity": "HIGH",
      "Package": "openssl",
      "FixedVersion": "3.0.9"
    },
    {
      "ID": "CVE-2024-5678",
      "Severity": "CRITICAL",
      "Package": "libcurl",
      "FixedVersion": "7.88.1"
    },
    {
      "ID": "CVE-2022-9999",
      "Severity": "MEDIUM",
      "Package": "zlib",
      "FixedVersion": "1.2.13"
    }
  ],
  "blocking_findings": [
    {
      "ID": "CVE-2023-1234",
      "Severity": "HIGH",
      "Package": "openssl",
      "FixedVersion": "3.0.9"
    },
    {
      "ID": "CVE-2024-5678",
      "Severity": "CRITICAL",
      "Package": "libcurl",
      "FixedVersion": "7.88.1"
    }
  ]
}
GATE FAILED: myapp:latest has blocking vulnerabilities:
  - CVE-2023-1234 (HIGH) openssl -> fix in 3.0.9
  - CVE-2024-5678 (CRITICAL) libcurl -> fix in 7.88.1

How it works

The mock_trivy_scan function builds a dictionary with a numeric severity rank for each vulnerability, then compares that rank against the configured threshold to determine which findings are blocking. A rank mapping keeps the comparison simple and avoids repeated if/elif chains. The gate function checks the passed flag and either prints a success or lists each blocking vulnerability with its fix version, then returns the appropriate exit code. Returning a nonzero code from sys.exit is the standard way to make a CI/CD pipeline step fail. This pattern mirrors how real Trivy scanning is often integrated into container build pipelines.

Common mistakes

  • Forgetting to call `sys.exit(gate(scan))` and letting the script quietly exit 0 even when blocked.
  • Using a string comparison for severity instead of a numeric rank, so 'HIGH' < 'CRITICAL' the wrong way.
  • Hard-coding the threshold inside the scan function instead of passing it as a parameter, making it hard to reuse.

Variations

  1. Use `argparse` to let CI operators set the image and threshold from the command line.
  2. Instead of printing JSON, write the raw scan result to a file for later parsing by a dashboard or audit tool.

Real-world use cases

  • Blocking a container image push in a CI/CD pipeline when known critical or high-severity vulnerabilities exist.
  • Running a mock scan in a local development environment to test gate logic without invoking real Trivy.
  • Integrating with a container registry webhook to automatically reject images that fail a security policy.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Production deployment patterns

Related tutorials and quizzes for this topic.