This is unreleased documentation for SBOM Scanner 0.13-dev.

Scanning Registries

This guide explains how to configure and run scans on container registries using SBOM Scanner.

It covers:

  • Defining a Registry custom resource

  • Running on-demand scans with a ScanJob

  • Targeting a subset of a Registry from a ScanJob

  • Configuring scheduled scans

  • Configuring registry without catalog

  • Filtering by tags

  • Filtering by platforms

  • Monitoring scan progress and results

  • Stopping scans and cleaning up resources

  • Remove a Registry

1. Define a Registry

Before scanning a registry, create a Registry custom resource that specifies the registry endpoint and repositories to scan.

Example manifest:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-registry
  namespace: default
spec:
  uri: ghcr.io
  scanInterval: 1h
  repositories:
    - name: kubewarden/sbomscanner/test-assets/golang

This configuration:

  • Targets the ghcr.io registry

  • Scans the kubewarden/sbomscanner/test-assets/golang repository

  • Runs a new scan every hour

Apply the resource:

kubectl apply -f registry.yaml

For private registries, see the Private Registries guide.

2. Run a Scan on Demand

To run a one-time scan, omit the scanInterval in the Registry resource and create a ScanJob that references it.

Example Registry without scheduling:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-registry
  namespace: default
spec:
  uri: ghcr.io
  repositories:
    - name: kubewarden/sbomscanner/test-assets/golang

Example ScanJob manifest:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: ScanJob
metadata:
  name: my-scanjob
  namespace: default
spec:
  registry: my-registry

Apply the job:

kubectl apply -f scanjob.yaml

The ScanJob must be created in the same namespace as its referenced Registry.

3. Target a Subset of a Registry

By default a ScanJob scans every repository (and every matchCondition) declared on the referenced Registry. You can narrow the scan to a subset by setting spec.repositories on the ScanJob.

Each entry references a repository by name. It can restrict the scan to a subset of the repository matchConditions.

Example: scan only one repository, all of its matchConditions:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: ScanJob
metadata:
  name: my-scanjob
  namespace: default
spec:
  registry: my-registry
  repositories:
    - name: kubewarden/sbomscanner/test-assets/golang

Example: scan a single repository, restricted to two of its matchConditions:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: ScanJob
metadata:
  name: my-scanjob
  namespace: default
spec:
  registry: my-registry
  repositories:
    - name: kubewarden/sbomscanner/test-assets/golang
      matchConditions:
        - production tags
        - latest tag

Each spec.repositories entry must reference a repository on the Registry. Each matchConditions name must reference a condition on that repository. The ScanJob controller validates these references. It marks the job as failed if a reference does not exist.

When spec.repositories is set, obsolete-image cleanup is skipped for the entire ScanJob. Images absent from the registry remain in the cluster during a targeted scan. A later non-targeted ScanJob reconciles them.

4. Configuring registry without catalog

Some registries do not implement or expose the _catalog endpoint. Examples include Docker Hub, Amazon ECR, and ghcr.io.

To scan these registries, specify the repositories instead of pulling the catalog.

When using catalogType as NoCatalog, you must explicitly provide the list of repositories to scan.

Example Registry without catalog:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-registry
  namespace: default
spec:
  uri: ghcr.io
  catalogType: NoCatalog
  repositories:
    - name: kubewarden/sbomscanner/test-assets/golang

These registries do not support _catalog:

  • Amazon ECR

  • Google Container Registry (GCR)

  • GitHub Container Registry (GHCR)

5. Filtering By Platforms

Usually, you do not need to scan all platforms for an image version. The platform filter prevents unnecessary scans.

To reduce the SBOM Scanner workload, specify the platforms to scan.

This example configures the registry for the linux/amd64 platform only.

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-first-registry
  namespace: default
spec:
  uri: dev-registry.default.svc.cluster.local:5000
  platforms:
    - arch: "amd64"
      os: "linux"

To configure multiple platforms, list them as follows:

...
spec:
  uri: dev-registry.default.svc.cluster.local:5000
  platforms:
    - arch: "amd64"
      os: "linux"
    - arch: "386"
      os: "linux"
    - arch: "arm64"
      os: "linux"
      variant: "v7"

6. Filtering By Tags

Use CEL expressions in repositories.matchConditions to filter image tags. Expressions can use regular expressions, version comparisons, and string operations. This reduces the number of scanned images and system load.

This is an example:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-first-registry
  namespace: default
spec:
  uri: dev-registry.default.svc.cluster.local:5000
  repositories:
    - name: kubewarden/sbomscanner/test-assets/test-image
      matchConditions:
        - name: "production tags"
          expression: "tag.endsWith('-prod')"

This example filters images with tags that end in -prod. Use this filter for images deployed in a production environment.

Use !tag.matches('-rc*') to prevent scans of release-candidate images. These images usually have the tag <version>-rc<rc_version_number>.

You can define multiple expressions in matchConditions. Use multiple expressions to split complex filters:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-first-registry
  namespace: default
spec:
  uri: dev-registry.default.svc.cluster.local:5000
  repositories:
    - name: kubewarden/sbomscanner/test-assets/test-image
      matchConditions:
        - name: "semver is less than v1.0.0"
          expression: "semver(tag, true).isLessThan(semver('v1.0.0', true))"
        - name: "semver is greater than v1.1.0"
          expression: "semver(tag, true).isGreaterThan(semver('v1.1.0', true))"

These expressions scan a range of image versions from v1.0.0 to v1.1.0.

By default, all conditions must pass for a tag to be included (AND logic).

Using OR Logic

If you want a tag to match when at least one condition passes, set the matchOperator field to Or:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: Registry
metadata:
  name: my-first-registry
  namespace: default
spec:
  uri: dev-registry.default.svc.cluster.local:5000
  repositories:
    - name: kubewarden/sbomscanner/test-assets/test-image
      matchOperator: Or
      matchConditions:
        - name: "latest tag"
          expression: "tag == 'latest'"
        - name: "production tags"
          expression: "tag.endsWith('-prod')"
        - name: "stable tags"
          expression: "tag.endsWith('-stable')"

This configuration scans tags that are either latest, end with -prod, or end with -stable.

Common Expression Language

The Common Expression Language (CEL) is used in the Kubernetes API to declare validation rules, policy rules, and other constraints or conditions.

Kubernetes uses CEL widely. CEL is an alternative to out-of-process mechanisms, such as webhooks.

For CEL details, see https://github.com/google/cel-spec.

These CEL expressions are common for tag filtering:

String and Regex

function example description

startsWith

tag.startsWith('v1')

Tags that starts with v1 prefix.

endsWith

tag.endsWith('-prod')

Tags that ends with -prod suffix.

matches

tag.matches('^v[01]\.*')

Tags that matches the regex ^v[01]\.*.

Semver

function example description

isGreaterThan

semver(tag, true).isGreaterThan(semver('v1.1.0', true))

Tags that are greater than a given version.

isLessThan

semver(tag, true).isLessThan(semver('v1.1.0', true))

Tags that are less than a given version.

7. Monitor Scan Progress

Check the status of a scan:

kubectl get scanjob my-scanjob -n default -o yaml

Example status:

status:
  imagesCount: 10
  conditions:
    - type: Complete
      status: "True"
      reason: "AllImagesScanned"
      message: "Scan completed successfully"

8. View Results

Reports generated by scans include images, SBOMs, and vulnerability findings. See the Querying Reports guide for details.

9. Stop an Ongoing Scan

To cancel a running scan, delete its ScanJob:

kubectl delete scanjob my-scanjob -n default

10. Remove a Registry

To delete a registry and its associated data:

kubectl delete registry my-registry -n default

This action removes:

  • The registry definition

  • All related images, SBOMs, and vulnerability reports

  • Any ScanJob resources referencing the registry

If a scan is in progress, it will be terminated.