Scanner Plugins
Motivation
By default, copa uses Trivy to scan container images for vulnerabilities. However, we understand that different organizations have different requirements and may want to use different vulnerability scanners.
Starting with v0.5.0 and later, copa offers extensibility to support different vulnerability scanners. Plugin architecture allows users to use the vulnerability scanner of their choice to patch container images without having to modify copa's core codebase.
Usage
Scanner plugin binaries must be in $PATH, and should be prefixed with copa- and have executable permissions. Copa will automatically detect and use the scanner plugin if it is in $PATH.
For example, if you have a scanner plugin binary called copa-foo in $PATH, you can run copa with the following command:
copa patch --scanner foo --image $IMAGE ...
You can also a submit scan report in native v1alpha1 format (interface mentioned below) by using --scanner native flag along with -r <report> flag.
Scanner Plugins from the Community
If you have built a scanner plugin and would like to add it to this list, please submit a PR to update this section with your plugin.
If you have any issues with a specific plugin, please open an issue in the applicable plugin's repository.
Writing a Scanner Plugin
Please see instructions at Scanner Plugin Template for a template to get started with writing a scanner plugin.
Scanner Plugin Interface
alpha versions of the API are not guarenteed to be backwards compatible. Once the API graduates to beta and stable, it will be backwards compatible.
API Versions:
- v1alpha1: Original format with single 
updatesfield - existing plugins continue to work - v1alpha2: New format with separate 
osupdatesandlangupdatesfields that supports app-level patching 
Scanner plugins support two API versions for backwards compatibility:
v1alpha1
type UpdateManifest struct {
    // API version (v1alpha1)
    APIVersion string         `json:"apiVersion"`
    // Metadata contains information about the OS and config
    Metadata   Metadata       `json:"metadata"`
    // Updates contains all package updates (OS packages only)
    Updates    UpdatePackages `json:"updates"`
}
type UpdatePackage struct {
    // Package name
    Name             string `json:"name"`
    // Installed version
    InstalledVersion string `json:"installedVersion"`
    // Fixed version
    FixedVersion     string `json:"fixedVersion"`
    // Vulnerability ID
    VulnerabilityID  string `json:"vulnerabilityID"`
}
type Metadata struct {
    OS     OS     `json:"os"`
    Config Config `json:"config"`
}
type Config struct {
    // OS Architecture (e.g. amd64, arm64)
    Arch string `json:"arch"`
}
v1alpha2
type UpdateManifest struct {
    // API version (v1alpha2)
    APIVersion  string             `json:"apiVersion"`
    // Metadata contains information about the OS and config
    Metadata    Metadata           `json:"metadata"`
    // OSUpdates is a list of OS package updates
    OSUpdates   UpdatePackages     `json:"osupdates"`
    // LangUpdates is a list of language/library package updates
    LangUpdates LangUpdatePackages `json:"langupdates"`
}
type UpdatePackage struct {
    // Package name
    Name             string `json:"name"`
    // Installed version
    InstalledVersion string `json:"installedVersion"`
    // Fixed version
    FixedVersion     string `json:"fixedVersion"`
    // Vulnerability ID
    VulnerabilityID  string `json:"vulnerabilityID"`
    // Package type (python-pkg)
    Type             string `json:"type"`
    // Package class (os-pkgs, lang-pkgs)
    Class            string `json:"class"`
}
type Config struct {
    // OS Architecture (e.g. amd64, arm64)
    Arch    string `json:"arch"`
    // Architecture variant (e.g. v8)
    Variant string `json:"variant,omitempty"`
}
Format Examples
From the above, we can see that the plugin must return a JSON object via standard out with the following fields.
v1alpha1
{
  "apiVersion": "v1alpha1",
  "metadata": {
    "os": {
        "type": "debian",
        "version": "11.3"
    },
    "config": {
      "arch": "amd64"
    }
  },
  "updates": [
      {
          "name": "libcurl4",
          "installedVersion": "7.74.0-1.3+deb11u1",
          "fixedVersion": "7.74.0-1.3+deb11u2",
          "vulnerabilityID": "CVE-2021-22945"
      }
  ]
}
v1alpha2
{
  "apiVersion": "v1alpha2",
  "metadata": {
    "os": {
        "type": "debian",
        "version": "11.3"
    },
    "config": {
      "arch": "amd64",
      "variant": "v8"
    }
  },
  "osupdates": [
      {
          "name": "libcurl4",
          "installedVersion": "7.74.0-1.3+deb11u1",
          "fixedVersion": "7.74.0-1.3+deb11u2",
          "vulnerabilityID": "CVE-2021-22945",
          "type": "debian",
          "class": "os-pkgs"
      }
  ],
  "langupdates": [
      {
          "name": "requests",
          "installedVersion": "2.25.1",
          "fixedVersion": "2.31.0",
          "vulnerabilityID": "CVE-2023-32681",
          "type": "python-pkg",
          "class": "lang-pkgs"
      }
  ]
}