This is unreleased documentation for SBOM Scanner 0.13-dev.

Scanning Nodes

Overview

SBOM Scanner can scan container images through Registry configurations and workload scanning, but the security posture of a cluster also depends on the nodes themselves. Nodes run the operating system, the container runtime, the kubelet, and other system-level packages that are invisible to image-based scanners.

The Node Scan feature deploys a worker on each eligible node as a DaemonSet. The worker scans the host filesystem. It produces a NodeSBOM and a NodeVulnerabilityReport for each node. These resources show node vulnerabilities.

Under the hood, SBOM Scanner creates a NodeScanJob resource for each matching node, on the configured schedule or on demand. The worker pod on the node scans the host filesystem and produces a NodeSBOM (in SPDX format) and a NodeVulnerabilityReport for that node.

Enabling Node Scan

Node scanning is inactive until you create a NodeScanConfiguration resource. Without it, no scans run and manually created NodeScanJob resources fail with the reason NodeScanConfigurationMissing.

To enable node scanning, apply the sample configuration from the examples folder:

kubectl apply -f https://raw.githubusercontent.com/kubewarden/sbomscanner/main/examples/nodescanconfiguration.yaml

Configuration

NodeScanConfiguration is a cluster-scoped singleton resource named default. It controls node scanning. Without this resource, no node is scanned. The cluster can contain only one instance.

Example configuration:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: NodeScanConfiguration
metadata:
  name: default
spec:
  scanInterval: 24h
  nodeSelector:
    matchExpressions:
      - key: kubernetes.io/hostname
        operator: In
        values:
          - "node1"
          - "node2"
  skipPatterns:
    - "/run/k3s/containerd/"
  platforms:
    - arch: "amd64"
      os: "linux"

Fields

Field Description Default

enabled

Enable or disable node scanning. See Disabling node scanning for details.

true

scanInterval

How often nodes are scanned. If not specified, automatic scanning is disabled and you must create NodeScanJob resources manually.

-

nodeSelector

A standard Kubernetes label selector. Only nodes matching the selector are scanned.

All nodes

skipPatterns

Gitignore-style patterns for files and directories to exclude from the scan. Patterns ending with / are treated as directories, all others as files. Glob patterns like **/vendor/ or *.min.js are supported.

Container runtime directories

platforms

Which OS/architecture combinations to scan. Each entry specifies an arch and os field.

All platforms

Selecting which nodes to scan

Use the nodeSelector field to restrict scanning to a subset of nodes. Use this field when some nodes lack scan resources. You can also use it to target node pools.

Scan only nodes with a specific label:

spec:
  nodeSelector:
    matchLabels:
      node-role.kubernetes.io/worker: ""

Scan specific nodes by hostname:

spec:
  nodeSelector:
    matchExpressions:
      - key: kubernetes.io/hostname
        operator: In
        values:
          - "worker-1"
          - "worker-2"

If nodeSelector is omitted, all nodes in the cluster are scanned.

Excluding files and directories

The skipPatterns field accepts gitignore-style patterns to exclude paths from the filesystem scan. This is useful to reduce noise or avoid scanning sensitive or irrelevant paths. If unset, a default list of patterns is applied that excludes container runtime directories. See the CRD reference for the default list. Set skipPatterns to an empty list to scan everything, including those directories.

spec:
  skipPatterns:
    - "/run/k3s/containerd/"
    - "/tmp/"
    - ".git/"
    - "node_modules/"
    - "*.min.js"
    - "package-lock.json"

Patterns ending with / match directories. All other patterns match files. Glob patterns such as **/vendor/ are supported.

When you set skipPatterns without all default patterns, SBOM Scanner emits an admission warning. The defaults exclude container-runtime state directories. Scanning these paths can cause the node scan to fail. Include the default patterns in your list. See the CRD reference for the default list.

Scanning specific platforms

By default, SBOM Scanner scans all nodes regardless of their platform. In clusters with mixed architectures, you can restrict scanning to specific OS/architecture combinations:

spec:
  platforms:
    - arch: "amd64"
      os: "linux"
    - arch: "arm64"
      os: "linux"

Running a scan on demand

To trigger a one-time scan, create a NodeScanJob resource. A NodeScanConfiguration must exist in the cluster. The job uses its settings.

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: NodeScanJob
metadata:
  name: scan-worker-1
spec:
  nodeName: worker-1

Apply the job:

kubectl apply -f nodescanjob.yaml

If another NodeScanJob is already in progress for the same node, the new job is marked as Failed with the reason ScanAlreadyInProgress.

Triggering an immediate rescan

To bypass the scan interval timer and trigger an immediate rescan of all matching nodes, annotate the NodeScanConfiguration:

kubectl annotate nodescanconfiguration default \
  sbomscanner.kubewarden.io/node-rescan-requested=true

The annotation is removed automatically after the scan jobs are created.

Monitoring scan progress

Check the status of node scan jobs:

kubectl get nodescanjobs

Example output:

NAME              STATUS       REASON       AGE
scan-worker-1     Complete     Complete     5m
scan-worker-2     InProgress   InProgress   1m

Get detailed status of a specific job:

kubectl get nodescanjob scan-worker-1 -o yaml

Example status:

status:
  startTime: "2026-06-01T10:00:00Z"
  completionTime: "2026-06-01T10:02:30Z"
  conditions:
    - type: Complete
      status: "True"
      reason: Complete
      message: "NodeScanJob completed successfully"
    - type: Failed
      status: "False"
      reason: Complete
    - type: InProgress
      status: "False"
      reason: Complete
    - type: Scheduled
      status: "False"
      reason: Complete

Status conditions

Each NodeScanJob has status conditions that track the scan lifecycle:

Status Meaning

Scheduled

The system has accepted the request and scheduled the scan.

InProgress

The scan is actively running on the node.

Complete

The scan finished successfully. The NodeSBOM and NodeVulnerabilityReport are available.

Failed

The scan encountered a terminal error. Check the condition’s reason and message for details.

Common failure reasons:

Reason Description

ScanAlreadyInProgress

Another scan job is already running for the same node.

NodeScanConfigurationMissing

No NodeScanConfiguration resource exists in the cluster.

NodeNotMatching

The target node does not match the nodeSelector defined in the configuration.

InternalError

An unexpected error occurred during the scan.

Viewing results

NodeSBOM

Once a scan completes, a NodeSBOM resource is created containing the Software Bill of Materials in SPDX format.

List node SBOMs:

kubectl get nodesboms

Query by node name:

kubectl get nodesboms --field-selector='nodeMetadata.name=worker-1'

Query by platform:

kubectl get nodesboms --field-selector='nodeMetadata.platform=linux/amd64'

View the full SBOM:

kubectl get nodesbom worker-node-1 -o yaml

Example output (truncated):

apiVersion: storage.sbomscanner.kubewarden.io/v1alpha1
kind: NodeSBOM
metadata:
  name: worker-node-1
nodeMetadata:
  name: worker-node-1
  platform: linux/amd64
spdx:
  spdxVersion: SPDX-2.3
  dataLicense: CC0-1.0
  name: worker-node-1
  packages:
    - name: libc6
      versionInfo: 2.39-0ubuntu8.3
      primaryPackagePurpose: LIBRARY
    - name: containerd
      versionInfo: 1.7.24-0ubuntu1~24.04.1
      primaryPackagePurpose: APPLICATION
    - name: kubelet
      versionInfo: 1.31.2-1.1
      primaryPackagePurpose: APPLICATION

NodeVulnerabilityReport

The vulnerability analysis results are stored in NodeVulnerabilityReport resources.

List node vulnerability reports:

kubectl get nodevulnerabilityreports

Query by node name:

kubectl get nodevulnerabilityreports --field-selector='nodeMetadata.name=worker-1'

View the full report:

kubectl get nodevulnerabilityreport worker-node-1 -o yaml

Supported nodeMetadata fields

NodeSBOM and NodeVulnerabilityReport resources share a common nodeMetadata field. These fields are useful when filtering resources with kubectl get --field-selector.

Field Type Description

name

string

The name of the node in the cluster.

platform

string

The OS and CPU architecture of the node, in OS/ARCH format. Example: linux/amd64.

Disabling node scanning

There are two levels of disabling the feature:

Disabling at the configuration level either sets enabled: false in the NodeScanConfiguration resource or deletes the resource entirely:

apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: NodeScanConfiguration
metadata:
  name: default
spec:
  enabled: false
  # ...

In both cases, all NodeScanJob and NodeSBOM resources are deleted from the cluster. NodeVulnerabilityReport resources are owned by their NodeSBOM and are garbage collected with it. Scanning starts again when you set enabled back to true or recreate the configuration.

Disabling at the Helm chart level prevents the reconcilers from starting. No node-scan resources are watched or cached. This configuration saves controller memory and reduces Kubernetes API load. Use it when you do not need node scanning:

controller:
  nodeScan:
    enabled: false

Pod Security Admission

The worker DaemonSet mounts the node root filesystem read-only through a hostPath volume. It runs as root and adds DAC_READ_SEARCH. The scanner can then traverse the filesystem. The restricted and baseline Pod Security Admission profiles reject these settings. When node scanning is enabled, the installation namespace cannot enforce either profile.