Skip to main content
CleanStart

Knowledge Hub

Source Intelligence Core SDK Quick Start: Go

The CleanStart Source Intelligence Core SDK for Go provides programmatic access to vulnerability data, package metadata, and supply chain intelligence. Query CVEs, track fix status, and monitor dependencies in your Go projects.

Installation

Add the module to your Go project using go get github.com/cleanstart/intelligence-go. Verify installation by running go list -m github.com/cleanstart/intelligence-go. Update to the latest version using go get -u github.com/cleanstart/intelligence-go.

Configuration

Set your API key as an environment variable with export CLEANSTART_API_KEY="your-api-key-here". Alternatively, pass it when creating the client as shown below.

import "github.com/cleanstart/intelligence-go" client := intelligence.NewClient(    intelligence.WithAPIKey("your-api-key-here"),)

To obtain an API key, visit dashboard.cleanstart.com and follow these steps. First, log in to your account. Next, navigate to Settings > API Keys. Then click Generate New Key. Select the scope Source Intelligence Read (minimum). Finally, copy the key and store it securely.

First Query

Query vulnerabilities by CVE ID using the code below.

package main import (    "context"    "fmt"    "log"     "github.com/cleanstart/intelligence-go") func main() {    client := intelligence.NewClient()    ctx := context.Background()     // Query CVE    vuln, err := client.Vulnerabilities.GetByCVEID(ctx, "CVE-2024-1234")    if err != nil {        log.Fatal(err)    }     fmt.Printf("CVE: %s\n", vuln.CVEID)    fmt.Printf("Severity: %s\n", vuln.Severity)    fmt.Printf("CVSS Score: %.1f\n", vuln.CVSSScore)    fmt.Printf("Description: %s\n", vuln.Description)}

Querying Vulnerabilities

By CVE ID

vuln, err := client.Vulnerabilities.GetByCVEID(ctx, "CVE-2024-1234")if err != nil {    log.Fatal(err)} fmt.Printf("CVEID: %s\n", vuln.CVEID)fmt.Printf("Severity: %s\n", vuln.Severity)fmt.Printf("CVSS Score: %.1f\n", vuln.CVSSScore)fmt.Printf("Description: %s\n", vuln.Description)

By Package Name

vulns, err := client.Vulnerabilities.GetByPackage(ctx, &intelligence.PackageQuery{    Name:     "django",    Ecosystem: "pypi",    Limit:    10,})if err != nil {    log.Fatal(err)} for _, vuln := range vulns.Results {    fmt.Printf("%s: %s\n", vuln.CVEID, vuln.Description)}

By Ecosystem

vulns, err := client.Vulnerabilities.GetByEcosystem(ctx, &intelligence.EcosystemQuery{    Ecosystem: "npm",    Severity:  "HIGH",    Limit:     50,})if err != nil {    log.Fatal(err)} fmt.Printf("Found %d HIGH severity vulnerabilities\n", len(vulns.Results))for _, vuln := range vulns.Results {    fmt.Printf("- %s: %v\n", vuln.CVEID, vuln.AffectedPackages)}

Advanced Filtering

vulns, err := client.Vulnerabilities.Search(ctx, &intelligence.VulnerabilityFilter{    SeverityMin:     "HIGH",    CVSSScoreMin:    7.0,    HasFix:          true,    PublishedAfter:  "2024-01-01",    Pagination: &intelligence.Pagination{        Page:  1,        Limit: 20,    },})if err != nil {    log.Fatal(err)} fmt.Printf("Total results: %d\n", vulns.Pagination.Total)fmt.Printf("Page: %d of %d\n", vulns.Pagination.Page, vulns.Pagination.Pages) for _, vuln := range vulns.Results {    // Process vulnerability}

Paginated Results

// Iterate through all pagesfilter := &intelligence.VulnerabilityFilter{    SeverityMin: "HIGH",} for page := 1; page <= 100; page++ {    filter.Pagination = &intelligence.Pagination{        Page:  page,        Limit: 100,    }     results, err := client.Vulnerabilities.Search(ctx, filter)    if err != nil {        log.Fatal(err)    }     for _, vuln := range results.Results {        // Process each vulnerability    }     if !results.Pagination.HasNext {        break    }}

Package and Version Information

Get Package Metadata

pkg, err := client.Packages.GetMetadata(ctx, &intelligence.PackageQuery{    Name:      "requests",    Ecosystem: "pypi",})if err != nil {    log.Fatal(err)} fmt.Printf("Name: %s\n", pkg.Name)fmt.Printf("Latest version: %s\n", pkg.LatestVersion)fmt.Printf("Repository: %s\n", pkg.RepositoryURL)fmt.Printf("License: %s\n", pkg.License)

Check if Vulnerability is Fixed

isFixed, err := client.Packages.IsVulnerabilityFixed(ctx, &intelligence.FixStatusQuery{    PackageName: "django",    Ecosystem:   "pypi",    Version:     "4.2.8",    CVEID:       "CVE-2024-1234",})if err != nil {    log.Fatal(err)} if isFixed {    fmt.Println("Vulnerability is fixed in Django 4.2.8")} else {    fmt.Println("Upgrade required")}

Get Version History

versions, err := client.Packages.GetVersions(ctx, &intelligence.PackageQuery{    Name:      "requests",    Ecosystem: "pypi",})if err != nil {    log.Fatal(err)} for _, version := range versions.Results {    if len(version.Vulnerabilities) > 0 {        fmt.Printf("%s: %d vulnerabilities\n", version.Version, len(version.Vulnerabilities))    } else {        fmt.Printf("%s: Clean\n", version.Version)    }}

Find Latest Safe Version

safeVersion, err := client.Packages.GetLatestSafeVersion(ctx, &intelligence.PackageQuery{    Name:      "requests",    Ecosystem: "pypi",})if err != nil {    log.Fatal(err)} if safeVersion != "" {    fmt.Printf("Latest safe version: %s\n", safeVersion)} else {    fmt.Println("No safe version found")}

Dependency Graph Traversal

Get Package Dependencies

deps, err := client.Dependencies.GetDependencies(ctx, &intelligence.DependencyQuery{    PackageName: "django",    Version:     "4.2.0",    Ecosystem:   "pypi",})if err != nil {    log.Fatal(err)} for _, dep := range deps.Results {    fmt.Printf("- %s %s\n", dep.PackageName, dep.VersionSpec)}

Get Transitive Dependencies

allDeps, err := client.Dependencies.GetTransitiveDependencies(ctx, &intelligence.DependencyQuery{    PackageName: "requests",    Version:     "2.31.0",    Ecosystem:   "pypi",})if err != nil {    log.Fatal(err)} for _, dep := range allDeps.Results {    path := strings.Join(dep.Path, " -> ")    fmt.Printf("%s (version: %s)\n", path, dep.Version)}

Find Vulnerabilities in Dependency Tree

vulnsInDeps, err := client.Dependencies.FindVulnerabilitiesInTree(ctx, &intelligence.DependencyQuery{    PackageName: "django",    Version:     "4.2.0",    Ecosystem:   "pypi",})if err != nil {    log.Fatal(err)} for _, vuln := range vulnsInDeps.Results {    path := strings.Join(vuln.Path, " -> ")    fmt.Printf("Vulnerability: %s\n", vuln.CVEID)    fmt.Printf("Path: %s\n", path)    fmt.Printf("Severity: %s\n\n", vuln.Severity)}

Exploit Prediction Scoring (EPSS)

Get EPSS Score

epss, err := client.Vulnerabilities.GetEPSS(ctx, "CVE-2024-1234")if err != nil {    log.Fatal(err)} fmt.Printf("EPSS Score: %.2f\n", epss.Score)     // 0.0 to 1.0fmt.Printf("Percentile: %d\n", epss.Percentile) // 0-100fmt.Printf("Severity: %s\n", epss.Severity) if epss.Score > 0.5 {    fmt.Println("High exploit probability - prioritize patching")}

Batch EPSS Lookup

cveIDs := []string{    "CVE-2024-1234",    "CVE-2024-5678",    "CVE-2024-9999",} epssData, err := client.Vulnerabilities.GetEPSSBatch(ctx, cveIDs)if err != nil {    log.Fatal(err)} for cveID, epss := range epssData {    fmt.Printf("%s: %.2f (percentile: %d)\n", cveID, epss.Score, epss.Percentile)}

Advisory Subscriptions

Get Security Advisories

advisories, err := client.Advisories.GetByPackage(ctx, &intelligence.PackageQuery{    Name:      "django",    Ecosystem: "pypi",})if err != nil {    log.Fatal(err)} for _, advisory := range advisories.Results {    fmt.Printf("Title: %s\n", advisory.Title)    fmt.Printf("Description: %s\n", advisory.Description)    fmt.Printf("Affected versions: %v\n", advisory.AffectedVersions)    fmt.Printf("Fixed version: %s\n", advisory.FixedVersion)    fmt.Printf("Published: %s\n\n", advisory.PublishedDate)}

Register Webhook

webhook, err := client.Webhooks.Register(ctx, &intelligence.WebhookConfig{    URL: "https://your-app.example.com/webhooks/advisories",    Events: []string{        "advisory.created",        "advisory.updated",    },    Packages: []*intelligence.PackageSpec{        {Name: "django", Ecosystem: "pypi"},        {Name: "requests", Ecosystem: "pypi"},    },})if err != nil {    log.Fatal(err)} fmt.Printf("Webhook ID: %s\n", webhook.ID)fmt.Printf("Endpoint: %s\n", webhook.URL)fmt.Printf("Created: %s\n", webhook.CreatedAt)

Verify Webhook Signature

import (    "crypto/hmac"    "crypto/sha256"    "encoding/hex") func verifyWebhookSignature(secret string, payload []byte, signature string) bool {    h := hmac.New(sha256.New, []byte(secret))    h.Write(payload)    expected := hex.EncodeToString(h.Sum(nil))    return hmac.Equal([]byte(signature), []byte(expected))} // In your webhook handlerfunc handleWebhook(w http.ResponseWriter, r *http.Request) {    signature := r.Header.Get("X-Signature")    payload, _ := ioutil.ReadAll(r.Body)     if !verifyWebhookSignature(os.Getenv("WEBHOOK_SECRET"), payload, signature) {        http.Error(w, "Invalid signature", http.StatusUnauthorized)        return    }     var advisory intelligence.Advisory    json.Unmarshal(payload, &advisory)     // Process advisory    w.WriteHeader(http.StatusOK)}

Response Types

Vulnerability Struct

type Vulnerability struct {    CVEID              string    Description        string    Severity           string    CVSSScore          float64    AffectedPackages   []Package    FixAvailable       bool    FixedVersion       string    DisclosureDate     string    PublishedDate      string    LastModifiedDate   string}

Package Struct

type Package struct {    Name              string    Ecosystem         string    LatestVersion     string    RepositoryURL     string    Description       string    License           string    Vulnerabilities   []Vulnerability}

Paginated Response

type PaginatedResults struct {    Results    []T    Pagination struct {        Page    int        Limit   int        Total   int        Pages   int        HasNext bool    }}

Error Handling

Error Types

import "github.com/cleanstart/intelligence-go" switch err := err.(type) {case nil:    // Success case *intelligence.NotFoundError:    log.Printf("Resource not found: %v", err) case *intelligence.RateLimitError:    log.Printf("Rate limited. Retry after: %d seconds", err.RetryAfter) case *intelligence.ValidationError:    log.Printf("Invalid input: %v", err) case *intelligence.AuthenticationError:    log.Printf("Authentication failed: %v", err) default:    log.Printf("API error: %v", err)}

Retry Logic with Exponential Backoff

import "github.com/cenkalti/backoff/v4" func queryWithRetry(ctx context.Context, cveID string) (*intelligence.Vulnerability, error) {    var vuln *intelligence.Vulnerability     err := backoff.Retry(        func() error {            var err error            vuln, err = client.Vulnerabilities.GetByCVEID(ctx, cveID)            return err        },        backoff.WithContext(backoff.NewExponentialBackOff(), ctx),    )     return vuln, err}

Bulk Operations

Batch Query Multiple CVEs

cveIDs := []string{    "CVE-2024-1234",    "CVE-2024-5678",    "CVE-2024-9999",} results, err := client.Vulnerabilities.GetBatch(ctx, cveIDs)if err != nil {    log.Fatal(err)} for cveID, vuln := range results {    if vuln != nil {        fmt.Printf("%s: %s\n", cveID, vuln.Severity)    } else {        fmt.Printf("%s: Not found\n", cveID)    }}

Scan Go Module Dependencies

import (    "golang.org/x/mod/modfile") func scanGoMod(modFilePath string) ([]Vulnerability, error) {    data, _ := os.ReadFile(modFilePath)    modFile, _ := modfile.Parse("go.mod", data, nil)     var vulns []Vulnerability     for _, req := range modFile.Require {        vulnList, err := client.Vulnerabilities.GetByPackage(ctx, &intelligence.PackageQuery{            Name:      req.Mod.Path,            Ecosystem: "go",        })        if err != nil {            continue        }         for _, vuln := range vulnList.Results {            vulns = append(vulns, Vulnerability{                Package:   req.Mod.Path,                Version:   req.Mod.Version,                CVEID:     vuln.CVEID,                Severity:  vuln.Severity,            })        }    }     return vulns, nil} vulns, _ := scanGoMod("go.mod")for _, v := range vulns {    fmt.Printf("%s@%s: %s\n", v.Package, v.Version, v.CVEID)}

Logging and Debugging

Enable Debug Logging

import "github.com/cleanstart/intelligence-go" client := intelligence.NewClient(    intelligence.WithDebug(true),    intelligence.WithLogger(log.New(os.Stderr, "", log.LstdFlags)),)

Custom HTTP Transport

import "net/http" transport := &http.Transport{    MaxIdleConns:       100,    MaxIdleConnsPerHost: 100,    MaxConnsPerHost:    100,} httpClient := &http.Client{    Transport: transport,    Timeout:   30 * time.Second,} client := intelligence.NewClient(    intelligence.WithHTTPClient(httpClient),)

Rate Limiting and Quotas

Default rate limits are 1,000 requests per minute, 10,000 requests per hour, and 100,000 requests per day.

Rate limit headers are available in response metadata:

vuln, err := client.Vulnerabilities.GetByCVEID(ctx, "CVE-2024-1234")if err == nil {    fmt.Printf("Rate limit remaining: %d\n", vuln.RateLimitRemaining)    fmt.Printf("Rate limit reset: %s\n", vuln.RateLimitReset)}

Caching

The SDK includes optional caching:

client := intelligence.NewClient(    intelligence.WithCacheTTL(3600 * time.Second),) // First call hits APIvuln1, _ := client.Vulnerabilities.GetByCVEID(ctx, "CVE-2024-1234") // Second call uses cachevuln2, _ := client.Vulnerabilities.GetByCVEID(ctx, "CVE-2024-1234") // Clear cacheclient.ClearCache() // Disable cache for specific queryvuln3, _ := client.Vulnerabilities.GetByCVEID(    context.WithValue(ctx, "no-cache", true),    "CVE-2024-1234",)

Examples

Vulnerability Severity Report

func generateSeverityReport(ecosystem string) error {    ctx := context.Background()     severities := []string{"CRITICAL", "HIGH", "MEDIUM", "LOW"}    report := make(map[string]int)     for _, severity := range severities {        vulns, err := client.Vulnerabilities.GetByEcosystem(ctx, &intelligence.EcosystemQuery{            Ecosystem: ecosystem,            Severity:  severity,        })        if err != nil {            return err        }         report[severity] = len(vulns.Results)    }     for severity, count := range report {        fmt.Printf("%s: %d\n", severity, count)    }     return nil}

Dependency Security Audit

type AuditResult struct {    Package         string    Version         string    VulnerabilityCount int    CriticalCount   int    HighCount       int    UpdateAvailable bool    LatestVersion   string} func auditDependency(ctx context.Context, pkgName, version string) (*AuditResult, error) {    // Get vulnerabilities for current version    vulns, err := client.Vulnerabilities.GetByPackage(ctx, &intelligence.PackageQuery{        Name:      pkgName,        Ecosystem: "go",    })    if err != nil {        return nil, err    }     // Count by severity    critical := 0    high := 0    for _, v := range vulns.Results {        if v.Severity == "CRITICAL" {            critical++        } else if v.Severity == "HIGH" {            high++        }    }     // Check for updates    pkg, _ := client.Packages.GetMetadata(ctx, &intelligence.PackageQuery{        Name:      pkgName,        Ecosystem: "go",    })     updateAvailable := version != pkg.LatestVersion     return &AuditResult{        Package:             pkgName,        Version:             version,        VulnerabilityCount: len(vulns.Results),        CriticalCount:      critical,        HighCount:          high,        UpdateAvailable:    updateAvailable,        LatestVersion:      pkg.LatestVersion,    }, nil}

Webhook Server

import (    "encoding/json"    "net/http") func handleAdvisoryWebhook(w http.ResponseWriter, r *http.Request) {    // Verify signature    signature := r.Header.Get("X-Signature")    payload, _ := io.ReadAll(r.Body)     if !verifyWebhookSignature(os.Getenv("WEBHOOK_SECRET"), payload, signature) {        http.Error(w, "Invalid signature", http.StatusUnauthorized)        return    }     // Parse webhook payload    var event map[string]interface{}    json.Unmarshal(payload, &event)     // Log advisory    log.Printf("Advisory event: %s\n", event["event"])    log.Printf("CVE: %s\n", event["advisory"].(map[string]interface{})["cve_id"])     w.WriteHeader(http.StatusOK)    json.NewEncoder(w).Encode(map[string]string{"status": "received"})} func main() {    http.HandleFunc("/webhooks/advisories", handleAdvisoryWebhook)    http.ListenAndServe(":8080", nil)}

Next Steps

API Reference: See Source Intelligence Core API docs for complete endpoint documentation (internal use). Authentication: Learn about API key management. Examples: Explore integration samples for common Go patterns. GitHub: View source code on GitHub.