Skip to main content

Scan images for vulnerabilities

Reviewed on · View on GitHub

This guide explains how to configure and use vulnerability scanning in the Numspot Container Registry.


Overview​

The Numspot Container Registry integrates a vulnerability scan based on Trivy, allowing you to:

  • Detect CVEs: identify known vulnerabilities in container images
  • Apply security policies: block vulnerable images at deployment
  • Meet compliance requirements: comply with security requirements for production deployments
  • Continuous monitoring: scan images on push and on a schedule

Key features​

  • Automatic scan: scan images automatically on push
  • Multiple scanners: Trivy (default), and support for external scanners
  • CVE database: up-to-date vulnerability database
  • Severity classification: CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN
  • Policy enforcement: prevent the deployment of vulnerable images
  • SBOM generation: Software Bill of Materials for supply chain security
  • Scan reports: detailed reports with remediation guidance

How vulnerability scanning works​

Scan architecture​

┌──────────────────────────────────────────────────────────┐
│ Instance Container Registry │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Image │ │ Trivy │ │ Scan │ │
│ │ push │──▶│ Adapter │──▶│ Engine │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ CVE Database │ │
│ │ │ │
│ └──────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────┐ │
│ │ Scan report │ │
│ │ (Results) │ │
│ └──────────────────┘ │
└──────────────────────────────────────────────────────────┘

Scan triggers​

TriggerDescription
On pushAutomatic scan when an image is pushed
ManualTrigger a scan through the interface or the API
ScheduledPeriodic rescan (daily, weekly)
On demandScans triggered through the API

Prerequisites​

  • Container Registry instance: a running Numspot Container Registry
  • Administrator or project administrator access: required to configure the scan
  • Trivy scanner: enabled by default in Numspot registries

Step 1: Configure the scan settings​

Through the Harbor interface​

  1. Log in to the Harbor interface as a system administrator
  2. Navigate to Administration → Interrogation Services → Scanners
  3. Configure the Trivy scanner:
SettingValue
NameTrivy
ProviderAqua Security
DescriptionTrivy vulnerability scanner
URLhttp://harbor-trivy:8080
Auth typeAucun (internal)
  1. Click Set as default to make Trivy the default scanner

Project-level scan configuration​

  1. Navigate to Projects → Select the project → Configuration
  2. Configure the scan:
SettingValue
Automatically scan images on pushEnable
Prevent vulnerable images from runningEnable (optional)
SeveritySelect the severity levels to block
Stop pulling images with CVE exemptionsConfigure as needed

Through the API​

curl -X PUT "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/scanner" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"is_default_scanner": true,
"use_project_scanner": false
}'

# Enable automatic scan on push
curl -X PUT "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"auto_scan": "true"
}
}'

Step 2: Scan the images​

Automatic scan on push​

When automatic scan is enabled:

  1. Push an image:
docker push registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/myproject/myimage:v1.0
  1. Harbor automatically triggers a Trivy scan
  2. The scan completes within a few seconds to a few minutes (depending on the image size)

Manual scan​

Through the Harbor interface​

  1. Navigate to Projects → Select the project → Repositories
  2. Click the repository
  3. Click the artifact tag
  4. Click the Scan button
  5. Select the scanner: Trivy
  6. Wait for the scan to finish
  7. Review the scan results

Through the API​

curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/scan" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"scan_type": "vulnerability"
}'

Scheduled scan​

Configure periodic rescans:

  1. Navigate to Administration → Interrogation Services → Scanners
  2. Click Schedule for the Trivy scanner
  3. Configure the cron schedule:
0 2 * * * # Daily at 2 a.m.
0 2 * * 0 # Weekly on Sunday

Step 3: Review the scan results​

Through the Harbor interface​

  1. Navigate to the repository and the artifact
  2. Review the Vulnerabilities tab
  3. View:
  • Total vulnerabilities: count by severity
  • Summary: CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN
  • Vulnerability list: detailed information on the CVEs
  • Package information: affected package and version
  • Fixed version: remediation guidance

Vulnerability details​

FieldDescription
CVE IDCVE identifier (e.g. CVE-2023-12345)
SeverityCRITICAL, HIGH, MEDIUM, LOW, UNKNOWN
PackageName of the affected package
VersionInstalled version
Fixed versionVersion with the fix (if available)
DescriptionDescription of the vulnerability
LinksReferences to the CVE details

Through the API​

# Get the scan report
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/scan" \
-u "admin:{password}"

# Get the vulnerability summary
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/additions/vulnerabilities" \
-u "admin:{password}" | jq '.scan_overview'

Response:

{
"scan_overview": {
"application/vnd.scanner.adapter.vuln.report.harbor+json; version=1.0": {
"report_id": "abc123",
"scan_status": "Success",
"severity": "HIGH",
"duration": 45,
"summary": {
"total": 25,
"fixable": 18,
"summary": {
"CRITICAL": 2,
"HIGH": 8,
"MEDIUM": 10,
"LOW": 5,
"UNKNOWN": 0
}
},
"start_time": "2026-05-05T10:00:00Z",
"end_time": "2026-05-05T10:00:45Z"
}
}
}

Step 4: Apply security policies​

Prevent vulnerable images from running​

Block images with vulnerabilities above a threshold:

  1. Navigate to Projects → Select the project → Configuration
  2. Enable Prevent vulnerable images from running
  3. Select the severity levels to block:
  • CRITICAL (recommended)
  • HIGH (recommended)
  • MEDIUM (optional)
  • LOW (optional)

Once enabled:

  • images with vulnerabilities at the selected levels or higher cannot be pulled
  • Harbor returns 403 Forbidden for vulnerable images
  • the scan must be completed before the image can be pulled

Through the API​

curl -X PUT "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"metadata": {
"auto_scan": "true",
"prevent_vul": "true",
"severity": "high,critical"
}
}'

CVE allowlist​

Allow specific CVEs to permit images with known exceptions:

  1. Navigate to Administration → Configuration → System Settings
  2. Scroll to CVE Allowlist
  3. Add the CVE IDs to allow:
CVE-2023-12345
CVE-2023-67890
  1. Click Save

Through the API​

curl -X PUT "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/system/CVEWhitelist" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"items": [
{"cve_id": "CVE-2023-12345"},
{"cve_id": "CVE-2023-67890"}
]
}'

Severity classification​

SeverityDescriptionRecommendation
CRITICALExploitable, immediate riskFix immediately
HIGHSignificant risk, prioritize the fixFix in the next release
MEDIUMModerate risk, should be fixedFix when possible
LOWMinor risk, informationalAssess the impact
UNKNOWNInsufficient data to classifyInvestigate further

Best practices​

Scan strategy​

  1. Enable automatic scan: scan on every push
  2. Block critical vulnerabilities: prevent the deployment of CRITICAL and HIGH
  3. Regular rescans: schedule weekly scans for the updated CVE databases
  4. Scan base images: ensure that base images are free of vulnerabilities
  5. Validate before production: scan in staging before promotion to production

Remediation flow​

  1. Identify the vulnerabilities: review the scan report
  2. Prioritize the fixes: focus on CRITICAL and HIGH first
  3. Update the packages: upgrade to the fixed versions
  4. Verify the fixes: rescan after remediation
  5. Document the exceptions: use the CVE allowlist for accepted risks

CI/CD integration​

Integrate vulnerability scanning into your CI/CD pipeline:

# GitLab CI example
scan-image:
stage: security
image: docker:latest
services:
- docker:dind
script:
- docker login -u "$HARBOR_USER" -p "$HARBOR_PASSWORD" $HARBOR_REGISTRY
- docker pull $HARBOR_REGISTRY/myproject/myimage:$CI_COMMIT_SHA
- |
SCAN_RESULT=$(curl -s -u "$HARBOR_USER:$HARBOR_PASSWORD" \
"$HARBOR_REGISTRY/api/v2.0/projects/myproject/repositories/myimage/artifacts/$CI_COMMIT_SHA/scan" | jq -r '.scan_overview[].severity')
if [ "$SCAN_RESULT" == "CRITICAL" ] || [ "$SCAN_RESULT" == "HIGH" ]; then
echo "Vulnerabilities detected: $SCAN_RESULT"
exit 1
fi
allow_failure: false

Advanced features​

SBOM generation​

Generate a Software Bill of Materials:

  1. Navigate to the artifact details
  2. Click the SBOM tab
  3. View the packages and dependencies
  4. Export the SBOM in SPDX or CycloneDX format

Through the API​

curl -X POST "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/scan" \
-u "admin:{password}" \
-H "Content-Type: application/json" \
-d '{
"scan_type": "sbom"
}'

Trivy configuration​

Trivy configuration options:

SettingDescriptionDefault value
Skip updateSkip the update of the CVE databasefalse
Offline scanUse the cached databasefalse
SeverityMinimum severity to reportUNKNOWN
Ignore unfixedIgnore vulnerabilities without a fixfalse

Monitoring and reporting​

Scan metrics​

Monitor scan performance:

  1. Navigate to Administration → Metrics
  2. Review the scan metrics:
  • total images scanned
  • vulnerabilities detected by severity
  • scan duration trends
  • scanner queue length

Security dashboard​

View the security posture:

  1. Navigate to Administration → Security Hub
  2. Review:
  • vulnerability summary per project
  • most vulnerable images
  • most common CVEs
  • security trends over time

Export reports​

Export the vulnerability reports:

# Get all vulnerabilities for an artifact
curl -X GET "https://registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/additions/vulnerabilities" \
-u "admin:{password}" > rapport-vulnerabilites.json

Troubleshooting​

Issue 1: Scan timeout​

Symptom: the scan takes too long or times out

Solutions:

  1. Increase the scanner timeout:
kubectl patch deployment harbor-trivy -n registry-instance-{registryId} --type=json -p='[{"op": "add", "path": "/spec/template/spec/containers/0/env/-", "value": {"name": "SCANNER_TIMEOUT", "value": "10m"}}]'
  1. Check the Trivy pod resources
  2. Check the network connectivity to the CVE database
  3. Consider scanning smaller images

Issue 2: Scanner unavailable​

Symptom: scans fail with scanner unavailable

Solutions:

  1. Check the status of the Trivy pod:
kubectl get pods -n registry-instance-{registryId} | grep trivy
  1. Review the Trivy pod logs:
kubectl logs -n registry-instance-{registryId} deployment/harbor-trivy
  1. Contact Numspot support

Issue 3: Outdated CVE database​

Symptom: CVEs not detected or outdated

Solutions:

  1. Trigger the update of the Trivy database:
kubectl rollout restart deployment/harbor-trivy -n registry-instance-{registryId}
  1. Wait for the database update to complete
  2. Rescan the affected images

Issue 4: False positives​

Symptom: CVEs incorrectly reported

Solutions:

  1. Verify the applicability of the CVE to your use case
  2. Add the CVEs to the allowlist if the risk is accepted
  3. Document the justification for the acceptance
  4. Report the false positives to the Trivy project

API reference​

Trigger a scan​

POST /api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/scan
Authorization: Basic {base64(admin:password)}
Content-Type: application/json

{
"scan_type": "vulnerability | sbom"
}

Get the scan report​

GET /api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/scan
Authorization: Basic {base64(admin:password)}

Get the vulnerability details​

GET /api/v2.0/projects/{project_id}/repositories/{repository_name}/artifacts/{digest}/additions/vulnerabilities
Authorization: Basic {base64(admin:password)}

Update the project scan settings​

PUT /api/v2.0/projects/{project_id}
Authorization: Basic {base64(admin:password)}
Content-Type: application/json

{
"metadata": {
"auto_scan": "true",
"prevent_vul": "true",
"severity": "high,critical"
}
}

Limitations​

  • File system scan only: Trivy scans the file system, not running containers
  • Licensed software: may not detect vulnerabilities in proprietary software
  • CVE database lag: new CVEs may not be immediately available
  • False negatives: some vulnerabilities may not be detected
  • Resource-intensive: large images require more scan time and resources