package cvss import ( "regexp" "strings" ) // 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 } // Return metrics in this vector. func (v v31Vector) Metrics() []Metric { // build slice of metrics r := make([]Metric, len(v)) for i, m := range(v) { r[i] = m } // return result return r } // create CVSS 3.1 vector from string. func newV31Vector(s string) (v31Vector, error) { // strip version prefix, split into metric strings strs := strings.Split(s[len(v31Prefix):], "/") r := make([]v3Metric, len(strs)) // build results for i, ms := range(strs) { // get metric from string m, err := getV3Metric(V31, ms) if err != nil { return nil, err } // add to results r[i] = m } // return result return v31Vector(r), nil } // // Unmarshal CVSS 3.1 vector from JSON string. // func (me *v31Vector) UnmarshalJSON(b []byte) error { // // decode string, check for error // var s string // if err := json.Unmarshal(b, &s); err != nil { // return err // } // // // parse vector, check for error // r, err := newV31Vector(s) // if err != nil { // return err // } // // // save result, return success // *me = r // return nil // } var v31VecRe = regexp.MustCompile( "\\ACVSS:3\\.1(?:/(?:" + strings.Join([]string { "(?:AV:[NALP])", "(?:AC:[LH])", "(?:PR:[NLH])", "(?:UI:[NR])", "(?:S:[UC])", "(?:C:[HLN])", "(?:I:[HLN])", "(?:A:[HLN])", "(?:E:[XHFPU])", "(?:RL:[XUWTO])", "(?:RC:[XCRU])", "(?:CR:[XHML])", "(?:IR:[XHML])", "(?:AR:[XHML])", "(?:MAV:[XNALP])", "(?:MAC:[XLH])", "(?:MPR:[XNLH])", "(?:MUI:[XNR])", "(?:MS:[XUC])", "(?:MC:[XNLH])", "(?:MI:[XNLH])", "(?:MA:[XNLH])", }, "|") + "))+\\z", ) // Is the given string a CVSSv3.1 vector string? func isV31VectorString(s string) bool { return (len(s) > len(v31Prefix)) && (s[:len(v31Prefix)] == v31Prefix) && v31VecRe.MatchString(s) }