-
Notifications
You must be signed in to change notification settings - Fork 505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add CVE Information to Release Notes #1441
Changes from all commits
d3fa4b7
15d64a3
2163900
181a262
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ import ( | |
"github.com/nozzle/throttler" | ||
"github.com/pkg/errors" | ||
"github.com/sirupsen/logrus" | ||
cvss "github.com/spiegel-im-spiegel/go-cvss/v3/metric" | ||
"gopkg.in/yaml.v2" | ||
|
||
"k8s.io/release/pkg/github" | ||
|
@@ -51,6 +52,9 @@ const ( | |
// maxParallelRequests is the maximum parallel requests we shall make to the | ||
// GitHub API | ||
maxParallelRequests = 10 | ||
|
||
// Regexp to check CVE IDs | ||
cveIDRegExp = `^CVE-\d{4}-\d+$` | ||
) | ||
|
||
type ( | ||
|
@@ -60,13 +64,15 @@ type ( | |
|
||
// CVEData Information of a linked CVE vulnerability | ||
type CVEData struct { | ||
ID string `json:"id"` | ||
Title string `json:"title"` | ||
Published string `json:"published"` | ||
Score float32 `json:"score"` | ||
Rating string `json:"rating"` | ||
LinkedPRs []int `json:"linkedPRs"` | ||
Description string `json:"description"` | ||
ID string `json:"id"` // CVE ID, eg CVE-2019-1010260 | ||
Title string `json:"title"` // Title of the vulnerability | ||
Description string `json:"description"` // Description text of the vulnerability | ||
TrackingIssue string `json:"issue"` // Link to the vulnerability tracking issue (url, optional) | ||
CVSSVector string `json:"vector"` // Full CVSS vector string, CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:H/A:H | ||
CVSSScore float32 `json:"score"` // Numeric CVSS score (eg 6.2) | ||
CVSSRating string `json:"rating"` // Severity bucket (eg Medium) | ||
CalcLink string // Link to the CVE calculator (automatic) | ||
LinkedPRs []int `json:"pullrequests"` // List of linked PRs (to remove them from the release notes doc) | ||
} | ||
|
||
const ( | ||
|
@@ -1085,3 +1091,61 @@ func (rn *ReleaseNote) ContentHash() (string, error) { | |
} | ||
return fmt.Sprintf("%x", h.Sum(nil)), nil | ||
} | ||
|
||
// Validate checks the data defined in a CVE map is complete and valid | ||
func (cve *CVEData) Validate() error { | ||
// Verify that rating is defined and a known string | ||
if cve.CVSSRating == "" { | ||
return errors.New("CVSS rating missing from CVE data") | ||
} | ||
|
||
// Check rating is a valid string | ||
if _, ok := map[string]bool{ | ||
"None": true, "Low": true, "Medium": true, "High": true, "Critical": true, | ||
}[cve.CVSSRating]; !ok { | ||
return errors.New("Invalid CVSS rating") | ||
} | ||
|
||
// Check vector string is not empty | ||
if cve.CVSSVector == "" { | ||
return errors.New("CVSS vector string missing from CVE data") | ||
} | ||
|
||
// Parse the vector string to make sure it is well formed | ||
bm, err := cvss.NewBase().Decode(cve.CVSSVector) | ||
if err != nil { | ||
return errors.Wrap(err, "parsing CVSS vector string") | ||
} | ||
cve.CalcLink = fmt.Sprintf( | ||
"https://www.first.org/cvss/calculator/%s#%s", bm.Ver.String(), cve.CVSSVector, | ||
) | ||
|
||
if cve.CVSSScore == 0 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should validate versus the known range of 0..10. |
||
return errors.New("CVSS score missing from CVE data") | ||
} | ||
if cve.CVSSScore < 0 || cve.CVSSScore > 10 { | ||
return errors.New("CVSS score pit of range, should be 0-10") | ||
} | ||
|
||
// Check that the CVE ID is not empty | ||
if cve.ID == "" { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this validate more that the id is of the expected form for a CVE? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ✔️ Added a basic regexp validation |
||
return errors.New("ID missing from CVE data") | ||
} | ||
|
||
// Verify that the CVE ID is well formed | ||
cvsre := regexp.MustCompile(cveIDRegExp) | ||
if !cvsre.MatchString(cve.ID) { | ||
return errors.New("CVS ID is not well formed") | ||
} | ||
|
||
// Title and description must not be empty | ||
if cve.Title == "" { | ||
return errors.New("Title missing from CVE data") | ||
} | ||
|
||
if cve.Description == "" { | ||
return errors.New("CVE description missing from CVE data") | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can see the new TrackingIssue perhaps being empty, but can't tell if that's intended. A couple changes to consider depending on if it is required or not
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've modified it to make the field optional. Once it is in use we can decide if we enforce it. |
||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a library that can validate the form is the expected CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:H/A:H sort of form?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm trying this one and seems to do the job just fine: https://github.com/spiegel-im-spiegel/go-cvss