Skip to content

Go SDK

The Go SDK is the type-safe foundation under both the CLI and the Skills. Use it when embedding OSV parsing/filtering/querying into a Go application.

Install

bash
go get -u github.com/scagogogo/osv-schema-skills
go
import osv "github.com/scagogogo/osv-schema-skills"

Quick start

go
package main

import (
    "fmt"
    "log"

    osv "github.com/scagogogo/osv-schema-skills"
)

func main() {
    // Parse OSV data from a JSON file
    v, err := osv.UnmarshalFromJsonFile[any, any]("vulnerability.json")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("ID: %s\n", v.ID)
    fmt.Printf("Summary: %s\n", v.Summary)

    // Get CVE from aliases
    if cve := v.Aliases.GetCVE(); cve != "" {
        fmt.Printf("CVE: %s\n", cve)
    }

    // Check if a specific ecosystem is affected
    if v.Affected.HasEcosystem(osv.EcosystemPyPI) {
        fmt.Println("Affects PyPI packages")
    }

    // Get CVSS v3 score
    if cvss3 := v.Severity.GetCVSS3(); cvss3 != nil {
        fmt.Printf("CVSS v3: %.1f\n", cvss3.GetScore())
    }
}

From JSON to code: object lifecycle

Core type

go
type OsvSchema[EcosystemSpecific, DatabaseSpecific any] struct {
    SchemaVersion    string
    ID               string
    Modified         time.Time
    Published        time.Time
    Withdrawn        string // string, not time.Time — check non-empty for withdrawn
    Aliases          Aliases
    Related          Related
    Summary          string
    Details          string
    Severity         SeveritySlice
    Affected         AffectedSlice[EcosystemSpecific, DatabaseSpecific]
    References       References
    DatabaseSpecific DatabaseSpecific
    Credits          *Credits
}

Generic type parameters EcosystemSpecific and DatabaseSpecific let you attach custom data per ecosystem or vulnerability database. Use any for general-purpose parsing.

Type relationships at a glance

Key methods

See the full table in Reference → Methods. Highlights:

TypeMethodDescription
OsvSchemaAffected.HasEcosystem(eco)Check if ecosystem is affected
AffectedSliceFilterByEcosystem(eco)Filter affected packages
AliasesGetCVE()Get first CVE identifier
SeveritySliceGetCVSS3() / GetCVSS2()Get CVSS severity entry
SeverityGetScore()Parse score as float64
ReferencesFilterByType(t)Filter by reference type
PackageIsMaven() / GetGroupID() / GetArtifactID()Maven decomposition

Serialization

Every core type carries json, yaml, mapstructure, db, bson, gorm tags — JSON, YAML, mapstructure, GORM, and MongoDB (BSON) work out of the box.

Typed vendor fields — a worked example

[any, any] is right for most parsing, but when you repeatedly read a known database_specific shape (e.g. GitHub's advisory blob), give it a concrete type and the compiler checks your field access.

go
// Define the shape of the vendor blob you care about
type GHSA struct {
    Severity        string   `json:"severity"`
    CWEIDs          []string `json:"cwe_ids"`
    GitHubReviewedAt string  `json:"github_reviewed_at"`
}

// Parse with the concrete type as DatabaseSpecific
v, err := osv.UnmarshalFromJsonFile[any, GHSA]("ghsa.json")
if err != nil {
    log.Fatal(err)
}
// v.DatabaseSpecific is now a typed GHSA — no map[string]any casting
fmt.Println(v.DatabaseSpecific.Severity, v.DatabaseSpecific.CWEIDs)

Only pay for the types you need

The two parameters are independent. Type just DatabaseSpecific and leave EcosystemSpecific as any (or vice-versa) — you don't have to model both blobs to get typing on one.

Design notes

  • Never nil on success, always nil on errorUnmarshalFromJsonFile / UnmarshalFromJson return (nil, err) on failure and a non-nil *OsvSchema on success. Check err before touching the pointer.
  • Withdrawn is a string — not time.Time. Check for a non-empty string to determine withdrawal status.
  • No omitempty on the SDK struct — the OsvSchema / Event / Package structs carry serialization tags but no omitempty. So json.Marshal(v) of a partially-filled record emits empty fields ("withdrawn": "", "published":"0001-01-01T00:00:00Z", "fixed": ""). The CLI's -o json avoids this by routing through its own DTO layer with omitempty; if you need the same clean output from the SDK, build a DTO or post-filter empties yourself.
  • Database strategy — simple fields are columns; complex nested structures (AffectedSlice, SeveritySlice) are stored as JSON strings via the GORM serializer.

Requirements

  • Go 1.18+

Last updated:

Released under the MIT License.