// CVSS vector parser. package cvss import ( "fmt" "strings" ) //go:generate stringer -linecomment -type=Version //go:generate stringer -linecomment -type=MetricCategory //go:generate stringer -linecomment -type=V2MetricKey //go:generate stringer -linecomment -type=V2Metric //go:generate stringer -linecomment -type=V3MetricKey //go:generate stringer -linecomment -type=V3Metric // CVSS version type Version byte const ( V20 Version = iota // 2.0 V30 // 3.0 V31 // 3.1 ) // CVSS metric category. type MetricCategory byte const ( Base MetricCategory = iota // Base Temporal // Temporal Environmental // Environmental ) // CVSS metric key type V2MetricKey byte const ( V2AccessVector V2MetricKey = iota // AV V2AccessComplexity // AC V2Authentication // Au V2ConfidentialityImpact // C V2IntegrityImpact // I V2AvailabilityImpact // A V2Exploitability // E V2RemediationLevel // RL V2ReportConfidence // RC V2CollateralDamagePotential // CDP V2TargetDistribution // TD V2ConfidentialityRequirement // CR V2IntegrityRequirement // IR V2AvailabilityRequirement // AR ) // CVSS V2 metric key info lut var v2MetricKeys = map[V2MetricKey]struct { Name string Category MetricCategory } { V2AccessVector: { "Access Vector", Base }, V2AccessComplexity: { "Access Complexity", Base }, V2Authentication: { "Authentication", Base }, V2ConfidentialityImpact: { "Confidentiality Impact", Base }, V2IntegrityImpact: { "Integrity Impact", Base }, V2AvailabilityImpact: { "Availability Impact", Base }, V2Exploitability: { "Exploitability", Temporal }, V2RemediationLevel: { "Remediation Level", Temporal }, V2ReportConfidence: { "Report Confidence", Temporal }, V2CollateralDamagePotential: { "Collateral Damage Potential", Environmental }, V2TargetDistribution: { "Target Distribution", Environmental }, V2ConfidentialityRequirement: { "Confidentiality Requirement", Environmental }, V2IntegrityRequirement: { "Integrity Requirement", Environmental }, V2AvailabilityRequirement: { "Availability Requirement", Environmental }, } // v2 metric key IDs lut var v2MetricKeyIds = map[string]V2MetricKey { "AV": V2AccessVector, "AC": V2AccessComplexity, "Au": V2Authentication, "C": V2ConfidentialityImpact, "I": V2IntegrityImpact, "A": V2AvailabilityImpact, "E": V2Exploitability, "RL": V2RemediationLevel, "RC": V2ReportConfidence, "CDP": V2CollateralDamagePotential, "TD": V2TargetDistribution, "CR": V2ConfidentialityRequirement, "IR": V2IntegrityRequirement, "AR": V2AvailabilityRequirement, } // Get metric key from string. func GetV2MetricKeyFromString(s string) (V2MetricKey, error) { k, ok := v2MetricKeyIds[s] if ok { return k, nil } else { return V2AccessVector, fmt.Errorf("unknown metric key: %s", s) } } // Get metric key name. func (k V2MetricKey) Name() string { return v2MetricKeys[k].Name } // Get metric key category. func (k V2MetricKey) Category() MetricCategory { return v2MetricKeys[k].Category } // CVSS v2 metric value type V2Metric byte const ( V2AVNetwork V2Metric = iota // AV:N V2AVAdjacentNetwork // AV:A V2AVLocal // AV:L V2ACLow // AC:L V2ACMedium // AC:L V2ACHigh // AC:H V2AuMultiple // Au:M V2AuSingle // Au:S V2AuNone // Au:N V2CNone // C:N V2CPartial // C:P V2CComplete // C:C V2INone // I:N V2IPartial // I:P V2IComplete // I:C V2ANone // A:N V2APartial // A:P V2AComplete // A:C V2ENotDefined // E:ND V2EUnproven // E:U V2EProofOfConcept // E:POC V2EFunctional // E:F V2EHigh // E:H V2RLOfficialFix // RL:OF V2RLTemporaryFix // RL:TF V2RLWorkaround // RL:W V2RLUnavailable // RL:U V2RLNotDefined // RL:ND V2RCUnconfirmed // RC:UC V2RCUncorroborated // RC:UR V2RCConfirmed // RC:C V2RCNotDefined // RC:ND V2CDPNone // CDP:N V2CDPLow // CDP:L V2CDPLowMedium // CDP:LM V2CDPMediumHigh // CDP:MH V2CDPHigh // CDP:H V2CDPNotDefined // CDP:ND V2TDNone // TD:N V2TDLow // TD:L V2TDMedium // TD:M V2TDHigh // TD:H V2TDNotDefined // TD:ND V2CRLow // CR:L V2CRMedium // CR:M V2CRHigh // CR:H V2CRNotDefined // CR:ND V2IRLow // IR:L V2IRMedium // IR:M V2IRHigh // IR:H V2IRNotDefined // IR:ND V2ARLow // AR:L V2ARMedium // AR:M V2ARHigh // AR:H V2ARNotDefined // AR:ND ) // map of metrics to metric keys var v2MetricKeyLut = map[V2Metric]V2MetricKey { V2AVNetwork: V2AccessVector, V2AVAdjacentNetwork: V2AccessVector, V2AVLocal: V2AccessVector, V2ACLow: V2AccessComplexity, V2ACMedium: V2AccessComplexity, V2ACHigh: V2AccessComplexity, V2AuMultiple: V2Authentication, V2AuSingle: V2Authentication, V2AuNone: V2Authentication, V2CNone: V2ConfidentialityImpact, V2CPartial: V2ConfidentialityImpact, V2CComplete: V2ConfidentialityImpact, V2INone: V2IntegrityImpact, V2IPartial: V2IntegrityImpact, V2IComplete: V2IntegrityImpact, V2ANone: V2AvailabilityImpact, V2APartial: V2AvailabilityImpact, V2AComplete: V2AvailabilityImpact, V2ENotDefined: V2Exploitability, V2EUnproven: V2Exploitability, V2EProofOfConcept: V2Exploitability, V2EFunctional: V2Exploitability, V2EHigh: V2Exploitability, V2RLOfficialFix: V2RemediationLevel, V2RLTemporaryFix: V2RemediationLevel, V2RLWorkaround: V2RemediationLevel, V2RLUnavailable: V2RemediationLevel, V2RLNotDefined: V2RemediationLevel, V2RCUnconfirmed: V2ReportConfidence, V2RCUncorroborated: V2ReportConfidence, V2RCConfirmed: V2ReportConfidence, V2RCNotDefined: V2ReportConfidence, V2CDPNone: V2CollateralDamagePotential, V2CDPLow: V2CollateralDamagePotential, V2CDPLowMedium: V2CollateralDamagePotential, V2CDPMediumHigh: V2CollateralDamagePotential, V2CDPHigh: V2CollateralDamagePotential, V2CDPNotDefined: V2CollateralDamagePotential, V2TDNone: V2TargetDistribution, V2TDLow: V2TargetDistribution, V2TDMedium: V2TargetDistribution, V2TDHigh: V2TargetDistribution, V2TDNotDefined: V2TargetDistribution, V2CRLow: V2ConfidentialityRequirement, V2CRMedium: V2ConfidentialityRequirement, V2CRHigh: V2ConfidentialityRequirement, V2CRNotDefined: V2ConfidentialityRequirement, V2IRLow: V2IntegrityRequirement, V2IRMedium: V2IntegrityRequirement, V2IRHigh: V2IntegrityRequirement, V2IRNotDefined: V2IntegrityRequirement, V2ARLow: V2AvailabilityRequirement, V2ARMedium: V2AvailabilityRequirement, V2ARHigh: V2AvailabilityRequirement, V2ARNotDefined: V2AvailabilityRequirement, } // map of metric strings to metrics var v2MetricStrLut = map[string]V2Metric { "AV:N": V2AVNetwork, "AV:A": V2AVAdjacentNetwork, "AV:L": V2AVLocal, "AC:L": V2ACLow, "AC:M": V2ACMedium, "AC:H": V2ACHigh, "Au:M": V2AuMultiple, "Au:S": V2AuSingle, "Au:N": V2AuNone, "C:N": V2CNone, "C:P": V2CPartial, "C:C": V2CComplete, "I:N": V2INone, "I:P": V2IPartial, "I:C": V2IComplete, "A:N": V2ANone, "A:P": V2APartial, "A:C": V2AComplete, "E:ND": V2ENotDefined, "E:U": V2EUnproven, "E:POC": V2EProofOfConcept, "E:F": V2EFunctional, "E:H": V2EHigh, "RL:OF": V2RLOfficialFix, "RL:TF": V2RLTemporaryFix, "RL:W": V2RLWorkaround, "RL:U": V2RLUnavailable, "RL:ND": V2RLNotDefined, "RC:UC": V2RCUnconfirmed, "RC:UR": V2RCUncorroborated, "RC:C": V2RCConfirmed, "RC:ND": V2RCNotDefined, "CDP:N": V2CDPNone, "CDP:L": V2CDPLow, "CDP:LM": V2CDPLowMedium, "CDP:MH": V2CDPMediumHigh, "CDP:H": V2CDPHigh, "CDP:ND": V2CDPNotDefined, "TD:N": V2TDNone, "TD:L": V2TDLow, "TD:M": V2TDMedium, "TD:H": V2TDHigh, "TD:ND": V2TDNotDefined, "CR:L": V2CRLow, "CR:M": V2CRMedium, "CR:H": V2CRHigh, "CR:ND": V2CRNotDefined, "IR:L": V2IRLow, "IR:M": V2IRMedium, "IR:H": V2IRHigh, "IR:ND": V2IRNotDefined, "AR:L": V2ARLow, "AR:M": V2ARMedium, "AR:H": V2ARHigh, "AR:ND": V2ARNotDefined, } // Convert string to CVSS 2.0 metric. func GetV2MetricFromString(s string) (V2Metric, error) { // get metric m, ok := v2MetricStrLut[s] if !ok { return V2AVNetwork, fmt.Errorf("invalid metric: %s", s) } // return success return m, nil } // CVSS 2.0 vector. type v2Vector []V2Metric // Convert vector to string func (v v2Vector) String() string { // convert to slice of metrics metrics := []V2Metric(v) // build vector r := make([]string, len(metrics)) for i, m := range(metrics) { r[i] = m.String() } // build and return string return strings.Join(r, "/") } // Return CVSS version. func (v2Vector) Version() Version { return V20 } // create CVSS 2.0 vector from string func NewV2VectorFromString(s string) (Vector, error) { strs := strings.Split(s, "/") r := make([]V2Metric, len(strs)) // walk metric strings for i, ms := range(strs) { // convert string to vector m, err := GetV2MetricFromString(ms) if err != nil { return nil, err } // add to results r[i] = m } // build and return vector return v2Vector(r), nil } // CVSS v3 metric key type V3MetricKey byte const ( V3AttackVector V3MetricKey = iota // AV V3AttackComplexity // AC V3PrivilegesRequired // PR V3UserInteraction // UI V3Scope // S V3Confidentiality // C V3Integrity // I V3Availability // A V3ExploitCodeMaturity // E V3RemediationLevel // RL V3ReportConfidence // RC V3ConfidentialityRequirement // CR V3IntegrityRequirement // IR V3AvailabilityRequirement // AR V3ModifiedAttackVector // MAV V3ModifiedAttackComplexity // MAC V3ModifiedPrivilegesRequired // MPR V3ModifiedUserInteraction // MUI V3ModifiedScope // MS V3ModifiedConfidentiality // MC V3ModifiedIntegrity // MI V3ModifiedAvailability // MA ) // CVSS V3 metric key info lut var v3MetricKeys = map[V3MetricKey]struct { Name string Category MetricCategory } { V3AttackVector: { "Attack Vector", Base }, V3AttackComplexity: { "Attack Complexity", Base }, V3PrivilegesRequired: { "Privileges Required", Base }, V3UserInteraction: { "User Interaction", Base }, V3Scope: { "Scope", Base }, V3Confidentiality: { "Confidentiality", Base }, V3Integrity: { "Integrity", Base }, V3Availability: { "Availability", Base }, V3ExploitCodeMaturity: { "Exploit Code Maturity", Temporal }, V3RemediationLevel: { "Remediation Level", Temporal }, V3ReportConfidence: { "Report Confidence", Temporal }, V3ConfidentialityRequirement: { "Confidentiality Requirement", Environmental }, V3IntegrityRequirement: { "Integrity Requirement", Environmental }, V3AvailabilityRequirement: { "Availability Requirement", Environmental }, V3ModifiedAttackVector: { "Modified Attack Vector", Environmental }, V3ModifiedAttackComplexity: { "Modified Attack Complexity", Environmental }, V3ModifiedPrivilegesRequired: { "Modified Privileges Required", Environmental }, V3ModifiedUserInteraction: { "Modified User Interaction", Environmental }, V3ModifiedScope: { "Modified Scope", Environmental }, V3ModifiedConfidentiality: { "Modified Confidentiality", Environmental }, V3ModifiedIntegrity: { "Modified Integrity", Environmental }, V3ModifiedAvailability: { "Modified Availability", Environmental }, } // metric key IDs lut var v3MetricKeyIds = map[string]V3MetricKey { "AV": V3AttackVector, "AC": V3AttackComplexity, "PR": V3PrivilegesRequired, "UI": V3UserInteraction, "S": V3Scope, "C": V3Confidentiality, "I": V3Integrity, "A": V3Availability, "E": V3ExploitCodeMaturity, "RL": V3RemediationLevel, "RC": V3ReportConfidence, "CR": V3ConfidentialityRequirement, "IR": V3IntegrityRequirement, "AR": V3AvailabilityRequirement, "MAV": V3ModifiedAttackVector, "MAC": V3ModifiedAttackComplexity, "MPR": V3ModifiedPrivilegesRequired, "MUI": V3ModifiedUserInteraction, "MS": V3ModifiedScope, "MC": V3ModifiedConfidentiality, "MI": V3ModifiedIntegrity, "MA": V3ModifiedAvailability, } // Get metric key from string. func GetV3MetricKeyFromString(s string) (V3MetricKey, error) { k, ok := v3MetricKeyIds[s] if ok { return k, nil } else { return V3AttackVector, fmt.Errorf("unknown metric key: %s", s) } } // Get metric key name. func (k V3MetricKey) Name() string { return v3MetricKeys[k].Name } // Get metric key category. func (k V3MetricKey) Category() MetricCategory { return v3MetricKeys[k].Category } // metric value type V3Metric byte const ( V3AVNetwork V3Metric = iota // AV:N V3AVAdjacentNetwork // AV:A V3AVLocal // AV:L V3AVPhysical // AV:P V3ACLow // AC:L V3ACHigh // AC:H V3PRNone // PR:N V3PRLow // PR:L V3PRHigh // PR:H V3UINone // UI:N V3UIRequired // UI:R V3SUnchanged // S:U V3SChanged // S:C V3CHigh // C:H V3CLow // C:L V3CNone // C:N V3IHigh // I:H V3ILow // I:L V3INone // I:N V3AHigh // A:H V3ALow // A:L V3ANone // A:N V3ENotDefined // E:X V3EHigh // E:H V3EFunctional // E:F V3EProofOfConcept // E:P V3EUnproven // E:U V3RLNotDefined // RL:X V3RLUnavailable // RL:U V3RLWorkaround // RL:W V3RLTemporaryFix // RL:T V3RLOfficialFix // RL:O V3RCNotDefined // RC:X V3RCConfirmed // RC:C V3RCReasonable // RC:R V3RCUnknown // RC:U V3CRNotDefined // CR:X V3CRHigh // CR:H V3CRMedium // CR:M V3CRLow // CR:L V3IRNotDefined // IR:X V3IRHigh // IR:H V3IRMedium // IR:M V3IRLow // IR:L V3ARNotDefined // AR:X V3ARHigh // AR:H V3ARMedium // AR:M V3ARLow // AR:L V3MAVNotDefined // MAV:X V3MAVNetwork // MAV:N V3MAVAdjacentNetwork // MAV:A V3MAVLocal // MAV:L V3MAVPhysical // MAV:P V3MACNotDefined // MAC:X V3MACLow // MAC:L V3MACHigh // MAC:H V3MMRNotDefined // MPR:X V3MPRLow // MPR:L V3MPRHigh // MPR:H V3MUINotDefined // MUI:X V3MUINone // MUI:N V3MUIRequired // MUI:R V3MSNotDefined // MMS:X V3MSUnchanged // MMS:U V3MSChanged // MMS:C V3MCNotDefined // MC:X V3MCHigh // MC:H V3MCLow // MC:L V3MCNone // MC:N V3MINotDefined // MI:X V3MIHigh // MI:H V3MILow // MI:L V3MINone // MI:N V3MANotDefined // MA:X V3MAHigh // MA:H V3MALow // MA:L V3MANone // MA:N V3UnknownMetric // unknown ) // map of metrics to metric keys var v3MetricKeyLut = map[V3Metric]V3MetricKey { V3AVNetwork: V3AttackVector, // AV:N V3AVAdjacentNetwork: V3AttackVector, // AV:A V3AVLocal: V3AttackVector, // AV:L V3AVPhysical: V3AttackVector, // AV:P V3ACLow: V3AttackComplexity, // AC:L V3ACHigh: V3AttackComplexity, // AC:H V3PRNone: V3PrivilegesRequired, // PR:N V3PRLow: V3PrivilegesRequired, // PR:L V3PRHigh: V3PrivilegesRequired, // PR:H V3UINone: V3UserInteraction, // UI:N V3UIRequired: V3UserInteraction, // UI:R V3SUnchanged: V3Scope, // S:U V3SChanged: V3Scope, // S:C V3CHigh: V3Confidentiality, // C:H V3CLow: V3Confidentiality, // C:L V3CNone: V3Confidentiality, // C:N V3IHigh: V3Integrity, // I:H V3ILow: V3Integrity, // I:L V3INone: V3Integrity, // I:N V3AHigh: V3Availability, // A:H V3ALow: V3Availability, // A:L V3ANone: V3Availability, // A:N V3ENotDefined: V3ExploitCodeMaturity, // E:X V3EHigh: V3ExploitCodeMaturity, // E:H V3EFunctional: V3ExploitCodeMaturity, // E:F V3EProofOfConcept: V3ExploitCodeMaturity, // E:P V3EUnproven: V3ExploitCodeMaturity, // E:U V3RLNotDefined: V3RemediationLevel, // RL:X V3RLUnavailable: V3RemediationLevel, // RL:U V3RLWorkaround: V3RemediationLevel, // RL:W V3RLTemporaryFix: V3RemediationLevel, // RL:T V3RLOfficialFix: V3RemediationLevel, // RL:O V3RCNotDefined: V3ReportConfidence, // RC:X V3RCConfirmed: V3ReportConfidence, // RC:C V3RCReasonable: V3ReportConfidence, // RC:R V3RCUnknown: V3ReportConfidence, // RC:U V3CRNotDefined: V3ConfidentialityRequirement, // CR:X V3CRHigh: V3ConfidentialityRequirement, // CR:H V3CRMedium: V3ConfidentialityRequirement, // CR:M V3CRLow: V3ConfidentialityRequirement, // CR:L V3IRNotDefined: V3IntegrityRequirement, // IR:X V3IRHigh: V3IntegrityRequirement, // IR:H V3IRMedium: V3IntegrityRequirement, // IR:M V3IRLow: V3IntegrityRequirement, // IR:L V3ARNotDefined: V3AvailabilityRequirement, // AR:X V3ARHigh: V3AvailabilityRequirement, // AR:H V3ARMedium: V3AvailabilityRequirement, // AR:M V3ARLow: V3AvailabilityRequirement, // AR:L V3MAVNotDefined: V3ModifiedAttackVector, // MAV:X V3MAVNetwork: V3ModifiedAttackVector, // MAV:N V3MAVAdjacentNetwork: V3ModifiedAttackVector, // MAV:A V3MAVLocal: V3ModifiedAttackVector, // MAV:L V3MAVPhysical: V3ModifiedAttackVector, // MAV:P V3MACNotDefined: V3ModifiedAttackComplexity, // MAC:X V3MACLow: V3ModifiedAttackComplexity, // MAC:L V3MACHigh: V3ModifiedAttackComplexity, // MAC:H V3MMRNotDefined: V3ModifiedPrivilegesRequired, // MPR:X V3MPRLow: V3ModifiedPrivilegesRequired, // MPR:L V3MPRHigh: V3ModifiedPrivilegesRequired, // MPR:H V3MUINotDefined: V3ModifiedUserInteraction, // MUI:X V3MUINone: V3ModifiedUserInteraction, // MUI:N V3MUIRequired: V3ModifiedUserInteraction, // MUI:R V3MSNotDefined: V3ModifiedScope, // MMS:X V3MSUnchanged: V3ModifiedConfidentiality, // MMS:U V3MSChanged: V3ModifiedIntegrity, // MMS:C V3MCNotDefined: V3ModifiedConfidentiality, // MC:X V3MCHigh: V3ModifiedConfidentiality, // MC:H V3MCLow: V3ModifiedConfidentiality, // MC:L V3MCNone: V3ModifiedConfidentiality, // MC:N V3MINotDefined: V3ModifiedIntegrity, // MI:X V3MIHigh: V3ModifiedIntegrity, // MI:H V3MILow: V3ModifiedIntegrity, // MI:L V3MINone: V3ModifiedIntegrity, // MI:N V3MANotDefined: V3ModifiedAvailability, // MA:X V3MAHigh: V3ModifiedAvailability, // MA:H V3MALow: V3ModifiedAvailability, // MA:L V3MANone: V3ModifiedAvailability, // MA:N } // map of metric strings to metrics var v3MetricStrLut = map[string]V3Metric { "AV:N": V3AVNetwork, "AV:A": V3AVAdjacentNetwork, "AV:L": V3AVLocal, "AV:P": V3AVPhysical, "AC:L": V3ACLow, "AC:H": V3ACHigh, "PR:N": V3PRNone, "PR:L": V3PRLow, "PR:H": V3PRHigh, "UI:N": V3UINone, "UI:R": V3UIRequired, "S:U": V3SUnchanged, "S:C": V3SChanged, "C:H": V3CHigh, "C:L": V3CLow, "C:N": V3CNone, "I:H": V3IHigh, "I:L": V3ILow, "I:N": V3INone, "A:H": V3AHigh, "A:L": V3ALow, "A:N": V3ANone, "E:X": V3ENotDefined, "E:H": V3EHigh, "E:F": V3EFunctional, "E:P": V3EProofOfConcept, "E:U": V3EUnproven, "RL:X": V3RLNotDefined, "RL:U": V3RLUnavailable, "RL:W": V3RLWorkaround, "RL:T": V3RLTemporaryFix, "RL:O": V3RLOfficialFix, "RC:X": V3RCNotDefined, "RC:C": V3RCConfirmed, "RC:R": V3RCReasonable, "RC:U": V3RCUnknown, "CR:X": V3CRNotDefined, "CR:H": V3CRHigh, "CR:M": V3CRMedium, "CR:L": V3CRLow, "IR:X": V3IRNotDefined, "IR:H": V3IRHigh, "IR:M": V3IRMedium, "IR:L": V3IRLow, "AR:X": V3ARNotDefined, "AR:H": V3ARHigh, "AR:M": V3ARMedium, "AR:L": V3ARLow, "MAV:X": V3MAVNotDefined, "MAV:N": V3MAVNetwork, "MAV:A": V3MAVAdjacentNetwork, "MAV:L": V3MAVLocal, "MAV:P": V3MAVPhysical, "MAC:X": V3MACNotDefined, "MAC:L": V3MACLow, "MAC:H": V3MACHigh, "MPR:X": V3MMRNotDefined, "MPR:L": V3MPRLow, "MPR:H": V3MPRHigh, "MUI:X": V3MUINotDefined, "MUI:N": V3MUINone, "MUI:R": V3MUIRequired, "MMS:X": V3MSNotDefined, "MMS:U": V3MSUnchanged, "MMS:C": V3MSChanged, "MC:X": V3MCNotDefined, "MC:H": V3MCHigh, "MC:L": V3MCLow, "MC:N": V3MCNone, "MI:X": V3MINotDefined, "MI:H": V3MIHigh, "MI:L": V3MILow, "MI:N": V3MINone, "MA:X": V3MANotDefined, "MA:H": V3MAHigh, "MA:L": V3MALow, "MA:N": V3MANone, } // Convert string to CVSS 3.1 metric. func GetV3MetricFromString(s string) (V3Metric, error) { // get metric m, ok := v3MetricStrLut[s] if !ok { return V3AVNetwork, fmt.Errorf("invalid metric: %s", s) } // return success return m, nil } // CVSS v3.0 prefix var v30Prefix = "CVSS:3.0/" // CVSS 3.0 vector. type v30Vector []V3Metric // Convert vector to string func (v v30Vector) String() string { // convert to slice of metrics metrics := []V3Metric(v) // build vector r := make([]string, len(metrics)) for i, m := range(metrics) { r[i] = m.String() } // build and return string return v30Prefix + strings.Join(r, "/") } // Return CVSS version. func (v30Vector) Version() Version { return V30 } // create CVSS 3.0 vector from string func NewV30VectorFromString(s string) (Vector, error) { strs := strings.Split(s, "/") r := make([]V3Metric, len(strs)) // walk metric strings for i, ms := range(strs) { // convert string to vector m, err := GetV3MetricFromString(ms) if err != nil { return nil, err } // add to results r[i] = m } // build and return vector return v30Vector(r), nil } // CVSS v3.1 prefix var v31Prefix = "CVSS:3.1/" // CVSS 3.1 vector. type v31Vector []V3Metric // Convert vector to string func (v v31Vector) String() string { // convert to slice of metrics metrics := []V3Metric(v) // build vector r := make([]string, len(metrics)) for i, m := range(metrics) { r[i] = m.String() } // build and return string return v31Prefix + strings.Join(r, "/") } // Return CVSS version. func (v31Vector) Version() Version { return V31 } // create CVSS 3.1 vector from string func NewV31VectorFromString(s string) (Vector, error) { strs := strings.Split(s, "/") r := make([]V3Metric, len(strs)) // walk metric strings for i, ms := range(strs) { // convert string to vector m, err := GetV3MetricFromString(ms) if err != nil { return nil, err } // add to results r[i] = m } // build and return vector return v31Vector(r), nil } // CVSS vector type Vector interface { // Get CVSS version. Version() Version // Get CVSS vector string. String() string } // Create new CVSS vector from vector string. func NewVector(s string) (Vector, error) { if len(s) > len(v31Prefix) && s[:len(v31Prefix)] == v31Prefix { // create CVSS v2.0 vector. return NewV31VectorFromString(s[len(v31Prefix):]) } else if len(s) > len(v30Prefix) && s[:len(v30Prefix)] == v30Prefix { // create CVSS v3.0 vector. return NewV30VectorFromString(s[len(v30Prefix):]) } else { // create CVSS V2 vector return NewV2VectorFromString(s) } }