Scan images for vulnerabilities
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
| Trigger | Description |
|---|---|
| On push | Automatic scan when an image is pushed |
| Manual | Trigger a scan through the interface or the API |
| Scheduled | Periodic rescan (daily, weekly) |
| On demand | Scans 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
- Log in to the Harbor interface as a system administrator
- Navigate to Administration → Interrogation Services → Scanners
- Configure the Trivy scanner:
| Setting | Value |
|---|---|
| Name | Trivy |
| Provider | Aqua Security |
| Description | Trivy vulnerability scanner |
| URL | http://harbor-trivy:8080 |
| Auth type | Aucun (internal) |
- Click Set as default to make Trivy the default scanner
Project-level scan configuration
- Navigate to Projects → Select the project → Configuration
- Configure the scan:
| Setting | Value |
|---|---|
| Automatically scan images on push | Enable |
| Prevent vulnerable images from running | Enable (optional) |
| Severity | Select the severity levels to block |
| Stop pulling images with CVE exemptions | Configure 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:
- Push an image:
docker push registry-{registryId}.hcp.cloudgouv-eu-west-1.numspot.com/myproject/myimage:v1.0
- Harbor automatically triggers a Trivy scan
- The scan completes within a few seconds to a few minutes (depending on the image size)
Manual scan
Through the Harbor interface
- Navigate to Projects → Select the project → Repositories
- Click the repository
- Click the artifact tag
- Click the Scan button
- Select the scanner: Trivy
- Wait for the scan to finish
- 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:
- Navigate to Administration → Interrogation Services → Scanners
- Click Schedule for the Trivy scanner
- 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
- Navigate to the repository and the artifact
- Review the Vulnerabilities tab
- 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
| Field | Description |
|---|---|
| CVE ID | CVE identifier (e.g. CVE-2023-12345) |
| Severity | CRITICAL, HIGH, MEDIUM, LOW, UNKNOWN |
| Package | Name of the affected package |
| Version | Installed version |
| Fixed version | Version with the fix (if available) |
| Description | Description of the vulnerability |
| Links | References 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:
- Navigate to Projects → Select the project → Configuration
- Enable Prevent vulnerable images from running
- 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:
- Navigate to Administration → Configuration → System Settings
- Scroll to CVE Allowlist
- Add the CVE IDs to allow:
CVE-2023-12345
CVE-2023-67890
- 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
| Severity | Description | Recommendation |
|---|---|---|
| CRITICAL | Exploitable, immediate risk | Fix immediately |
| HIGH | Significant risk, prioritize the fix | Fix in the next release |
| MEDIUM | Moderate risk, should be fixed | Fix when possible |
| LOW | Minor risk, informational | Assess the impact |
| UNKNOWN | Insufficient data to classify | Investigate further |
Best practices
Scan strategy
- Enable automatic scan: scan on every push
- Block critical vulnerabilities: prevent the deployment of CRITICAL and HIGH
- Regular rescans: schedule weekly scans for the updated CVE databases
- Scan base images: ensure that base images are free of vulnerabilities
- Validate before production: scan in staging before promotion to production
Remediation flow
- Identify the vulnerabilities: review the scan report
- Prioritize the fixes: focus on CRITICAL and HIGH first
- Update the packages: upgrade to the fixed versions
- Verify the fixes: rescan after remediation
- 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:
- Navigate to the artifact details
- Click the SBOM tab
- View the packages and dependencies
- 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:
| Setting | Description | Default value |
|---|---|---|
| Skip update | Skip the update of the CVE database | false |
| Offline scan | Use the cached database | false |
| Severity | Minimum severity to report | UNKNOWN |
| Ignore unfixed | Ignore vulnerabilities without a fix | false |
Monitoring and reporting
Scan metrics
Monitor scan performance:
- Navigate to Administration → Metrics
- Review the scan metrics:
- total images scanned
- vulnerabilities detected by severity
- scan duration trends
- scanner queue length
Security dashboard
View the security posture:
- Navigate to Administration → Security Hub
- 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:
- 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"}}]'
- Check the Trivy pod resources
- Check the network connectivity to the CVE database
- Consider scanning smaller images
Issue 2: Scanner unavailable
Symptom: scans fail with scanner unavailable
Solutions:
- Check the status of the Trivy pod:
kubectl get pods -n registry-instance-{registryId} | grep trivy
- Review the Trivy pod logs:
kubectl logs -n registry-instance-{registryId} deployment/harbor-trivy
- Contact Numspot support
Issue 3: Outdated CVE database
Symptom: CVEs not detected or outdated
Solutions:
- Trigger the update of the Trivy database:
kubectl rollout restart deployment/harbor-trivy -n registry-instance-{registryId}
- Wait for the database update to complete
- Rescan the affected images
Issue 4: False positives
Symptom: CVEs incorrectly reported
Solutions:
- Verify the applicability of the CVE to your use case
- Add the CVEs to the allowlist if the risk is accepted
- Document the justification for the acceptance
- 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