Skip to main content

Security & SBOM

Purpose: For security officers, shows how to configure vulnerability scanning, SBOM generation, and image signing.

Task Summary

This guide covers three security controls applied to every container image: vulnerability scanning with Trivy (integrated into Harbor), SBOM generation in SPDX format, and cryptographic signing with cosign. Together these controls ensure that only scanned, cataloged, and signed images run in production clusters.

Prerequisites

  • Harbor deployed as a platform service with Trivy adapter enabled
  • cosign CLI installed (v2.x+)
  • trivy CLI installed for local/CI scanning
  • Signing key pair generated or Fulcio keyless signing configured

Steps

1. Configure Harbor Project Vulnerability Policy

Each Harbor project enforces a vulnerability threshold. Images exceeding the threshold are blocked from pull.

In the Harbor UI: Projects > platform-production > Configuration > Vulnerability:

  • Set "Prevent vulnerable images from running" to Enabled
  • Set severity threshold to Critical

This means any image with an unfixed Critical CVE cannot be pulled from the production project.

2. Run Trivy in CI (Pre-Push Scan)

Scan images in CI before pushing to Harbor to catch issues early:

# Scan the locally built image
trivy image --severity CRITICAL,HIGH --exit-code 1 \
--ignore-unfixed \
myservice:1.4.2-a1b2c3d

Key flags:

FlagPurpose
--severity CRITICAL,HIGHOnly fail on Critical and High CVEs
--exit-code 1Non-zero exit fails the CI pipeline
--ignore-unfixedSkip CVEs with no available fix

3. Generate an SBOM

Trivy generates SBOMs in SPDX or CycloneDX format. The platform standard is SPDX JSON:

trivy image --format spdx-json --output myservice-1.4.2.spdx.json \
harbor.opencenter.example.com/platform-dev/myservice:1.4.2-a1b2c3d

Attach the SBOM to the image as an OCI artifact:

cosign attach sbom --sbom myservice-1.4.2.spdx.json \
harbor.opencenter.example.com/platform-dev/myservice:1.4.2-a1b2c3d

Harbor also generates its own SBOM on scan. The CI-generated SBOM provides a build-time snapshot; Harbor's provides a registry-time snapshot.

4. Sign the Image with cosign

After scanning and SBOM attachment, sign the image:

# Key-pair signing
cosign sign --key cosign.key \
harbor.opencenter.example.com/platform-dev/myservice:1.4.2-a1b2c3d

# Or keyless signing (Fulcio + Rekor)
cosign sign \
harbor.opencenter.example.com/platform-dev/myservice:1.4.2-a1b2c3d

The signature is stored as an OCI artifact in the same Harbor repository.

5. Enforce Signature Verification at Admission

Kyverno verifies image signatures before pods are admitted to the cluster:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signatures
spec:
validationFailureAction: Enforce
background: false
rules:
- name: verify-cosign-signature
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "harbor.opencenter.example.com/*"
attestors:
- entries:
- keys:
publicKeys: |-
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----

Pods referencing unsigned images from Harbor are rejected with a policy violation.

Verification

Check that an image has a valid signature:

cosign verify --key cosign.pub \
harbor.opencenter.example.com/platform-production/myservice:1.4.2-a1b2c3d

Check that an SBOM is attached:

cosign verify-attestation --key cosign.pub --type spdxjson \
harbor.opencenter.example.com/platform-production/myservice:1.4.2-a1b2c3d

Troubleshooting

SymptomCauseFix
Pod rejected with "image signature not found"Image not signed or wrong keySign the image; verify the Kyverno policy references the correct public key
Trivy scan shows 0 vulnerabilitiesImage uses distroless/scratch (no OS packages)Expected behavior for minimal images; application-level deps are still scanned
SBOM missing after promotionskopeo copy didn't include OCI referrersUse cosign copy or skopeo v1.14+ with --all flag

Further Reading