OSV Server
A self-hosted Open-Source Vulnerabilities (OSV) API server written in Go. Provides local access to the OSV vulnerability database with automatic updates and resumable downloads.
Features
- Automatic initial data download on startup
- Configurable periodic updates (default: 24 hours)
- Resumable downloads with crash recovery
- Hash verification and staleness detection
- Background updates that don't block the API
- Health check and statistics endpoints
- Minimal dependencies (Chi router only)
- Static binary builds for easy deployment
- Decentralized distribution of the database
Todo
- Reticulum support
Install
go install git.quad4.io/quad4-software/osv-server/cmd/osv-server@latest
Building
Development Build
make build
Release Build (Static, Stripped)
make release
This creates a statically linked binary optimized for production deployment in bin/osv-server.
Configuration
Configuration priority (highest to lowest):
- Command-line flags
- Environment variables
config.inifile- Default values
Command-Line Flags
./osv-server \
-port 8080 \
-data-dir ./data \
-update-interval 24h \
-osv-base-url https://storage.googleapis.com/osv-vulnerabilities \
-max-retries 3 \
-retry-delay 5s \
-enable-download-endpoint \
-config config.ini
Environment Variables
export OSV_PORT=8080
export OSV_DATA_DIR=./data
export OSV_UPDATE_INTERVAL=24h
export OSV_BASE_URL=https://storage.googleapis.com/osv-vulnerabilities
export OSV_MAX_RETRIES=3
export OSV_RETRY_DELAY=5s
export OSV_ENABLE_DOWNLOAD_ENDPOINT=true
Config File (config.ini)
port = 8080
data_dir = ./data
update_interval = 24h
osv_base_url = https://storage.googleapis.com/osv-vulnerabilities
max_retries = 3
retry_delay = 5s
enable_download_endpoint = true
Default Values
- Port:
8080 - Data Directory:
./data - Update Interval:
24h - OSV Base URL:
https://storage.googleapis.com/osv-vulnerabilities - Max Retries:
3 - Retry Delay:
5s - Enable Download Endpoint:
false(disabled by default for security)
Usage
Start the server:
./osv-server
The server will:
- Start downloading the OSV database in the background and indexing it (this might take a while)
- Begin serving API requests immediately
- Automatically update the database at configured intervals
API Endpoints
Health Check
Check if the server is running and if data is available.
curl http://localhost:8080/health
Response:
{
"status": "healthy"
}
Status values:
healthy- Server is running and data is availableinitializing- Server is running but data is still downloading
Statistics
Get download and update statistics.
curl http://localhost:8080/stats
Response:
{
"last_update": "2025-12-26T00:00:00Z",
"last_update_error": "",
"total_downloads": 1,
"failed_downloads": 0,
"update_in_progress": false
}
Query
Query the OSV database. Currently serves the full database zip file.
curl -O http://localhost:8080/v1/query
Batch Query
Batch query endpoint. Currently serves the full database zip file.
curl -O http://localhost:8080/v1/querybatch
Download Endpoint (Decentralized Distribution)
Enable the download endpoint to allow other OSV servers and clients to download the verified database from your server. This enables decentralized distribution where servers share the database with each other.
Enable via flag:
./osv-server -enable-download-endpoint
Enable via environment:
export OSV_ENABLE_DOWNLOAD_ENDPOINT=true
Enable via config file:
enable_download_endpoint = true
Download from another server:
curl -O http://other-osv-server:8080/v1/download
The endpoint includes verification headers:
X-OSV-Hash: SHA256 hash of the database fileX-OSV-Last-Modified: Last modification timestampX-OSV-Size: File size in bytes
Example with verification:
curl -O -H "Accept: application/zip" http://other-osv-server:8080/v1/download
# Verify hash from headers
curl -I http://other-osv-server:8080/v1/download | grep X-OSV-Hash
Use as download source in another server:
export OSV_BASE_URL=http://other-osv-server:8080/v1/download
./osv-server
This creates a decentralized network where OSV servers can download from each other, reducing load on the primary Google Cloud Storage bucket and enabling faster local distribution.
Vulnerability Checking Examples
Download and Extract Database
First, download the complete OSV database:
curl -o osv-db.zip http://localhost:8080/v1/query
unzip osv-db.zip -d osv-db/
Query by Package (Standard OSV API Format)
The standard OSV API uses POST requests with JSON payloads. Example queries:
Check a Python package:
curl -X POST http://localhost:8080/v1/query \
-H "Content-Type: application/json" \
-d '{
"package": {
"name": "requests",
"ecosystem": "PyPI"
},
"version": "2.28.0"
}'
Check a Go package:
curl -X POST http://localhost:8080/v1/query \
-H "Content-Type: application/json" \
-d '{
"package": {
"name": "github.com/gin-gonic/gin",
"ecosystem": "Go"
},
"version": "v1.9.0"
}'
Check an npm package:
curl -X POST http://localhost:8080/v1/query \
-H "Content-Type: application/json" \
-d '{
"package": {
"name": "lodash",
"ecosystem": "npm"
},
"version": "4.17.20"
}'
Batch Query Multiple Packages
Check multiple packages in a single request:
curl -X POST http://localhost:8080/v1/querybatch \
-H "Content-Type: application/json" \
-d '{
"queries": [
{
"package": {
"name": "requests",
"ecosystem": "PyPI"
},
"version": "2.28.0"
},
{
"package": {
"name": "github.com/gin-gonic/gin",
"ecosystem": "Go"
},
"version": "v1.9.0"
}
]
}'
Query by Commit Hash
Check vulnerabilities by commit hash:
curl -X POST http://localhost:8080/v1/query \
-H "Content-Type: application/json" \
-d '{
"commit": "6879efc2c1596d11a6a6ad296f800f2ee0a2c0db"
}'
Query by Package Name Only
Get all vulnerabilities for a package:
curl -X POST http://localhost:8080/v1/query \
-H "Content-Type: application/json" \
-d '{
"package": {
"name": "requests",
"ecosystem": "PyPI"
}
}'
Example Response
Successful query response:
{
"vulns": [
{
"id": "GHSA-xxxx-xxxx-xxxx",
"summary": "Vulnerability description",
"details": "Detailed information...",
"modified": "2024-01-01T00:00:00Z",
"published": "2024-01-01T00:00:00Z",
"affected": [
{
"package": {
"name": "requests",
"ecosystem": "PyPI"
},
"ranges": [
{
"type": "ECOSYSTEM",
"events": [
{
"introduced": "2.27.0"
},
{
"fixed": "2.28.1"
}
]
}
],
"versions": ["2.27.0", "2.28.0"]
}
],
"references": [
{
"type": "ADVISORY",
"url": "https://github.com/advisories/..."
}
]
}
]
}
Using with Gitea Actions
Example Gitea Actions workflow:
name: OSV Scan
on: [push, pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Check vulnerabilities
run: |
for pkg in $(cat go.mod | grep -E '^\s+\w+' | awk '{print $1}'); do
curl -X POST http://your-osv-server:8080/v1/query \
-H "Content-Type: application/json" \
-d "{\"package\":{\"name\":\"$pkg\",\"ecosystem\":\"Go\"}}" \
| jq '.vulns[] | select(. != null)'
done
Note: The current implementation serves the complete database zip file. Full query endpoint implementation with JSON parsing and filtering is recommended for production use.
Architecture
cmd/osv-server/ - Main application entry point
internal/
api/ - HTTP API handlers and routes
config/ - Configuration management
downloader/ - HTTP downloader with resume support
osv/ - OSV data manager and scheduler
storage/ - File storage and metadata tracking
Data Management
The server downloads the complete OSV database from Google Cloud Storage:
- Source:
gs://osv-vulnerabilities/all.zip - Stored locally in the configured data directory
- Metadata tracked for hash verification and staleness detection
- Automatic updates based on Last-Modified headers and configured interval
Error Handling
- Automatic retry with exponential backoff for failed downloads
- Resumable downloads recover from crashes and unexpected restarts
- Background updates don't interrupt API availability
- Errors logged but don't crash the server
License
See LICENSE