VYPR
High severityNVD Advisory· Published Sep 15, 2022· Updated Apr 22, 2025

Out-of-bounds Read in go-cvss

CVE-2022-39213

Description

go-cvss Go module has an out-of-bounds read vulnerability when parsing a full CVSS v2.0 vector, causing a panic; fixed in v0.4.0.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

go-cvss Go module has an out-of-bounds read vulnerability when parsing a full CVSS v2.0 vector, causing a panic; fixed in v0.4.0.

Vulnerability

Description

The go-cvss Go module, designed for parsing and manipulating CVSS vectors, contains an out-of-bounds read vulnerability in its ParseVector function when processing a complete CVSS v2.0 vector string. The issue arises from insufficient input validation, specifically when the vector includes all defined attributes (e.g., base, temporal, environmental, and supplemental metrics). This flaw can cause the Go runtime to panic, leading to a denial of service [1][2].

Exploitation

Conditions

An attacker can exploit this vulnerability by providing a crafted full CVSS v2.0 vector string to any application that uses the go-cvss library to parse user-supplied vectors. No authentication or special network position is required if the application exposes this functionality. The out-of-bounds read occurs during parsing, immediately triggering a panic and crashing the application [2][4].

Impact

The primary impact is denial of service through application termination. The advisory does not indicate that memory corruption leads to code execution or information disclosure. The vulnerability is specific to CVSS v2.0 parsing; other supported CVSS versions (3.0, 3.1, 4.0) are not affected [1].

Mitigation

The issue is patched in go-cvss version v0.4.0, with the fix committed in d9d478ff0c13b8b09ace030db9262f3c2fe031f4 [3]. Users are strongly advised to upgrade. For those unable to upgrade, a workaround is to only parse CVSS v2.0 vectors that do not contain all attributes (e.g., omit environmental or temporal metrics) [2]. The vulnerability is also tracked as GO-2022-1002 in the Go vulnerability database [4].

AI Insight generated on May 21, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/pandatix/go-cvssGo
>= 0.2.0, < 0.4.00.4.0

Affected products

2

Patches

1
d9d478ff0c13

Improve CVSS v2.0 implementation (0/1 allocs/op)

https://github.com/pandatix/go-cvssTESSON LucasSep 13, 2022via ghsa
6 files changed · +468 248
  • 20/cvss20_bench_test.go+100 0 added
    @@ -0,0 +1,100 @@
    +package gocvss20_test
    +
    +import (
    +	"testing"
    +
    +	gocvss20 "github.com/pandatix/go-cvss/20"
    +)
    +
    +var Gcvss20 *gocvss20.CVSS20
    +var Gerr error
    +
    +func BenchmarkParseVector_Base(b *testing.B) {
    +	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C", b)
    +}
    +
    +func BenchmarkParseVector_WithTempAndEnv(b *testing.B) {
    +	benchmarkParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M", b)
    +}
    +
    +func benchmarkParseVector(vector string, b *testing.B) {
    +	var cvss20 *gocvss20.CVSS20
    +	var err error
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		cvss20, err = gocvss20.ParseVector(vector)
    +	}
    +	Gcvss20 = cvss20
    +	Gerr = err
    +}
    +
    +var Gstr string
    +
    +func BenchmarkCVSS20Vector(b *testing.B) {
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	var str string
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		str = cvss20.Vector()
    +	}
    +	Gstr = str
    +}
    +
    +var Gget string
    +
    +func BenchmarkCVSS20Get(b *testing.B) {
    +	const abv = "Au"
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	var get string
    +	var err error
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		get, err = cvss20.Get(abv)
    +	}
    +	Gget = get
    +	Gerr = err
    +}
    +
    +func BenchmarkCVSS20Set(b *testing.B) {
    +	const abv = "Au"
    +	const value = "S"
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	var err error
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		err = cvss20.Set(abv, value)
    +	}
    +	Gerr = err
    +}
    +
    +var Gscore float64
    +
    +func BenchmarkCVSS20BaseScore(b *testing.B) {
    +	var score float64
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		score = cvss20.BaseScore()
    +	}
    +	Gscore = score
    +}
    +
    +func BenchmarkCVSS20TemporalScore(b *testing.B) {
    +	var score float64
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		score = cvss20.TemporalScore()
    +	}
    +	Gscore = score
    +}
    +
    +func BenchmarkCVSS20EnvironmentalScore(b *testing.B) {
    +	var score float64
    +	cvss20, _ := gocvss20.ParseVector("AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M")
    +	b.ResetTimer()
    +	for i := 0; i < b.N; i++ {
    +		score = cvss20.EnvironmentalScore()
    +	}
    +	Gscore = score
    +}
    
  • 20/cvss20_fuzz_test.go+2 4 modified
    @@ -1,9 +1,7 @@
    -package gocvss20_test
    +package gocvss20
     
     import (
     	"testing"
    -
    -	gocvss20 "github.com/pandatix/go-cvss/20"
     )
     
     func FuzzParseVector(f *testing.F) {
    @@ -12,7 +10,7 @@ func FuzzParseVector(f *testing.F) {
     	}
     
     	f.Fuzz(func(t *testing.T, vector string) {
    -		cvss20, err := gocvss20.ParseVector(vector)
    +		cvss20, err := ParseVector(vector)
     
     		if err != nil {
     			if cvss20 != nil {
    
  • 20/cvss20.go+187 101 modified
    @@ -3,172 +3,250 @@ package gocvss20
     import (
     	"math"
     	"strings"
    +	"sync"
    +	"unsafe"
     )
     
    +var order = [][]string{
    +	{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
    +	{"E", "RL", "RC"},                 // Temporal metrics
    +	{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
    +}
    +
     // ParseVector parses a CVSS v2.0 vector.
     func ParseVector(vector string) (*CVSS20, error) {
     	// Split parts
    -	pts := strings.Split(vector, "/")
    -	if len(pts) != 6 && len(pts) != 9 && len(pts) != 14 {
    +	pts, l := split(vector)
    +	if l != 6 && l != 9 && l != 14 {
     		return nil, ErrTooShortVector
     	}
    +	pts = pts[:l]
     
     	// Work on each CVSS part
     	cvss20 := &CVSS20{
    -		Base: Base{},
    -		Temporal: Temporal{
    -			Exploitability:   "ND",
    -			RemediationLevel: "ND",
    -			ReportConfidence: "ND",
    +		base: base{},
    +		temporal: temporal{
    +			exploitability:   "ND",
    +			remediationLevel: "ND",
    +			reportConfidence: "ND",
     		},
    -		Environmental: Environmental{
    -			CollateralDamagePotential:  "ND",
    -			TargetDistribution:         "ND",
    -			ConfidentialityRequirement: "ND",
    -			IntegrityRequirement:       "ND",
    -			AvailabilityRequirement:    "ND",
    +		environmental: environmental{
    +			collateralDamagePotential:  "ND",
    +			targetDistribution:         "ND",
    +			confidentialityRequirement: "ND",
    +			integrityRequirement:       "ND",
    +			availabilityRequirement:    "ND",
     		},
     	}
     
    -	// Parse metrics in order
    -	slcs := [][]string{
    -		{"AV", "AC", "Au", "C", "I", "A"}, // Base metrics
    -		{"E", "RL", "RC"},                 // Temporal metrics
    -		{"CDP", "TD", "CR", "IR", "AR"},   // Environmental metrics
    -	}
     	slci := 0
    -	currSlc := slcs[slci]
     	i := 0
     	for _, pt := range pts {
     		abv, v, _ := strings.Cut(pt, ":")
    -		if abv != currSlc[i] {
    +		if slci == 4 {
    +			return nil, &ErrDefinedN{Abv: abv}
    +		}
    +		if abv != order[slci][i] {
     			return nil, ErrInvalidMetricOrder
     		}
    +
     		if err := cvss20.Set(abv, v); err != nil {
     			return nil, err
     		}
    +
     		// Go to next element in slice, or next slice if fully consumed
     		i++
    -		if i == len(currSlc) {
    +		if i == len(order[slci]) {
     			slci++
    -			currSlc = slcs[slci]
     			i = 0
     		}
     	}
     
     	return cvss20, nil
     }
     
    +var splitPool = sync.Pool{
    +	New: func() any {
    +		return make([]string, 14)
    +	},
    +}
    +
    +func split(vector string) ([]string, int) {
    +	partsPtr := splitPool.Get()
    +	defer splitPool.Put(partsPtr)
    +	parts := partsPtr.([]string)
    +
    +	start := 0
    +	curr := 0
    +	l := len(vector)
    +	i := 0
    +	for ; i < l; i++ {
    +		if vector[i] == '/' {
    +			parts[curr] = vector[start:i]
    +
    +			start = i + 1
    +			curr++
    +
    +			if curr == 13 {
    +				break
    +			}
    +		}
    +	}
    +	parts[curr] = vector[start:]
    +	return parts, curr + 1
    +}
    +
     func (cvss20 CVSS20) Vector() string {
    -	s := ""
    +	l := lenVec(&cvss20)
    +	b := make([]byte, 0, l)
    +
     	// Base
    -	s += "AV:" + cvss20.AccessVector
    -	s += "/AC:" + cvss20.AccessComplexity
    -	s += "/Au:" + cvss20.Authentication
    -	s += "/C:" + cvss20.ConfidentialityImpact
    -	s += "/I:" + cvss20.IntegrityImpact
    -	s += "/A:" + cvss20.AvailabilityImpact
    -	// Temporal, if any is defined
    -	if cvss20.Exploitability != "ND" || cvss20.RemediationLevel != "ND" || cvss20.ReportConfidence != "ND" {
    -		s += "/E:" + cvss20.Exploitability
    -		s += "/RL:" + cvss20.RemediationLevel
    -		s += "/RC:" + cvss20.ReportConfidence
    +	app(&b, "AV:", cvss20.accessVector)
    +	app(&b, "/AC:", cvss20.accessComplexity)
    +	app(&b, "/Au:", cvss20.authentication)
    +	app(&b, "/C:", cvss20.confidentialityImpact)
    +	app(&b, "/I:", cvss20.integrityImpact)
    +	app(&b, "/A:", cvss20.availabilityImpact)
    +
    +	// Temporal
    +	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
    +		app(&b, "/E:", cvss20.exploitability)
    +		app(&b, "/RL:", cvss20.remediationLevel)
    +		app(&b, "/RC:", cvss20.reportConfidence)
     	}
    -	// Environmental, if any is defined
    -	if cvss20.CollateralDamagePotential != "ND" || cvss20.TargetDistribution != "ND" || cvss20.ConfidentialityRequirement != "ND" || cvss20.IntegrityRequirement != "ND" || cvss20.AvailabilityRequirement != "ND" {
    -		s += "/CDP:" + cvss20.CollateralDamagePotential
    -		s += "/TD:" + cvss20.TargetDistribution
    -		s += "/CR:" + cvss20.ConfidentialityRequirement
    -		s += "/IR:" + cvss20.IntegrityRequirement
    -		s += "/AR:" + cvss20.AvailabilityRequirement
    +
    +	// Environmental
    +	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
    +		app(&b, "/CDP:", cvss20.collateralDamagePotential)
    +		app(&b, "/TD:", cvss20.targetDistribution)
    +		app(&b, "/CR:", cvss20.confidentialityRequirement)
    +		app(&b, "/IR:", cvss20.integrityRequirement)
    +		app(&b, "/AR:", cvss20.availabilityRequirement)
     	}
    -	return s
    +
    +	return *(*string)(unsafe.Pointer(&b))
    +}
    +
    +func lenVec(cvss20 *CVSS20) int {
    +	// Base:
    +	// - AV, AC, Au: 4
    +	// - C, I, A: 3
    +	// - separators: 5
    +	// Total: 3*4 + 3*3 + 5 = 30
    +	l := 26
    +
    +	// Temporal:
    +	// - E: 2 + len(v)
    +	// - RL: 3 + len(v)
    +	// - RC: 3 + len(v)
    +	// - separators: 3
    +	// Total: 11 + 3*len(v)
    +	if cvss20.exploitability != "ND" || cvss20.remediationLevel != "ND" || cvss20.reportConfidence != "ND" {
    +		l += 11 + len(cvss20.exploitability) + len(cvss20.remediationLevel) + len(cvss20.reportConfidence)
    +	}
    +
    +	// Environmental:
    +	// - CDP: 4 + len(v)
    +	// - TD: 3 + len(v)
    +	// - CR, IR, AR: 3 + len(v)
    +	// - separators: 5
    +	// Total: 21 + 5*len(v)
    +	if cvss20.collateralDamagePotential != "ND" || cvss20.targetDistribution != "ND" || cvss20.confidentialityRequirement != "ND" || cvss20.integrityRequirement != "ND" || cvss20.availabilityRequirement != "ND" {
    +		l += 21 + len(cvss20.collateralDamagePotential) + len(cvss20.targetDistribution) + len(cvss20.confidentialityRequirement) + len(cvss20.integrityRequirement) + len(cvss20.availabilityRequirement)
    +	}
    +
    +	return l
    +}
    +
    +func app(b *[]byte, pre, v string) {
    +	*b = append(*b, pre...)
    +	*b = append(*b, v...)
     }
     
     // CVSS20 embeds all the metric values defined by the CVSS v2.0
     // rev2 specification.
     // Attributes values must not be manipulated directly. Use Get
     // and Set methods.
     type CVSS20 struct {
    -	Base
    -	Temporal
    -	Environmental
    +	base
    +	temporal
    +	environmental
     }
     
    -// Base is the group of metrics defined with such name by the
    +// base is the group of metrics defined with such name by the
     // first.org CVSS v2.0 rev2 specification.
     // Mandatory.
    -type Base struct {
    +type base struct {
     	// AV -> [L,A,N]
    -	AccessVector string
    +	accessVector string
     	// AC -> [H,M,L]
    -	AccessComplexity string
    +	accessComplexity string
     	// Au -> [M,S,N]
    -	Authentication string
    +	authentication string
     	// C -> [N,P,C]
    -	ConfidentialityImpact string
    +	confidentialityImpact string
     	// I -> [N,P,C]
    -	IntegrityImpact string
    +	integrityImpact string
     	// A -> [N,P,C]
    -	AvailabilityImpact string
    +	availabilityImpact string
     }
     
    -// Temporal is the group of metrics defined with such name by the
    +// temporal is the group of metrics defined with such name by the
     // first.org CVSS v2.0 rev2 specification.
     // Not mandatory.
    -type Temporal struct {
    +type temporal struct {
     	// E -> [U,POC,F,F,H,ND]
    -	Exploitability string
    +	exploitability string
     	// RL -> [OF,TF,W,U,ND]
    -	RemediationLevel string
    +	remediationLevel string
     	// RC -> [UC,UR,C,ND]
    -	ReportConfidence string
    +	reportConfidence string
     }
     
    -// Environmental is the group of metrics defined with such name by the
    +// environmental is the group of metrics defined with such name by the
     // first.org CVSS v2.0 rev2 specification.
     // Not mandatory.
    -type Environmental struct {
    +type environmental struct {
     	// CDP -> [N,L,LM,MH,H,ND]
    -	CollateralDamagePotential string
    +	collateralDamagePotential string
     	// TD -> [N,L,M,H,ND]
    -	TargetDistribution string
    +	targetDistribution string
     	// CR,IR,AR -> [L,M,H,ND]
    -	ConfidentialityRequirement string
    -	IntegrityRequirement       string
    -	AvailabilityRequirement    string
    +	confidentialityRequirement string
    +	integrityRequirement       string
    +	availabilityRequirement    string
     }
     
     func (cvss20 CVSS20) Get(abv string) (string, error) {
     	switch abv {
     	case "AV":
    -		return cvss20.AccessVector, nil
    +		return cvss20.accessVector, nil
     	case "AC":
    -		return cvss20.AccessComplexity, nil
    +		return cvss20.accessComplexity, nil
     	case "Au":
    -		return cvss20.Authentication, nil
    +		return cvss20.authentication, nil
     	case "C":
    -		return cvss20.ConfidentialityImpact, nil
    +		return cvss20.confidentialityImpact, nil
     	case "I":
    -		return cvss20.IntegrityImpact, nil
    +		return cvss20.integrityImpact, nil
     	case "A":
    -		return cvss20.AvailabilityImpact, nil
    +		return cvss20.availabilityImpact, nil
     	case "E":
    -		return cvss20.Exploitability, nil
    +		return cvss20.exploitability, nil
     	case "RL":
    -		return cvss20.RemediationLevel, nil
    +		return cvss20.remediationLevel, nil
     	case "RC":
    -		return cvss20.ReportConfidence, nil
    +		return cvss20.reportConfidence, nil
     	case "CDP":
    -		return cvss20.CollateralDamagePotential, nil
    +		return cvss20.collateralDamagePotential, nil
     	case "TD":
    -		return cvss20.TargetDistribution, nil
    +		return cvss20.targetDistribution, nil
     	case "CR":
    -		return cvss20.ConfidentialityRequirement, nil
    +		return cvss20.confidentialityRequirement, nil
     	case "IR":
    -		return cvss20.IntegrityRequirement, nil
    +		return cvss20.integrityRequirement, nil
     	case "AR":
    -		return cvss20.AvailabilityRequirement, nil
    +		return cvss20.availabilityRequirement, nil
     	default:
     		return "", &ErrInvalidMetric{Abv: abv}
     	}
    @@ -181,74 +259,74 @@ func (cvss20 *CVSS20) Set(abv string, value string) error {
     		if err := validate(value, []string{"L", "A", "N"}); err != nil {
     			return err
     		}
    -		cvss20.AccessVector = value
    +		cvss20.accessVector = value
     	case "AC":
     		if err := validate(value, []string{"H", "M", "L"}); err != nil {
     			return err
     		}
    -		cvss20.AccessComplexity = value
    +		cvss20.accessComplexity = value
     	case "Au":
     		if err := validate(value, []string{"M", "S", "N"}); err != nil {
     			return err
     		}
    -		cvss20.Authentication = value
    +		cvss20.authentication = value
     	case "C":
     		if err := validate(value, []string{"N", "P", "C"}); err != nil {
     			return err
     		}
    -		cvss20.ConfidentialityImpact = value
    +		cvss20.confidentialityImpact = value
     	case "I":
     		if err := validate(value, []string{"N", "P", "C"}); err != nil {
     			return err
     		}
    -		cvss20.IntegrityImpact = value
    +		cvss20.integrityImpact = value
     	case "A":
     		if err := validate(value, []string{"N", "P", "C"}); err != nil {
     			return err
     		}
    -		cvss20.AvailabilityImpact = value
    +		cvss20.availabilityImpact = value
     	// Temporal
     	case "E":
     		if err := validate(value, []string{"U", "POC", "F", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.Exploitability = value
    +		cvss20.exploitability = value
     	case "RL":
     		if err := validate(value, []string{"OF", "TF", "W", "U", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.RemediationLevel = value
    +		cvss20.remediationLevel = value
     	case "RC":
     		if err := validate(value, []string{"UC", "UR", "C", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.ReportConfidence = value
    +		cvss20.reportConfidence = value
     	// Environmental
     	case "CDP":
     		if err := validate(value, []string{"N", "L", "LM", "MH", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.CollateralDamagePotential = value
    +		cvss20.collateralDamagePotential = value
     	case "TD":
     		if err := validate(value, []string{"N", "L", "M", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.TargetDistribution = value
    +		cvss20.targetDistribution = value
     	case "CR":
     		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.ConfidentialityRequirement = value
    +		cvss20.confidentialityRequirement = value
     	case "IR":
     		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.IntegrityRequirement = value
    +		cvss20.integrityRequirement = value
     	case "AR":
     		if err := validate(value, []string{"L", "M", "H", "ND"}); err != nil {
     			return err
     		}
    -		cvss20.AvailabilityRequirement = value
    +		cvss20.availabilityRequirement = value
     	default:
     		return &ErrInvalidMetric{Abv: abv}
     	}
    @@ -267,32 +345,40 @@ func validate(value string, enabled []string) error {
     
     // BaseScore returns the CVSS v2.0's base score.
     func (cvss20 CVSS20) BaseScore() float64 {
    -	impact := 10.41 * (1 - (1-cia(cvss20.ConfidentialityImpact))*(1-cia(cvss20.IntegrityImpact))*(1-cia(cvss20.AvailabilityImpact)))
    +	impact := cvss20.Impact()
     	fimpact := 0.0
     	if impact != 0 {
     		fimpact = 1.176
     	}
    -	exploitability := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
    +	exploitability := cvss20.Exploitability()
     	return roundTo1Decimal(((0.6 * impact) + (0.4 * exploitability) - 1.5) * fimpact)
     }
     
    +func (cvss20 CVSS20) Impact() float64 {
    +	return 10.41 * (1 - (1-cia(cvss20.confidentialityImpact))*(1-cia(cvss20.integrityImpact))*(1-cia(cvss20.availabilityImpact)))
    +}
    +
    +func (cvss20 CVSS20) Exploitability() float64 {
    +	return 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
    +}
    +
     // TemporalScore returns the CVSS v2.0's temporal score.
     func (cvss20 CVSS20) TemporalScore() float64 {
    -	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
    +	return roundTo1Decimal(cvss20.BaseScore() * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
     }
     
     // EnvironmentalScore returns the CVSS v2.0's environmental score.
     func (cvss20 CVSS20) EnvironmentalScore() float64 {
     	// Recompute base score
    -	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.ConfidentialityImpact)*ciar(cvss20.ConfidentialityRequirement))*(1-cia(cvss20.IntegrityImpact)*ciar(cvss20.IntegrityRequirement))*(1-cia(cvss20.AvailabilityImpact)*ciar(cvss20.AvailabilityRequirement))))
    +	adjustedImpact := math.Min(10, 10.41*(1-(1-cia(cvss20.confidentialityImpact)*ciar(cvss20.confidentialityRequirement))*(1-cia(cvss20.integrityImpact)*ciar(cvss20.integrityRequirement))*(1-cia(cvss20.availabilityImpact)*ciar(cvss20.availabilityRequirement))))
     	fimpactBase := 0.0
     	if adjustedImpact != 0 {
     		fimpactBase = 1.176
     	}
    -	expltBase := 20 * accessVector(cvss20.AccessVector) * accessComplexity(cvss20.AccessComplexity) * authentication(cvss20.Authentication)
    +	expltBase := 20 * accessVector(cvss20.accessVector) * accessComplexity(cvss20.accessComplexity) * authentication(cvss20.authentication)
     	recBase := roundTo1Decimal(((0.6 * adjustedImpact) + (0.4 * expltBase) - 1.5) * fimpactBase)
    -	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.Exploitability) * remediationLevel(cvss20.RemediationLevel) * reportConfidence(cvss20.ReportConfidence))
    -	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.CollateralDamagePotential)) * targetDistribution(cvss20.TargetDistribution))
    +	adjustedTemporal := roundTo1Decimal(recBase * exploitability(cvss20.exploitability) * remediationLevel(cvss20.remediationLevel) * reportConfidence(cvss20.reportConfidence))
    +	return roundTo1Decimal((adjustedTemporal + (10-adjustedTemporal)*collateralDamagePotential(cvss20.collateralDamagePotential)) * targetDistribution(cvss20.targetDistribution))
     }
     
     // Helpers to compute CVSS v2.0 scores.
    
  • 20/cvss20_test.go+146 113 modified
    @@ -1,95 +1,128 @@
    -package gocvss20_test
    +package gocvss20
     
     import (
     	"testing"
     
    -	gocvss20 "github.com/pandatix/go-cvss/20"
     	"github.com/stretchr/testify/assert"
     )
     
     var testsParseVector = map[string]struct {
     	Vector         string
    -	ExpectedCVSS20 *gocvss20.CVSS20
    +	ExpectedCVSS20 *CVSS20
     	ExpectedErr    error
     }{
     	"CVSS v2.0 Guide Section 3.3.1 CVE-2002-0392": {
     		Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:C/E:F/RL:OF/RC:C",
    -		ExpectedCVSS20: &gocvss20.CVSS20{
    -			Base: gocvss20.Base{
    -				AccessVector:          "N",
    -				AccessComplexity:      "L",
    -				Authentication:        "N",
    -				ConfidentialityImpact: "N",
    -				IntegrityImpact:       "N",
    -				AvailabilityImpact:    "C",
    +		ExpectedCVSS20: &CVSS20{
    +			base: base{
    +				accessVector:          "N",
    +				accessComplexity:      "L",
    +				authentication:        "N",
    +				confidentialityImpact: "N",
    +				integrityImpact:       "N",
    +				availabilityImpact:    "C",
     			},
    -			Temporal: gocvss20.Temporal{
    -				Exploitability:   "F",
    -				RemediationLevel: "OF",
    -				ReportConfidence: "C",
    +			temporal: temporal{
    +				exploitability:   "F",
    +				remediationLevel: "OF",
    +				reportConfidence: "C",
     			},
    -			Environmental: gocvss20.Environmental{
    -				CollateralDamagePotential:  "ND",
    -				TargetDistribution:         "ND",
    -				ConfidentialityRequirement: "ND",
    -				IntegrityRequirement:       "ND",
    -				AvailabilityRequirement:    "ND",
    +			environmental: environmental{
    +				collateralDamagePotential:  "ND",
    +				targetDistribution:         "ND",
    +				confidentialityRequirement: "ND",
    +				integrityRequirement:       "ND",
    +				availabilityRequirement:    "ND",
     			},
     		},
     		ExpectedErr: nil,
     	},
     	"CVSS v2.0 Guide Section 3.3.2 CVE-2003-0818": {
     		Vector: "AV:N/AC:L/Au:N/C:C/I:C/A:C/E:F/RL:OF/RC:C",
    -		ExpectedCVSS20: &gocvss20.CVSS20{
    -			Base: gocvss20.Base{
    -				AccessVector:          "N",
    -				AccessComplexity:      "L",
    -				Authentication:        "N",
    -				ConfidentialityImpact: "C",
    -				IntegrityImpact:       "C",
    -				AvailabilityImpact:    "C",
    +		ExpectedCVSS20: &CVSS20{
    +			base: base{
    +				accessVector:          "N",
    +				accessComplexity:      "L",
    +				authentication:        "N",
    +				confidentialityImpact: "C",
    +				integrityImpact:       "C",
    +				availabilityImpact:    "C",
     			},
    -			Temporal: gocvss20.Temporal{
    -				Exploitability:   "F",
    -				RemediationLevel: "OF",
    -				ReportConfidence: "C",
    +			temporal: temporal{
    +				exploitability:   "F",
    +				remediationLevel: "OF",
    +				reportConfidence: "C",
     			},
    -			Environmental: gocvss20.Environmental{
    -				CollateralDamagePotential:  "ND",
    -				TargetDistribution:         "ND",
    -				ConfidentialityRequirement: "ND",
    -				IntegrityRequirement:       "ND",
    -				AvailabilityRequirement:    "ND",
    +			environmental: environmental{
    +				collateralDamagePotential:  "ND",
    +				targetDistribution:         "ND",
    +				confidentialityRequirement: "ND",
    +				integrityRequirement:       "ND",
    +				availabilityRequirement:    "ND",
     			},
     		},
     		ExpectedErr: nil,
     	},
     	"CVSS v2.0 Guide Section 3.3.3 CVE-2003-0062": {
     		Vector: "AV:L/AC:H/Au:N/C:C/I:C/A:C/E:POC/RL:OF/RC:C",
    -		ExpectedCVSS20: &gocvss20.CVSS20{
    -			Base: gocvss20.Base{
    -				AccessVector:          "L",
    -				AccessComplexity:      "H",
    -				Authentication:        "N",
    -				ConfidentialityImpact: "C",
    -				IntegrityImpact:       "C",
    -				AvailabilityImpact:    "C",
    +		ExpectedCVSS20: &CVSS20{
    +			base: base{
    +				accessVector:          "L",
    +				accessComplexity:      "H",
    +				authentication:        "N",
    +				confidentialityImpact: "C",
    +				integrityImpact:       "C",
    +				availabilityImpact:    "C",
     			},
    -			Temporal: gocvss20.Temporal{
    -				Exploitability:   "POC",
    -				RemediationLevel: "OF",
    -				ReportConfidence: "C",
    +			temporal: temporal{
    +				exploitability:   "POC",
    +				remediationLevel: "OF",
    +				reportConfidence: "C",
     			},
    -			Environmental: gocvss20.Environmental{
    -				CollateralDamagePotential:  "ND",
    -				TargetDistribution:         "ND",
    -				ConfidentialityRequirement: "ND",
    -				IntegrityRequirement:       "ND",
    -				AvailabilityRequirement:    "ND",
    +			environmental: environmental{
    +				collateralDamagePotential:  "ND",
    +				targetDistribution:         "ND",
    +				confidentialityRequirement: "ND",
    +				integrityRequirement:       "ND",
    +				availabilityRequirement:    "ND",
     			},
     		},
     		ExpectedErr: nil,
     	},
    +	"all-defined": {
    +		Vector: "AV:N/AC:L/Au:N/C:P/I:P/A:C/E:U/RL:OF/RC:C/CDP:MH/TD:H/CR:M/IR:M/AR:M",
    +		ExpectedCVSS20: &CVSS20{
    +			base: base{
    +				accessVector:          "N",
    +				accessComplexity:      "L",
    +				authentication:        "N",
    +				confidentialityImpact: "P",
    +				integrityImpact:       "P",
    +				availabilityImpact:    "C",
    +			},
    +			temporal: temporal{
    +				exploitability:   "U",
    +				remediationLevel: "OF",
    +				reportConfidence: "C",
    +			},
    +			environmental: environmental{
    +				collateralDamagePotential:  "MH",
    +				targetDistribution:         "H",
    +				confidentialityRequirement: "M",
    +				integrityRequirement:       "M",
    +				availabilityRequirement:    "M",
    +			},
    +		},
    +		ExpectedErr: nil,
    +	},
    +	"Fuzz_50620a37c4a7716a77a14602b4bcc7b02e6f751d0a714ed796d9b04402c745ac": {
    +		// This fuzz crasher enabled detecting that the split function
    +		// (comming from the optimization step) was doing an Out-Of-Bounds
    +		// Write (CWE-787) if the vector was only composed of '/'.
    +		Vector:         "//////////////",
    +		ExpectedCVSS20: nil,
    +		ExpectedErr:    ErrInvalidMetricOrder,
    +	},
     }
     
     func TestParseVector(t *testing.T) {
    @@ -99,7 +132,7 @@ func TestParseVector(t *testing.T) {
     		t.Run(testname, func(t *testing.T) {
     			assert := assert.New(t)
     
    -			cvss20, err := gocvss20.ParseVector(tt.Vector)
    +			cvss20, err := ParseVector(tt.Vector)
     
     			assert.Equal(tt.ExpectedCVSS20, cvss20)
     			assert.Equal(tt.ExpectedErr, err)
    @@ -111,86 +144,86 @@ func TestScores(t *testing.T) {
     	t.Parallel()
     
     	var tests = map[string]struct {
    -		CVSS20                     *gocvss20.CVSS20
    +		CVSS20                     *CVSS20
     		ExpectedBaseScore          float64
     		ExpectedTemporalScore      float64
     		ExpectedEnvironmentalScore float64
     	}{
     		"CVSS v2.0 Guide Section 3.3.1 CVE-2002-0392": {
    -			CVSS20: &gocvss20.CVSS20{
    -				Base: gocvss20.Base{
    -					AccessVector:          "N",
    -					AccessComplexity:      "L",
    -					Authentication:        "N",
    -					ConfidentialityImpact: "N",
    -					IntegrityImpact:       "N",
    -					AvailabilityImpact:    "C",
    +			CVSS20: &CVSS20{
    +				base: base{
    +					accessVector:          "N",
    +					accessComplexity:      "L",
    +					authentication:        "N",
    +					confidentialityImpact: "N",
    +					integrityImpact:       "N",
    +					availabilityImpact:    "C",
     				},
    -				Temporal: gocvss20.Temporal{
    -					Exploitability:   "F",
    -					RemediationLevel: "OF",
    -					ReportConfidence: "C",
    +				temporal: temporal{
    +					exploitability:   "F",
    +					remediationLevel: "OF",
    +					reportConfidence: "C",
     				},
    -				Environmental: gocvss20.Environmental{
    -					CollateralDamagePotential:  "ND",
    -					TargetDistribution:         "ND",
    -					ConfidentialityRequirement: "ND",
    -					IntegrityRequirement:       "ND",
    -					AvailabilityRequirement:    "ND",
    +				environmental: environmental{
    +					collateralDamagePotential:  "ND",
    +					targetDistribution:         "ND",
    +					confidentialityRequirement: "ND",
    +					integrityRequirement:       "ND",
    +					availabilityRequirement:    "ND",
     				},
     			},
     			ExpectedBaseScore:          7.8,
     			ExpectedTemporalScore:      6.4,
     			ExpectedEnvironmentalScore: 6.4,
     		},
     		"CVSS v2.0 Guide Section 3.3.2 CVE-2003-0818": {
    -			CVSS20: &gocvss20.CVSS20{
    -				Base: gocvss20.Base{
    -					AccessVector:          "N",
    -					AccessComplexity:      "L",
    -					Authentication:        "N",
    -					ConfidentialityImpact: "C",
    -					IntegrityImpact:       "C",
    -					AvailabilityImpact:    "C",
    +			CVSS20: &CVSS20{
    +				base: base{
    +					accessVector:          "N",
    +					accessComplexity:      "L",
    +					authentication:        "N",
    +					confidentialityImpact: "C",
    +					integrityImpact:       "C",
    +					availabilityImpact:    "C",
     				},
    -				Temporal: gocvss20.Temporal{
    -					Exploitability:   "F",
    -					RemediationLevel: "OF",
    -					ReportConfidence: "C",
    +				temporal: temporal{
    +					exploitability:   "F",
    +					remediationLevel: "OF",
    +					reportConfidence: "C",
     				},
    -				Environmental: gocvss20.Environmental{
    -					CollateralDamagePotential:  "ND",
    -					TargetDistribution:         "ND",
    -					ConfidentialityRequirement: "ND",
    -					IntegrityRequirement:       "ND",
    -					AvailabilityRequirement:    "ND",
    +				environmental: environmental{
    +					collateralDamagePotential:  "ND",
    +					targetDistribution:         "ND",
    +					confidentialityRequirement: "ND",
    +					integrityRequirement:       "ND",
    +					availabilityRequirement:    "ND",
     				},
     			},
     			ExpectedBaseScore:          10.0,
     			ExpectedTemporalScore:      8.3,
     			ExpectedEnvironmentalScore: 8.3,
     		},
     		"CVSS v2.0 Guide Section 3.3.3 CVE-2003-0062": {
    -			CVSS20: &gocvss20.CVSS20{
    -				Base: gocvss20.Base{
    -					AccessVector:          "L",
    -					AccessComplexity:      "H",
    -					Authentication:        "N",
    -					ConfidentialityImpact: "C",
    -					IntegrityImpact:       "C",
    -					AvailabilityImpact:    "C",
    +			CVSS20: &CVSS20{
    +				base: base{
    +					accessVector:          "L",
    +					accessComplexity:      "H",
    +					authentication:        "N",
    +					confidentialityImpact: "C",
    +					integrityImpact:       "C",
    +					availabilityImpact:    "C",
     				},
    -				Temporal: gocvss20.Temporal{
    -					Exploitability:   "POC",
    -					RemediationLevel: "OF",
    -					ReportConfidence: "C",
    +				temporal: temporal{
    +					exploitability:   "POC",
    +					remediationLevel: "OF",
    +					reportConfidence: "C",
     				},
    -				Environmental: gocvss20.Environmental{
    -					CollateralDamagePotential:  "ND",
    -					TargetDistribution:         "ND",
    -					ConfidentialityRequirement: "ND",
    -					IntegrityRequirement:       "ND",
    -					AvailabilityRequirement:    "ND",
    +				environmental: environmental{
    +					collateralDamagePotential:  "ND",
    +					targetDistribution:         "ND",
    +					confidentialityRequirement: "ND",
    +					integrityRequirement:       "ND",
    +					availabilityRequirement:    "ND",
     				},
     			},
     			ExpectedBaseScore:          6.2,
    
  • 20/errors.go+2 14 modified
    @@ -11,26 +11,14 @@ var (
     	ErrInvalidMetricValue = errors.New("invalid metric value")
     )
     
    -// ErrBaseScore is an error returned by ParseVector when the
    -// given vector have missing base score attributes.
    -type ErrBaseScore struct {
    -	Missings []string
    -}
    -
    -func (err ErrBaseScore) Error() string {
    -	return fmt.Sprintf("base score is missing metrics %v", err.Missings)
    -}
    -
    -var _ error = (*ErrBaseScore)(nil)
    -
     // ErrDefinedN is an error return by ParseVector when the
     // given vector has metrics abbreviations defined multiple times.
     type ErrDefinedN struct {
    -	Abv []string
    +	Abv string
     }
     
     func (err ErrDefinedN) Error() string {
    -	return fmt.Sprintf("given CVSS v3.1 vector has %v metric abbreviations defined multiple times", err.Abv)
    +	return fmt.Sprintf("given CVSS v3.1 vector has %s metric abbreviation defined after vector end", err.Abv)
     }
     
     var _ error = (*ErrDefinedN)(nil)
    
  • README.md+31 16 modified
    @@ -74,21 +74,36 @@ We challenge any other Go implementation to do better :stuck_out_tongue_winking_
     
     ### CVSS v2.0
     
    +```
    +goos: linux
    +goarch: amd64
    +pkg: github.com/pandatix/go-cvss/20
    +cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
    +BenchmarkParseVector_Base-4             	 2089275	       572.9 ns/op	     224 B/op	       1 allocs/op
    +BenchmarkParseVector_WithTempAndEnv-4   	 1000000	        1118 ns/op	     224 B/op	       1 allocs/op
    +BenchmarkCVSS20Vector-4                 	 6806152	       176.3 ns/op	      80 B/op	       1 allocs/op
    +BenchmarkCVSS20Get-4                    	46162280	       26.50 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS20Set-4                    	42365036	       27.50 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS20BaseScore-4              	20117143	       57.68 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS20TemporalScore-4          	14383033	       83.66 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS20EnvironmentalScore-4     	15307656	       79.48 ns/op	       0 B/op	       0 allocs/op
    +```
    +
     ### CVSS v3.0
     
     ```
     goos: linux
     goarch: amd64
     pkg: github.com/pandatix/go-cvss/30
     cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
    -BenchmarkParseVector_Base-4                      1443836               808.4 ns/op           352 B/op          1 allocs/op
    -BenchmarkParseVector_WithTempAndEnv-4             701901              1711 ns/op             352 B/op          1 allocs/op
    -BenchmarkCVSS30Vector-4                          5593758               215.8 ns/op            96 B/op          1 allocs/op
    -BenchmarkCVSS30Get-4                            27306528                41.66 ns/op            0 B/op          0 allocs/op
    -BenchmarkCVSS30Set-4                            31862641                37.94 ns/op            0 B/op          0 allocs/op
    -BenchmarkCVSS30BaseScore-4                       7769804               139.2 ns/op             0 B/op          0 allocs/op
    -BenchmarkCVSS30TemporalScore-4                   5814230               189.1 ns/op             0 B/op          0 allocs/op
    -BenchmarkCVSS30EnvironmentalScore-4              6402489               188.7 ns/op             0 B/op          0 allocs/op
    +BenchmarkParseVector_Base-4             	 1458514	       843.4 ns/op	     352 B/op	       1 allocs/op
    +BenchmarkParseVector_WithTempAndEnv-4   	  703789	        2067 ns/op	     352 B/op	       1 allocs/op
    +BenchmarkCVSS30Vector-4                 	 4587404	       237.0 ns/op	      96 B/op	       1 allocs/op
    +BenchmarkCVSS30Get-4                    	26877397	       51.38 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS30Set-4                    	32284153	       38.53 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS30BaseScore-4              	 8275440	       145.4 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS30TemporalScore-4          	 6054021	       195.7 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS30EnvironmentalScore-4     	 6230708	       191.2 ns/op	       0 B/op	       0 allocs/op
     ```
     
     ### CVSS v3.1
    @@ -98,14 +113,14 @@ goos: linux
     goarch: amd64
     pkg: github.com/pandatix/go-cvss/31
     cpu: Intel(R) Core(TM) i5-2450M CPU @ 2.50GHz
    -BenchmarkParseVector_Base-4             	 1312525	       895.0 ns/op	     352 B/op	       1 allocs/op
    -BenchmarkParseVector_WithTempAndEnv-4   	  685629	        2232 ns/op	     352 B/op	       1 allocs/op
    -BenchmarkCVSS31Vector-4                 	 4867528	       223.2 ns/op	      96 B/op	       1 allocs/op
    -BenchmarkCVSS31Get-4                    	31498058	       36.37 ns/op	       0 B/op	       0 allocs/op
    -BenchmarkCVSS31Set-4                    	30187612	       38.73 ns/op	       0 B/op	       0 allocs/op
    -BenchmarkCVSS31BaseScore-4              	11144173	       101.2 ns/op	       0 B/op	       0 allocs/op
    -BenchmarkCVSS31TemporalScore-4          	 7856455	       154.4 ns/op	       0 B/op	       0 allocs/op
    -BenchmarkCVSS31EnvironmentalScore-4     	 6310815	       169.4 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkParseVector_Base-4             	 1445559	       825.3 ns/op	     352 B/op	       1 allocs/op
    +BenchmarkParseVector_WithTempAndEnv-4   	  658578	        1836 ns/op	     352 B/op	       1 allocs/op
    +BenchmarkCVSS31Vector-4                 	 5087984	       244.1 ns/op	      96 B/op	       1 allocs/op
    +BenchmarkCVSS31Get-4                    	28350058	       41.40 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS31Set-4                    	30340425	       40.16 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS31BaseScore-4              	 8535666	       139.3 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS31TemporalScore-4          	 6004561	       189.7 ns/op	       0 B/op	       0 allocs/op
    +BenchmarkCVSS31EnvironmentalScore-4     	 5937879	       184.5 ns/op	       0 B/op	       0 allocs/op
     ```
     
     ## Feedbacks
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.