From 47d25cba0fa216342ce3cc5f1cb3a8bd8d17c824 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Wed, 16 Feb 2022 03:08:44 -0500 Subject: cvss: 100% v31vector test coverage --- cvss/v31vector.go | 448 +++++++++++++++++++++++++----------------------- cvss/v31vector_test.go | 130 +++++++++++++- cvss/v3metric.go | 21 ++- cvss/v3metric_string.go | 47 ++--- cvss/v3metric_test.go | 18 +- 5 files changed, 408 insertions(+), 256 deletions(-) diff --git a/cvss/v31vector.go b/cvss/v31vector.go index b191ce0..1950e5a 100644 --- a/cvss/v31vector.go +++ b/cvss/v31vector.go @@ -131,218 +131,257 @@ func hasTemporalScoreKeys(keys map[Key]v3Metric) bool { (rc_ok && rc != v3RCNotDefined) } +// Does the map have at least one of the keys needed for an env score to +// be defined? +func hasEnvScoreKeys(keys map[Key]v3Metric) bool { + mav, mav_ok := keys[v3ModifiedAttackVector] // MAV + mac, mac_ok := keys[v3ModifiedAttackComplexity] // MAC + mpr, mpr_ok := keys[v3ModifiedPrivilegesRequired] // MPR + mui, mui_ok := keys[v3ModifiedUserInteraction] // MUI + ms, ms_ok := keys[v3ModifiedScope] // MS + mc, mc_ok := keys[v3ModifiedConfidentiality] // MC + mi, mi_ok := keys[v3ModifiedIntegrity] // MI + ma, ma_ok := keys[v3ModifiedAvailability] // MA + cr, cr_ok := keys[v3ConfidentialityRequirement] // CR + ir, ir_ok := keys[v3IntegrityRequirement] // IR + ar, ar_ok := keys[v3AvailabilityRequirement] // AR + + return (mav_ok && mav != v3MAVNotDefined) || + (mac_ok && mac != v3MACNotDefined) || + (mpr_ok && mpr != v3MPRNotDefined) || + (mui_ok && mui != v3MUINotDefined) || + (ms_ok && ms != v3MSNotDefined) || + (mc_ok && mc != v3MCNotDefined) || + (mi_ok && mi != v3MINotDefined) || + (ma_ok && ma != v3MANotDefined) || + (cr_ok && cr != v3CRNotDefined) || + (ir_ok && ir != v3IRNotDefined) || + (ar_ok && ar != v3ARNotDefined); +} + // roundup implemention (from CVSS v3.1 spec, appendix A) func roundup(val float64) float64 { return math.Ceil(10.0 * val) / 10.0 } +var v31MetricCoefs = map[v3Metric]float64 { + v3AVNetwork: 0.85, // AV:N + v3AVAdjacentNetwork: 0.62, // AV:A + v3AVLocal: 0.55, // AV:L + v3AVPhysical: 0.2, // AV:P + + v3ACLow: 0.77, // AC:L + v3ACHigh: 0.44, // AC:H + + v3PRNone: 0.85, // PR:N + v3PRLow: 0.62, // PR:L + v3PRHigh: 0.27, // PR:H + + v3UINone: 0.85, // UI:N + v3UIRequired: 0.62, // UI:R + + v3CHigh: 0.56, // C:H + v3CLow: 0.22, // C:L + v3CNone: 0.0, // C:N + + v3IHigh: 0.56, // I:H + v3ILow: 0.22, // I:L + v3INone: 0.0, // I:N + + v3AHigh: 0.56, // A:H + v3ALow: 0.22, // A:L + v3ANone: 0.0, // A:N + + v3ENotDefined: 1.0, // E:X + v3EHigh: 1.0, // E:H + v3EFunctional: 0.97, // E:F + v3EProofOfConcept: 0.94, // E:P + v3EUnproven: 0.91, // E:U + + v3RLNotDefined: 1.0, // RL:X + v3RLUnavailable: 1.0, // RL:U + v3RLWorkaround: 0.97, // RL:W + v3RLTemporaryFix: 0.96, // RL:T + v3RLOfficialFix: 0.95, // RL:O + + v3RCNotDefined: 1.0, // RC:X + v3RCConfirmed: 1.0, // RC:C + v3RCReasonable: 0.96, // RC:R + v3RCUnknown: 0.92, // RC:U + + v3CRNotDefined: 1.0, // CR:X + v3CRHigh: 1.5, // CR:H + v3CRMedium: 1.0, // CR:M + v3CRLow: 0.5, // CR:L + + v3IRNotDefined: 1.0, // IR:X + v3IRHigh: 1.5, // IR:H + v3IRMedium: 1.0, // IR:M + v3IRLow: 0.5, // IR:L + + v3ARNotDefined: 1.0, // AR:X + v3ARHigh: 1.5, // AR:H + v3ARMedium: 1.0, // AR:M + v3ARLow: 0.5, // AR:L + + v3MAVNotDefined: 1.0, // MAV:X + v3MAVNetwork: 0.85, // MAV:N + v3MAVAdjacentNetwork: 0.62, // MAV:A + v3MAVLocal: 0.55, // MAV:L + v3MAVPhysical: 0.2, // MAV:P + + v3MACNotDefined: 1.0, // MAC:X + v3MACLow: 0.77, // MAC:L + v3MACHigh: 0.44, // MAC:H + + v3MPRNotDefined: 1.0, // MPR:X + v3MPRNone: 0.85, // MPR:N + v3MPRLow: 0.62, // MPR:L + v3MPRHigh: 0.27, // MPR:H + + v3MUINotDefined: 1.0, // MUI:X + v3MUINone: 0.85, // MUI:N + v3MUIRequired: 0.62, // MUI:R + + v3MCNotDefined: 1.0, // MC:X + v3MCHigh: 0.56, // MC:H + v3MCLow: 0.22, // MC:L + v3MCNone: 0.0, // MC:N + + v3MINotDefined: 1.0, // MI:X + v3MIHigh: 0.56, // MI:H + v3MILow: 0.22, // MI:L + v3MINone: 0.0, // MI:N + + v3MANotDefined: 1.0, // MA:X + v3MAHigh: 0.56, // MA:H + v3MALow: 0.22, // MA:L + v3MANone: 0.0, // MA:N +} + +// map of modified metrics to not defined value and base key +var v31ModMetricDefaults = map[v3Key]struct { + notDefined v3Metric + baseKey v3Key +} { + v3ModifiedAttackVector: { v3MAVNotDefined, v3AttackVector }, + v3ModifiedAttackComplexity: { v3MACNotDefined, v3AttackComplexity }, + v3ModifiedUserInteraction: { v3MUINotDefined, v3UserInteraction }, + v3ModifiedConfidentiality: { v3MCNotDefined, v3Confidentiality }, + v3ModifiedIntegrity: { v3MINotDefined, v3Integrity }, + v3ModifiedAvailability: { v3MANotDefined, v3Availability }, +} + +// Get modified metric coefficient, or fall back to base coefficient if +// modified metric is not defined. +func getModCoef(keys map[Key]v3Metric, key v3Key) float64 { + d := v31ModMetricDefaults[key] + if v, _ := keys[key]; v != d.notDefined { + // return modified metric coefficient + return v31MetricCoefs[v] + } else { + // return base coefficient + return v31MetricCoefs[keys[d.baseKey]] + } +} +// var metricWeightMPR = CVSS31.Weight.PR [MS !== "X" ? MS : S] [MPR !== "X" ? MPR : PR]; // Depends on MS. + +var v31PrivReqCoefs = map[v3Metric]map[bool]float64 { + v3PRNone: map[bool]float64 { false: 0.85, true: 0.85 }, + v3PRLow: map[bool]float64 { false: 0.62, true: 0.68 }, + v3PRHigh: map[bool]float64 { false: 0.27, true: 0.50 }, + v3MPRNone: map[bool]float64 { false: 0.85, true: 0.85 }, + v3MPRLow: map[bool]float64 { false: 0.62, true: 0.68 }, + v3MPRHigh: map[bool]float64 { false: 0.27, true: 0.50 }, +} + // Return numerical scores for this vector. func (v v31Vector) Scores() (Scores, error) { - attackVector := 0.0 - attackComplexity := 0.0 - privsRequired := 0.0 - userInteraction := 0.0 scopeChanged := false - conf := 0.0 - integ := 0.0 - avail := 0.0 - ecm := 1.0 - remediationLevel := 1.0 - reportConfidence := 1.0 - confReq := 1.0 - availReq := 1.0 - integReq := 1.0 - - modAttackVector := 0.0 - modAttackComplexity := 0.0 - modPrivsRequired := 0.0 - modUserInteraction := 0.0 modScopeChanged := false - modConf := 0.0 - modInteg := 0.0 - modAvail := 0.0 - keys := make(map[Key]v3Metric) + // default metrics map + keys := map[Key]v3Metric { + v3ExploitCodeMaturity: v3ENotDefined, + v3RemediationLevel: v3RLNotDefined, + v3ReportConfidence: v3RCNotDefined, + v3ConfidentialityRequirement: v3CRNotDefined, + v3IntegrityRequirement: v3IRNotDefined, + v3AvailabilityRequirement: v3ARNotDefined, + v3ModifiedAttackVector: v3MAVNotDefined, + v3ModifiedAttackComplexity: v3MACNotDefined, + v3ModifiedPrivilegesRequired: v3MPRNotDefined, + v3ModifiedUserInteraction: v3MUINotDefined, + v3ModifiedConfidentiality: v3MCNotDefined, + v3ModifiedIntegrity: v3MINotDefined, + v3ModifiedAvailability: v3MANotDefined, + v3ModifiedScope: v3MSNotDefined, + } + // populate metrics map for _, m := range([]v3Metric(v)) { keys[m.Key()] = m switch m { - case v3AVNetwork: // AV:N - attackVector = 0.85 - case v3AVAdjacentNetwork: // AV:A - attackVector = 0.62 - case v3AVLocal: // AV:L - attackVector = 0.55 - case v3AVPhysical: // AV:P - attackVector = 0.2 - - case v3ACLow: // AC:L - attackComplexity = 0.77 - case v3ACHigh: // AC:H - attackComplexity = 0.44 - - case v3PRNone: // PR:N - privsRequired = 0.85 - case v3PRLow: // PR:L - privsRequired = 0.62 - case v3PRHigh: // PR:H - privsRequired = 0.27 - - case v3UINone: // UI:N - userInteraction = 0.85 - case v3UIRequired: // UI:R - userInteraction = 0.62 - case v3SUnchanged: // S:U scopeChanged = false case v3SChanged: // S:C scopeChanged = true - case v3CHigh: // C:H - conf = 0.56 - case v3CLow: // C:L - conf = 0.22 - case v3CNone: // C:N - conf = 0.0 - - case v3IHigh: // I:H - integ = 0.56 - case v3ILow: // I:L - integ = 0.22 - case v3INone: // I:N - integ = 0.0 - - case v3AHigh: // A:H - avail = 0.56 - case v3ALow: // A:L - avail = 0.22 - case v3ANone: // A:N - avail = 0.0 - - case v3ENotDefined: // E:X - ecm = 1.0 - case v3EHigh: // E:H - ecm = 1.0 - case v3EFunctional: // E:F - ecm = 0.97 - case v3EProofOfConcept: // E:P - ecm = 0.94 - case v3EUnproven: // E:U - ecm = 0.91 - - case v3RLNotDefined: // RL:X - remediationLevel = 1.0 - case v3RLUnavailable: // RL:U - remediationLevel = 1.0 - case v3RLWorkaround: // RL:W - remediationLevel = 0.97 - case v3RLTemporaryFix: // RL:T - remediationLevel = 0.96 - case v3RLOfficialFix: // RL:O - remediationLevel = 0.95 - - case v3RCNotDefined: // RC:X - reportConfidence = 1.0 - case v3RCConfirmed: // RC:C - reportConfidence = 1.0 - case v3RCReasonable: // RC:R - reportConfidence = 0.96 - case v3RCUnknown: // RC:U - reportConfidence = 0.92 - - case v3CRNotDefined: // CR:X - confReq = 1.0 - case v3CRHigh: // CR:H - confReq = 1.5 - case v3CRMedium: // CR:M - confReq = 1.0 - case v3CRLow: // CR:L - confReq = 0.5 - - case v3IRNotDefined: // IR:X - integReq = 1.0 - case v3IRHigh: // IR:H - integReq = 1.5 - case v3IRMedium: // IR:M - integReq = 1.0 - case v3IRLow: // IR:L - integReq = 0.5 - - case v3ARNotDefined: // AR:X - availReq = 1.0 - case v3ARHigh: // AR:H - availReq = 1.5 - case v3ARMedium: // AR:M - availReq = 1.0 - case v3ARLow: // AR:L - availReq = 0.5 - - case v3MAVNotDefined: // MAV:X - modAttackVector = 0.0 - case v3MAVNetwork: // MAV:N - modAttackVector = 0.85 - case v3MAVAdjacentNetwork: // MAV:A - modAttackVector = 0.62 - case v3MAVLocal: // MAV:L - modAttackVector = 0.55 - case v3MAVPhysical: // MAV:P - modAttackVector = 0.2 - - case v3MACNotDefined: // MAC:X - modAttackComplexity = 0.0 - case v3MACLow: // MAC:L - modAttackComplexity = 0.77 - case v3MACHigh: // MAC:H - modAttackComplexity = 0.44 - - case v3MPRNotDefined: // MPR:X - modPrivsRequired = 0.0 - case v3MPRLow: // MPR:L - modPrivsRequired = 0.62 - case v3MPRHigh: // MPR:H - modPrivsRequired = 0.27 - - case v3MUINotDefined: // MUI:X - modUserInteraction = 0.85 - case v3MUINone: // MUI:N - modUserInteraction = 0.85 - case v3MUIRequired: // MUI:R - modUserInteraction = 0.62 - - case v3MSNotDefined: // MS:X - modScopeChanged = false case v3MSUnchanged: // MS:U modScopeChanged = false - case v3MSChanged: // MS:C + case v3MSChanged: // MS:U modScopeChanged = true + } + } - case v3MCNotDefined: // MC:X - modConf = 0.0 - case v3MCHigh: // MC:H - modConf = 0.56 - case v3MCLow: // MC:L - modConf = 0.22 - case v3MCNone: // MC:N - modConf = 0.0 - - case v3MINotDefined: // MI:X - modInteg = 0.0 - case v3MIHigh: // MI:H - modInteg = 0.56 - case v3MILow: // MI:L - modInteg = 0.22 - case v3MINone: // MI:N - modInteg = 0.0 - - case v3MANotDefined: // MA:X - modAvail = 0.0 - case v3MAHigh: // MA:H - modAvail = 0.56 - case v3MALow: // MA:L - modAvail = 0.22 - case v3MANone: // MA:N - modAvail = 0.0 + attackVector := v31MetricCoefs[keys[v3AttackVector]] + attackComplexity := v31MetricCoefs[keys[v3AttackComplexity]] + userInteraction := v31MetricCoefs[keys[v3UserInteraction]] + conf := v31MetricCoefs[keys[v3Confidentiality]] + integ := v31MetricCoefs[keys[v3Integrity]] + avail := v31MetricCoefs[keys[v3Availability]] + ecm := v31MetricCoefs[keys[v3ExploitCodeMaturity]] + remediationLevel := v31MetricCoefs[keys[v3RemediationLevel]] + reportConfidence := v31MetricCoefs[keys[v3ReportConfidence]] + confReq := v31MetricCoefs[keys[v3ConfidentialityRequirement]] + availReq := v31MetricCoefs[keys[v3AvailabilityRequirement]] + integReq := v31MetricCoefs[keys[v3IntegrityRequirement]] + + // adjust privsRequired based on scopeChanged + // (CVSS v3.1 spec, section 7.4, table 16) + privsRequired := v31PrivReqCoefs[keys[v3PrivilegesRequired]][scopeChanged] + + modAttackVector := getModCoef(keys, v3ModifiedAttackVector) + modAttackComplexity := getModCoef(keys, v3ModifiedAttackComplexity) + modUserInteraction := getModCoef(keys, v3ModifiedUserInteraction) + modConf := getModCoef(keys, v3ModifiedConfidentiality) + modInteg := getModCoef(keys, v3ModifiedIntegrity) + modAvail := getModCoef(keys, v3ModifiedAvailability) + + if v, _ := keys[v3ModifiedScope]; v == v3MSNotDefined { + // default to base scopeChanged + modScopeChanged = scopeChanged + } + + // adjust modPrivsRequired based on scopeChanged + // (CVSS v3.1 spec, section 7.4, table 16) + modPrivsRequired := 0.0 + { + mpr, _ := keys[v3ModifiedPrivilegesRequired] + pr, _ := keys[v3PrivilegesRequired] + ms, _ := keys[v3ModifiedScope] + + if mpr != v3MPRNotDefined && ms != v3MSNotDefined { + modPrivsRequired = v31PrivReqCoefs[mpr][ms == v3MSChanged] + } else if mpr != v3MPRNotDefined && ms == v3MSNotDefined { + modPrivsRequired = v31PrivReqCoefs[mpr][scopeChanged] + } else if mpr == v3MPRNotDefined && ms != v3MSNotDefined { + modPrivsRequired = v31PrivReqCoefs[pr][ms == v3MSChanged] + } else { + // default to base privsRequired + // modPrivsRequired = privsRequired + modPrivsRequired = v31PrivReqCoefs[pr][scopeChanged] } } @@ -356,17 +395,6 @@ func (v v31Vector) Scores() (Scores, error) { impact := 0.0 if scopeChanged { impact = 7.52 * (iss - 0.029) - 3.25 * math.Pow(iss - 0.02, 15) - - // adjust privileges required based on scopeChanged - // (CVSS v3.1 spec, section 7.4, table 16) - if pr, ok := keys[v3PrivilegesRequired]; ok { - switch pr { - case v3PRLow: // PR:L - privsRequired = 0.68 - case v3PRHigh: // PR:H - privsRequired = 0.50 - } - } } else { impact = 6.42 * iss } @@ -389,18 +417,10 @@ func (v v31Vector) Scores() (Scores, error) { tempScore = roundup(baseScore * ecm * remediationLevel * reportConfidence) } - // environmental score (CVSS v3.1 spec, section 7.3) - // - // MISS = Minimum( - // 1 - [(1 - ConfidentialityRequirement × ModifiedConfidentiality) × (1 - IntegrityRequirement × ModifiedIntegrity) × (1 - AvailabilityRequirement × ModifiedAvailability)], - // 0.915 - // ) - // - // environmental score (CVSS v3.1 spec, section 7.3) envScore := 0.0 - { - // modified impact sub score + if hasEnvScoreKeys(keys) { + // modified impact sub score (ISC_m) miss := math.Min( 1 - (1 - confReq * modConf) * (1 - integReq * modInteg) * (1 - availReq * modAvail), 0.915, @@ -415,18 +435,18 @@ func (v v31Vector) Scores() (Scores, error) { impact = 6.42 * miss } - // modified exploitability + // modified exploitability sub score expl := 8.22 * modAttackVector * modAttackComplexity * modPrivsRequired * modUserInteraction // calculate env score - if impact < 0.0 { + if impact <= 0.0 { envScore = 0.0 } else if modScopeChanged { - // Roundup ( Roundup [Minimum (1.08 × [ModifiedImpact + ModifiedExploitability], 10) ] × ExploitCodeMaturity × RemediationLevel × ReportConfidence) + // Roundup(Roundup[Minimum(1.08 × [ModifiedImpact + ModifiedExploitability], 10)] × ExploitCodeMaturity × RemediationLevel × ReportConfidence) envScore = roundup(roundup(math.Min(1.08 * (impact + expl), 10.0)) * ecm * remediationLevel * reportConfidence) } else { - // Roundup ( Roundup [Minimum ([ModifiedImpact + ModifiedExploitability], 10) ] × ExploitCodeMaturity × RemediationLevel × ReportConfidence) - envScore = roundup(roundup(math.Min((impact * expl), 10.0)) * ecm * remediationLevel * reportConfidence) + // Roundup(Roundup[Minimum([ModifiedImpact + ModifiedExploitability], 10) ] × ExploitCodeMaturity × RemediationLevel × ReportConfidence) + envScore = roundup(roundup(math.Min((impact + expl), 10.0)) * ecm * remediationLevel * reportConfidence) } } diff --git a/cvss/v31vector_test.go b/cvss/v31vector_test.go index 519b18a..46e1fde 100644 --- a/cvss/v31vector_test.go +++ b/cvss/v31vector_test.go @@ -70,7 +70,7 @@ func TestNewV31Vector(t *testing.T) { } func TestIsV31VectorString(t *testing.T) { - // test non v31 strings + // test v31 strings passTests := []string { "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H", "CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N", @@ -678,6 +678,134 @@ func TestV31VectorScores(t *testing.T) { name: "RC:C", val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/RC:C", exp: []float64 { 7.3, 7.3, 0.0 }, + }, { + name: "MAV:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:N/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MAV:A", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:A/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.3 }, + }, { + name: "MAV:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:L/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 5.9 }, + }, { + name: "MAV:P", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:P/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 4.3 }, + }, { + name: "MAC:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:L/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MAC:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:H/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 5.6 }, + }, { + name: "MPR:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:N/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MPR:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:L/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.3 }, + }, { + name: "MPR:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:H/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 4.7 }, + }, { + name: "MUI:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:N/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MUI:R", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:R/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.3 }, + }, { + name: "MS:U", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:U/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MS:C", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:C/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 8.3 }, + }, { + name: "MC:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:N/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.5 }, + }, { + name: "MC:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:L/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MC:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:H/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 8.6 }, + }, { + name: "MI:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:N/MA:X", + exp: []float64 { 7.3, 0.0, 6.5 }, + }, { + name: "MI:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:L/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MI:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:H/MA:X", + exp: []float64 { 7.3, 0.0, 8.6 }, + }, { + name: "MA:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:N", + exp: []float64 { 7.3, 0.0, 6.5 }, + }, { + name: "MA:N", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:L", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "MA:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:H", + exp: []float64 { 7.3, 0.0, 8.6 }, + }, { + name: "CR:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:L/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.9 }, + }, { + name: "CR:M", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:M/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "CR:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:H/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.7 }, + }, { + name: "IR:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:L/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.9 }, + }, { + name: "IR:M", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:M/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "IR:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:H/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.7 }, + }, { + name: "AR:L", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:L/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.9 }, + }, { + name: "AR:M", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:M/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.3 }, + }, { + name: "AR:H", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:H/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 7.7 }, + }, { + name: "MPR:H/MS:C", + val: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:H/MUI:X/MS:C/MC:X/MI:X/MA:X", + exp: []float64 { 7.3, 0.0, 6.6 }, }} for _, test := range(tests) { diff --git a/cvss/v3metric.go b/cvss/v3metric.go index df408fd..c0f00be 100644 --- a/cvss/v3metric.go +++ b/cvss/v3metric.go @@ -79,6 +79,7 @@ const ( v3MACHigh // MAC:H v3MPRNotDefined // MPR:X + v3MPRNone // MPR:N v3MPRLow // MPR:L v3MPRHigh // MPR:H @@ -86,9 +87,9 @@ const ( v3MUINone // MUI:N v3MUIRequired // MUI:R - v3MSNotDefined // MMS:X - v3MSUnchanged // MMS:U - v3MSChanged // MMS:C + v3MSNotDefined // MS:X + v3MSUnchanged // MS:U + v3MSChanged // MS:C v3MCNotDefined // MC:X v3MCHigh // MC:H @@ -183,6 +184,7 @@ var v3KeyLut = map[v3Metric]v3Key { v3MACHigh: v3ModifiedAttackComplexity, // MAC:H v3MPRNotDefined: v3ModifiedPrivilegesRequired, // MPR:X + v3MPRNone: v3ModifiedPrivilegesRequired, // MPR:N v3MPRLow: v3ModifiedPrivilegesRequired, // MPR:L v3MPRHigh: v3ModifiedPrivilegesRequired, // MPR:H @@ -190,9 +192,9 @@ var v3KeyLut = map[v3Metric]v3Key { v3MUINone: v3ModifiedUserInteraction, // MUI:N v3MUIRequired: v3ModifiedUserInteraction, // MUI:R - v3MSNotDefined: v3ModifiedScope, // MMS:X - v3MSUnchanged: v3ModifiedConfidentiality, // MMS:U - v3MSChanged: v3ModifiedIntegrity, // MMS:C + v3MSNotDefined: v3ModifiedScope, // MS:X + v3MSUnchanged: v3ModifiedScope, // MS:U + v3MSChanged: v3ModifiedScope, // MS:C v3MCNotDefined: v3ModifiedConfidentiality, // MC:X v3MCHigh: v3ModifiedConfidentiality, // MC:H @@ -285,6 +287,7 @@ var v3MetricStrLut = map[string]v3Metric { "MAC:H": v3MACHigh, "MPR:X": v3MPRNotDefined, + "MPR:N": v3MPRNone, "MPR:L": v3MPRLow, "MPR:H": v3MPRHigh, @@ -292,9 +295,9 @@ var v3MetricStrLut = map[string]v3Metric { "MUI:N": v3MUINone, "MUI:R": v3MUIRequired, - "MMS:X": v3MSNotDefined, - "MMS:U": v3MSUnchanged, - "MMS:C": v3MSChanged, + "MS:X": v3MSNotDefined, + "MS:U": v3MSUnchanged, + "MS:C": v3MSChanged, "MC:X": v3MCNotDefined, "MC:H": v3MCHigh, diff --git a/cvss/v3metric_string.go b/cvss/v3metric_string.go index b7d6702..6435c57 100644 --- a/cvss/v3metric_string.go +++ b/cvss/v3metric_string.go @@ -65,32 +65,33 @@ func _() { _ = x[v3MACLow-54] _ = x[v3MACHigh-55] _ = x[v3MPRNotDefined-56] - _ = x[v3MPRLow-57] - _ = x[v3MPRHigh-58] - _ = x[v3MUINotDefined-59] - _ = x[v3MUINone-60] - _ = x[v3MUIRequired-61] - _ = x[v3MSNotDefined-62] - _ = x[v3MSUnchanged-63] - _ = x[v3MSChanged-64] - _ = x[v3MCNotDefined-65] - _ = x[v3MCHigh-66] - _ = x[v3MCLow-67] - _ = x[v3MCNone-68] - _ = x[v3MINotDefined-69] - _ = x[v3MIHigh-70] - _ = x[v3MILow-71] - _ = x[v3MINone-72] - _ = x[v3MANotDefined-73] - _ = x[v3MAHigh-74] - _ = x[v3MALow-75] - _ = x[v3MANone-76] - _ = x[v3InvalidMetric-77] + _ = x[v3MPRNone-57] + _ = x[v3MPRLow-58] + _ = x[v3MPRHigh-59] + _ = x[v3MUINotDefined-60] + _ = x[v3MUINone-61] + _ = x[v3MUIRequired-62] + _ = x[v3MSNotDefined-63] + _ = x[v3MSUnchanged-64] + _ = x[v3MSChanged-65] + _ = x[v3MCNotDefined-66] + _ = x[v3MCHigh-67] + _ = x[v3MCLow-68] + _ = x[v3MCNone-69] + _ = x[v3MINotDefined-70] + _ = x[v3MIHigh-71] + _ = x[v3MILow-72] + _ = x[v3MINone-73] + _ = x[v3MANotDefined-74] + _ = x[v3MAHigh-75] + _ = x[v3MALow-76] + _ = x[v3MANone-77] + _ = x[v3InvalidMetric-78] } -const _v3Metric_name = "AV:NAV:AAV:LAV:PAC:LAC:HPR:NPR:LPR:HUI:NUI:RS:US:CC:HC:LC:NI:HI:LI:NA:HA:LA:NE:XE:HE:FE:PE:URL:XRL:URL:WRL:TRL:ORC:XRC:CRC:RRC:UCR:XCR:HCR:MCR:LIR:XIR:HIR:MIR:LAR:XAR:HAR:MAR:LMAV:XMAV:NMAV:AMAV:LMAV:PMAC:XMAC:LMAC:HMPR:XMPR:LMPR:HMUI:XMUI:NMUI:RMMS:XMMS:UMMS:CMC:XMC:HMC:LMC:NMI:XMI:HMI:LMI:NMA:XMA:HMA:LMA:Ninvalid" +const _v3Metric_name = "AV:NAV:AAV:LAV:PAC:LAC:HPR:NPR:LPR:HUI:NUI:RS:US:CC:HC:LC:NI:HI:LI:NA:HA:LA:NE:XE:HE:FE:PE:URL:XRL:URL:WRL:TRL:ORC:XRC:CRC:RRC:UCR:XCR:HCR:MCR:LIR:XIR:HIR:MIR:LAR:XAR:HAR:MAR:LMAV:XMAV:NMAV:AMAV:LMAV:PMAC:XMAC:LMAC:HMPR:XMPR:NMPR:LMPR:HMUI:XMUI:NMUI:RMS:XMS:UMS:CMC:XMC:HMC:LMC:NMI:XMI:HMI:LMI:NMA:XMA:HMA:LMA:Ninvalid" -var _v3Metric_index = [...]uint16{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 181, 186, 191, 196, 201, 206, 211, 216, 221, 226, 231, 236, 241, 246, 251, 256, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 316} +var _v3Metric_index = [...]uint16{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 164, 168, 172, 176, 181, 186, 191, 196, 201, 206, 211, 216, 221, 226, 231, 236, 241, 246, 251, 255, 259, 263, 267, 271, 275, 279, 283, 287, 291, 295, 299, 303, 307, 311, 318} func (i v3Metric) String() string { if i >= v3Metric(len(_v3Metric_index)-1) { diff --git a/cvss/v3metric_test.go b/cvss/v3metric_test.go index a3c587a..40cdec1 100644 --- a/cvss/v3metric_test.go +++ b/cvss/v3metric_test.go @@ -88,9 +88,9 @@ func TestGetV3Metric(t *testing.T) { { "MUI:N", v3MUINone, true }, { "MUI:R", v3MUIRequired, true }, - { "MMS:X", v3MSNotDefined, true }, - { "MMS:U", v3MSUnchanged, true }, - { "MMS:C", v3MSChanged, true }, + { "MS:X", v3MSNotDefined, true }, + { "MS:U", v3MSUnchanged, true }, + { "MS:C", v3MSChanged, true }, { "MC:X", v3MCNotDefined, true }, { "MC:H", v3MCHigh, true }, @@ -209,9 +209,9 @@ func TestGetV3MetricKey(t *testing.T) { { v3MUINone, v3ModifiedUserInteraction }, // MUI:N { v3MUIRequired, v3ModifiedUserInteraction }, // MUI:R - { v3MSNotDefined, v3ModifiedScope }, // MMS:X - { v3MSUnchanged, v3ModifiedConfidentiality }, // MMS:U - { v3MSChanged, v3ModifiedIntegrity }, // MMS:C + { v3MSNotDefined, v3ModifiedScope }, // MS:X + { v3MSUnchanged, v3ModifiedScope }, // MS:U + { v3MSChanged, v3ModifiedScope }, // MS:C { v3MCNotDefined, v3ModifiedConfidentiality }, // MC:X { v3MCHigh, v3ModifiedConfidentiality }, // MC:H @@ -324,9 +324,9 @@ func TestV3MetricString(t *testing.T) { { v3MUINone, "MUI:N" }, { v3MUIRequired, "MUI:R" }, - { v3MSNotDefined, "MMS:X" }, - { v3MSUnchanged, "MMS:U" }, - { v3MSChanged, "MMS:C" }, + { v3MSNotDefined, "MS:X" }, + { v3MSUnchanged, "MS:U" }, + { v3MSChanged, "MS:C" }, { v3MCNotDefined, "MC:X" }, { v3MCHigh, "MC:H" }, -- cgit v1.2.3