Skip to content

Dem1241/harbor-scanner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

harbor-scanner

harbor-scanner is a small Go CLI for working with Harbor image scans.

It helps with two common cases:

  • an image already exists in Harbor and you want to scan it
  • an image exists locally and you want to push it to Harbor, scan it, and save the report

It does not scan images by itself. Harbor and Trivy do that part. This tool just automates the workflow around them.

What it does

The CLI can:

  • publish an image to Harbor
  • trigger a scan
  • wait for the scan to finish
  • fetch the vulnerability report
  • print a severity summary
  • save the full report as JSON

Requirements

You need:

  • a running Harbor instance
  • Harbor configured with Trivy or another compatible scanner
  • a Harbor user or robot account with permission to push images and trigger scans
  • a local container CLI if you want to publish images

Supported local CLIs:

  • docker
  • podman
  • nerdctl

Configuration

Set these environment variables:

export HARBOR_URL=http://harbor.local
export HARBOR_USER=admin
export HARBOR_PASSWORD=your-password-or-robot-token

Optional:

export HARBOR_REGISTRY=harbor-registry.local
export CONTAINER_CLI=podman

Notes:

  • HARBOR_URL is the Harbor API base URL.
  • HARBOR_REGISTRY is optional. Use it when the registry hostname is different from the Harbor API hostname.
  • CONTAINER_CLI is optional. It defaults to docker.

Login

Before publishing images, log your container CLI into Harbor:

docker login harbor.local

If you use Podman:

podman login harbor.local

If Harbor is running over plain HTTP, your container runtime must be configured to trust that registry.

Build

go build -o harbor-scanner

Quick start

1. Check Harbor health

./harbor-scanner health

2. Scan an image that is already in Harbor

./harbor-scanner scan-wait library demo-nginx 1.21 reports/demo-nginx-1.21.json

This:

  • triggers the scan
  • waits for it to finish
  • prints the summary
  • writes the full JSON report to reports/demo-nginx-1.21.json

3. Publish and scan an image in one step

./harbor-scanner publish-scan nginx:1.21 library demo-nginx 1.21 reports/demo-nginx-1.21.json

This is the main end-to-end workflow.

4. Use Podman instead of Docker

export CONTAINER_CLI=podman
./harbor-scanner publish-scan nginx:1.21 library demo-nginx 1.21 reports/demo-nginx-1.21.json

You can do the same with nerdctl:

export CONTAINER_CLI=nerdctl
./harbor-scanner publish-scan nginx:1.21 library demo-nginx 1.21 reports/demo-nginx-1.21.json

Commands

health

Checks whether Harbor is reachable.

./harbor-scanner health

publish

Pushes a local or remote image into Harbor.

./harbor-scanner publish <source-image> <project> <repository> <tag>

Example:

./harbor-scanner publish nginx:1.21 library demo-nginx 1.21

Internally this does the equivalent of:

docker pull nginx:1.21
docker tag nginx:1.21 harbor.local/library/demo-nginx:1.21
docker push harbor.local/library/demo-nginx:1.21

Except it uses whatever is set in CONTAINER_CLI.

scan

Starts a scan for an image that already exists in Harbor.

./harbor-scanner scan <project> <repository> <tag-or-digest>

Example:

./harbor-scanner scan library demo-nginx 1.21

report

Fetches and prints an existing vulnerability report.

./harbor-scanner report <project> <repository> <tag-or-digest>

Example:

./harbor-scanner report library demo-nginx 1.21

scan-wait

Triggers a scan, waits for completion, and writes a JSON report.

./harbor-scanner scan-wait <project> <repository> <tag-or-digest> <output-file.json>

Example:

./harbor-scanner scan-wait library demo-nginx 1.21 reports/demo-nginx-1.21.json

publish-scan

Publishes an image, scans it, waits for completion, and writes a JSON report.

./harbor-scanner publish-scan <source-image> <project> <repository> <tag> <output-file.json>

Example:

./harbor-scanner publish-scan nginx:1.21 library demo-nginx 1.21 reports/demo-nginx-1.21.json

For a locally built app:

docker build -t my-api:dev .
./harbor-scanner publish-scan my-api:dev library my-api dev reports/my-api-dev.json

Image naming

A Harbor image reference looks like this:

harbor.local/library/demo-nginx:1.21

Parts:

  • harbor.local: registry host
  • library: Harbor project
  • demo-nginx: repository name
  • 1.21: tag

Report format

Saved reports contain:

  • project
  • repository
  • reference
  • image
  • generated timestamp
  • severity summary
  • full findings list

Example:

{
  "project": "library",
  "repository": "demo-nginx",
  "reference": "1.21",
  "image": "library/demo-nginx:1.21",
  "generated_at": "2026-06-03T21:30:00+02:00",
  "summary": {
    "CRITICAL": 28,
    "HIGH": 159,
    "MEDIUM": 262,
    "LOW": 209,
    "UNKNOWN": 15
  },
  "findings": [
    {
      "id": "CVE-2024-56171",
      "severity": "CRITICAL",
      "package": "libxml2",
      "version": "2.9.10",
      "fixed_version": "2.9.10+patched",
      "description": "Example vulnerability description"
    }
  ]
}

Typical workflows

Full workflow:

export HARBOR_URL=http://harbor.local
export HARBOR_USER=admin
export HARBOR_PASSWORD=your-password

docker login harbor.local

./harbor-scanner publish-scan nginx:1.21 library demo-nginx 1.21 reports/demo-nginx-1.21.json

Existing Harbor image only:

export HARBOR_URL=http://harbor.local
export HARBOR_USER=admin
export HARBOR_PASSWORD=your-password

./harbor-scanner scan-wait library demo-nginx 1.21 reports/demo-nginx-1.21.json

For shared or production usage, a Harbor robot account is usually better than a personal admin account.