|
This is unreleased documentation for SBOM Scanner 0.12-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 closes this gap. It deploys a worker on every
eligible node as a DaemonSet, scans the host filesystem, and produces a
NodeSBOM and a NodeVulnerabilityReport per node. This gives you a
comprehensive overview of node-level vulnerabilities, ensuring the
safety of the infrastructure where your workloads reside.
How it works
-
A
NodeScanConfigurationresource defines the global scan settings (interval, node selector, skip patterns, platforms). -
The controller creates a
NodeScanJobfor each matching node, either on a recurring schedule or on demand. -
Each worker, running as a DaemonSet pod on the target node, receives the scan request through NATS and scans the host filesystem.
-
The worker generates a
NodeSBOM(in SPDX format) and aNodeVulnerabilityReport, stored in the Storage API Extension Server.
Default behavior
The Node Scan reconcilers are enabled by default when installing
SBOM Scanner via the Helm chart. Node scanning becomes active once you
create a NodeScanConfiguration resource. A sample configuration is
available in the
examples folder.
Configuration
The NodeScanConfiguration is a cluster-scoped singleton resource named
default. It is the single entry point for controlling the node
scanning behavior. Only one instance is allowed.
To activate node scanning after installation, apply the example configuration:
kubectl apply -f https://raw.githubusercontent.com/kubewarden/sbomscanner/main/examples/nodescanconfiguration.yaml
Or create your own configuration:
apiVersion: sbomscanner.kubewarden.io/v1alpha1
kind: NodeScanConfiguration
metadata:
name: default
spec:
scanInterval: 5m
nodeSelector:
matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- "node1"
- "node2"
skipPatterns:
- "/run/k3s/containerd/"
platforms:
- arch: "amd64"
os: "linux"
Fields
| Field | Description | Default |
|---|---|---|
|
How often nodes are scanned. If not specified, automatic scanning is
disabled and you must create |
- |
|
A standard Kubernetes label selector. Only nodes matching the selector are scanned. |
All nodes |
|
Gitignore-style patterns for files and directories to exclude from the
scan. Patterns ending with |
- |
|
Which OS/architecture combinations to scan. Each entry specifies an
|
All platforms |
Selecting which nodes to scan
Use the nodeSelector field to restrict scanning to a subset of nodes.
This is useful when some nodes do not have enough resources for scanning
or when you only want to target specific 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.
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.
Running a scan on demand
You can trigger a one-time scan by creating a NodeScanJob resource
manually. A NodeScanConfiguration must already exist in the cluster,
since the job depends on its settings (skip patterns, platforms).
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 |
|---|---|
|
The system has accepted the request and scheduled the scan. |
|
The scan is actively running on the node. |
|
The scan finished successfully. The |
|
The scan encountered a terminal error. Check the condition’s |
Common failure reasons:
| Reason | Description |
|---|---|
|
Another scan job is already running for the same node. |
|
No |
|
The target node does not match the |
|
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 |
|---|---|---|
|
string |
The name of the node in the cluster. |
|
string |
The OS and CPU architecture of the node, in |