# How to Export Vulnerability Scan Results from Harbor: Complete API Workflow Guide

> Easily export vulnerability scan results from Harbor using the API. Learn the complete workflow to generate CSV files with detailed vulnerability data for your images.

- Repository: [Harbor/harbor](https://github.com/goharbor/harbor)
- Tags: how-to-guide
- Published: 2026-04-09

---

**Harbor provides a scan data export feature via the `POST /api/v2.0/scan/data/export` endpoint that generates CSV files containing vulnerability details for images in a specified project.**

Harbor's vulnerability scanning capabilities generate detailed security reports for container images, and the platform offers a programmatic way to export vulnerability scan results from Harbor through its REST API. This workflow is implemented asynchronously across several Go packages in the `goharbor/harbor` repository, utilizing a job-based architecture that processes exports in the background to handle large datasets efficiently.

## Understanding the Export Architecture

The export functionality follows a four-stage pipeline implemented across the API handler, controller, and job service layers. When you initiate an export, Harbor validates your request, creates an execution record, processes the data asynchronously, and stores the result as a system artifact.

### API Handler Layer ([`src/server/v2.0/handler/scanexport.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/scanexport.go))

The `ExportScanData` method handles incoming HTTP requests and validates parameters using `validateScanExportParams`. This function checks MIME types, ensures exactly one project is specified, and verifies that repository, tag, or CVE filters contain no spaces before accepting the request.

### Controller Layer ([`src/controller/scandataexport/execution.go`](https://github.com/goharbor/harbor/blob/main/src/controller/scandataexport/execution.go))

The `Start` method in the `scandataexport.Controller` creates a `task.Execution` record and launches a `task.Job` of type `ScanDataExportVendorType`. If job creation fails, the controller marks the execution as errored using the internal `markError` function.

### Job Service Layer ([`src/jobservice/job/impl/scandataexport/scan_data_export.go`](https://github.com/goharbor/harbor/blob/main/src/jobservice/job/impl/scandataexport/scan_data_export.go))

The `Execute` method runs in Harbor's jobservice process, fetching scanner data from the specified project, formatting it into CSV rows based on the `export.Data` struct, and storing the blob via the `systemartifact.Manager`. The resulting digest is saved to the execution record's `ExportDataDigest` field.

## Step-by-Step Export Workflow

Exporting vulnerability data requires interacting with three main API endpoints to trigger, monitor, and retrieve the CSV file.

1. **Initiate the Export**: Send a POST request to `/api/v2.0/scan/data/export` with your project ID and optional filters for repositories, tags, or CVE IDs.
2. **Poll for Completion**: Query the execution status via `GET /api/v2.0/scan/data/export/executions/{id}` until `file_present` returns `true`.
3. **Download the CSV**: Retrieve the file using `GET /api/v2.0/scan/data/export/executions/{id}/download`, which streams the artifact and automatically cleans up temporary storage after completion.

## API Implementation and Code Examples

The following examples demonstrate how to interact with the Harbor API to export vulnerability scan results programmatically.

### Starting an Export Job

The handler in [`src/server/v2.0/handler/scanexport.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/scanexport.go) (lines 26-61) accepts JSON payloads containing the project ID in an array and optional filter strings.

```bash
curl -X POST "https://harbor.example.com/api/v2.0/scan/data/export" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <access_token>" \
  -H "X-Scan-Data-Type: application/vnd.scanner.adapter.scan.report.generic" \
  -d '{
        "job_name": "my-export-job",
        "projects": [42],
        "repositories": "",
        "tags": "",
        "cve_ids": ""
      }'

```

The response contains the execution ID:

```json
{
  "id": 12345
}

```

### Checking Export Status

Poll the execution endpoint implemented in `GetScanDataExportExecution` (lines 13-44 of [`scanexport.go`](https://github.com/goharbor/harbor/blob/main/scanexport.go)) to monitor progress. The endpoint returns the job status and a `file_present` boolean indicating CSV readiness.

```bash
curl -X GET "https://harbor.example.com/api/v2.0/scan/data/export/executions/12345" \
  -H "Authorization: Bearer <access_token>"

```

Successful completion shows:

```json
{
  "id": 12345,
  "status": "Success",
  "file_present": true,
  "export_data_digest": "a3f5c6..."
}

```

### Downloading the CSV Report

When `file_present` is `true`, retrieve the file using the `DownloadScanData` handler (lines 84-103 of [`scanexport.go`](https://github.com/goharbor/harbor/blob/main/scanexport.go)). This streams the CSV with `Content-Type: text/csv` and executes `cleanUpArtifact` (lines 80-99) to remove the temporary system artifact and execution record after transfer.

```bash
curl -L -X GET "https://harbor.example.com/api/v2.0/scan/data/export/executions/12345/download" \
  -H "Authorization: Bearer <access_token>" \
  -o scan_report_42.csv

```

### Listing All Export Executions

To view historical exports for your user account, call the list endpoint handled by `GetScanDataExportExecutionList`:

```bash
curl -X GET "https://harbor.example.com/api/v2.0/scan/data/export/executions" \
  -H "Authorization: Bearer <access_token>"

```

## Core Data Structures and Storage

The export system relies on models defined in [`src/pkg/scan/export/model.go`](https://github.com/goharbor/harbor/blob/main/src/pkg/scan/export/model.go):

- **`export.Data`**: Defines CSV columns for vulnerability details including CVE IDs, severity, packages, and artifacts
- **`export.Request`**: Contains the project ID array and filter criteria specified during initiation
- **`export.Execution`**: Tracks job status, user ownership via `UserName`, and the `ExportDataDigest` referencing the stored blob

The CSV content is persisted using the system artifact manager ([`src/pkg/systemartifact/manager.go`](https://github.com/goharbor/harbor/blob/main/src/pkg/systemartifact/manager.go)), which stores blobs in Harbor's configured storage backend. The digest stored in the execution record allows the `DownloadScanData` handler to locate and stream the file to the client.

## Permissions and Security Controls

The export endpoints enforce **project-level RBAC** using `rbac.ActionCreate` for initiating exports and `rbac.ActionRead` for downloading or listing executions. Additionally, the `DownloadScanData` handler compares the request's security context with the execution's `UserName` field, ensuring users can only access export files they created.

## Summary

- Harbor exports vulnerability scan results asynchronously via `POST /api/v2.0/scan/data/export`, creating background jobs handled by the jobservice
- The workflow spans four core files: [`scanexport.go`](https://github.com/goharbor/harbor/blob/main/scanexport.go) (API validation), [`execution.go`](https://github.com/goharbor/harbor/blob/main/execution.go) (controller logic), [`scan_data_export.go`](https://github.com/goharbor/harbor/blob/main/scan_data_export.go) (job implementation), and [`systemartifact/manager.go`](https://github.com/goharbor/harbor/blob/main/systemartifact/manager.go) (blob storage)
- CSV files are stored as system artifacts and retrieved via the download endpoint, with automatic cleanup via `cleanUpArtifact` after streaming
- Request validation enforces single-project scope and rejects unsupported MIME types or malformed filters containing spaces
- Access is restricted to the creating user through execution record ownership checks in the handler security context

## Frequently Asked Questions

### How long does Harbor retain exported vulnerability scan CSV files?

Harbor stores exported CSV files as system artifacts only until the download completes. According to the implementation in [`src/server/v2.0/handler/scanexport.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/scanexport.go), the `DownloadScanData` handler automatically calls `cleanUpArtifact` to delete the temporary artifact and execution record after successfully streaming the file to the client.

### Can I export vulnerability data from multiple projects simultaneously?

No. The `validateScanExportParams` function in [`src/server/v2.0/handler/scanexport.go`](https://github.com/goharbor/harbor/blob/main/src/server/v2.0/handler/scanexport.go) explicitly validates that exactly one project ID is provided in the request array. If multiple projects are specified, the handler rejects the request with a validation error to ensure manageable processing scope and file sizes.

### What CSV columns are included in the vulnerability export?

The export includes fields defined in the `export.Data` struct from [`src/pkg/scan/export/model.go`](https://github.com/goharbor/harbor/blob/main/src/pkg/scan/export/model.go), typically containing CVE IDs, severity levels, CVSS scores, package names, artifact repositories, tags, and scan timestamps. The exact column schema depends on your configured scanner adapter's report format.

### Why does my export execution show a "Running" status for an extended period?

Large projects with numerous artifacts or extensive vulnerability histories require significant processing time in the `Execute` method of [`src/jobservice/job/impl/scandataexport/scan_data_export.go`](https://github.com/goharbor/harbor/blob/main/src/jobservice/job/impl/scandataexport/scan_data_export.go). The job queries the vulnerability database, formats records into CSV rows, writes to system artifact storage, and updates the execution's `ExportDataDigest` before marking `FilePresent=true` in the database.