diff --git a/github/github.go b/github/github.go index 9287eb5..bf0774d 100644 --- a/github/github.go +++ b/github/github.go @@ -60,6 +60,7 @@ const ( PushEvent Event = "push" ReleaseEvent Event = "release" RepositoryEvent Event = "repository" + SecurityAdvisoryEvent Event = "security_advisory" StatusEvent Event = "status" TeamEvent Event = "team" TeamAddEvent Event = "team_add" @@ -288,6 +289,10 @@ func (hook Webhook) Parse(r *http.Request, events ...Event) (interface{}, error) var pl RepositoryPayload err = json.Unmarshal([]byte(payload), &pl) return pl, err + case SecurityAdvisoryEvent: + var pl SecurityAdvisoryPayload + err = json.Unmarshal([]byte(payload), &pl) + return pl, err case StatusEvent: var pl StatusPayload err = json.Unmarshal([]byte(payload), &pl) diff --git a/github/github_test.go b/github/github_test.go index 5ffa98a..b484444 100644 --- a/github/github_test.go +++ b/github/github_test.go @@ -453,6 +453,16 @@ func TestWebhooks(t *testing.T) { "X-Hub-Signature": []string{"sha1=df442a8af41edd2d42ccdd997938d1d111b0f94e"}, }, }, + { + name: "SecurityAdvisoryEvent", + event: SecurityAdvisoryEvent, + typ: SecurityAdvisoryPayload{}, + filename: "../testdata/github/security-advisory.json", + headers: http.Header{ + "X-Github-Event": []string{"security_advisory"}, + "X-Hub-Signature": []string{"sha1=6a71f24fa69f55469843a91dc3a5c3e29714a565"}, + }, + }, { name: "StatusEvent", event: StatusEvent, diff --git a/github/payload.go b/github/payload.go index 664ff51..d125773 100644 --- a/github/payload.go +++ b/github/payload.go @@ -4,18 +4,18 @@ import "time" // CheckRunPayload contains the information for GitHub's check_run hook event type CheckRunPayload struct { - Action string `json:"action"` + Action string `json:"action"` CheckRun struct { - ID int64 `json:"id"` - Name string `json:"name"` - HeadSHA string `json:"head_sha"` - Status string `json:"status"` - Conclusion string `json:"conclusion"` - URL string `json:"url"` - HtmlURL string `json:"html_url"` - StarterAt time.Time `json:"started_at"` - CompletedAt time.Time `json:"completed_at"` - Output struct { + ID int64 `json:"id"` + Name string `json:"name"` + HeadSHA string `json:"head_sha"` + Status string `json:"status"` + Conclusion string `json:"conclusion"` + URL string `json:"url"` + HtmlURL string `json:"html_url"` + StarterAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + Output struct { Title string `json:"title"` Summary string `json:"summary"` Text string `json:"text"` @@ -32,8 +32,8 @@ type CheckRunPayload struct { Before string `json:"before"` After string `json:"after"` PullRequests []PullRequestPayload `json:"pull_requests"` - App struct { - ID int64 `json:"id"` + App struct { + ID int64 `json:"id"` Owner struct { Login string `json:"login"` ID int64 `json:"id"` @@ -53,18 +53,18 @@ type CheckRunPayload struct { Type string `json:"type"` SiteAdmin bool `json:"site_admin"` } `json:"owner"` - Name string `json:"name"` - Description string `json:"description"` - ExternalURL string `json:"external_url"` - HtmlURL string `json:"html_url"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + Name string `json:"name"` + Description string `json:"description"` + ExternalURL string `json:"external_url"` + HtmlURL string `json:"html_url"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } `json:"app"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } `json:"check_suite"` App struct { - ID int64 `json:"id"` + ID int64 `json:"id"` Owner struct { Login string `json:"login"` ID int64 `json:"id"` @@ -84,12 +84,12 @@ type CheckRunPayload struct { Type string `json:"type"` SiteAdmin bool `json:"site_admin"` } `json:"owner"` - Name string `json:"name"` - Description string `json:"description"` - ExternalURL string `json:"external_url"` - HtmlURL string `json:"html_url"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + Name string `json:"name"` + Description string `json:"description"` + ExternalURL string `json:"external_url"` + HtmlURL string `json:"html_url"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } `json:"app"` PullRequests []PullRequestPayload `json:"pull_requests"` } `json:"check_run"` @@ -203,7 +203,7 @@ type CheckRunPayload struct { // CheckSuitePayload contains the information for GitHub's check_suite hook event type CheckSuitePayload struct { - Action string `json:"action"` + Action string `json:"action"` CheckSuite struct { ID int64 `json:"id"` HeadBranch string `json:"head_branch"` @@ -214,8 +214,8 @@ type CheckSuitePayload struct { Before string `json:"before"` After string `json:"after"` PullRequests []PullRequestPayload `json:"pull_requests"` - App struct { - ID int64 `json:"id"` + App struct { + ID int64 `json:"id"` Owner struct { Login string `json:"login"` ID int64 `json:"id"` @@ -235,23 +235,23 @@ type CheckSuitePayload struct { Type string `json:"type"` SiteAdmin bool `json:"site_admin"` } `json:"owner"` - Name string `json:"name"` - Description string `json:"description"` - ExternalURL string `json:"external_url"` - HtmlURL string `json:"html_url"` - CreatedAt string `json:"created_at"` - UpdatedAt string `json:"updated_at"` + Name string `json:"name"` + Description string `json:"description"` + ExternalURL string `json:"external_url"` + HtmlURL string `json:"html_url"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` } `json:"app"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` LatestCheckRunsCount int64 `json:"latest_check_runs_count"` CheckRunsURL string `json:"check_runs_url"` - HeadCommit struct { + HeadCommit struct { ID string `json:"id"` TreeID string `json:"tree_id"` Message string `json:"message"` Timestamp time.Time `json:"timestamp"` - Author struct { + Author struct { Name string `json:"name"` Email string `json:"email"` } `json:"author"` @@ -5077,6 +5077,38 @@ type RepositoryPayload struct { } `json:"sender"` } +// SecurityAdvisoryPayload contains the information for GitHub's security_advisory hook event. +type SecurityAdvisoryPayload struct { + Action string `json:"action"` + SecurityAdvisory struct { + GHSAID string `json:"ghsa_id"` + Summary string `json:"summary"` + Description string `json:"description"` + Severity string `json:"string"` + Identifiers []struct { + Value string `json:"value"` + Type string `json:"type"` + } `json:"identifiers"` + References []struct { + URL string `json:"url"` + } `json:"references"` + PublishedAt time.Time `json:"published_at"` + UpdatedAt time.Time `json:"updated_at"` + WithdrawnAt *time.Time `json:"withdrawn_at"` + Vulnerabilities []struct { + Package struct { + Ecosystem string `json:"ecosystem"` + Name string `json:"name"` + } + Severity string `json:"severity"` + VulnerableVersionRange string `json:"vulnerable_version_range"` + FirstPatchedVersion *struct { + Identifier string `json:"identifier"` + } `json:"first_patched_version"` + } `json:"vulnerabilities"` + } `json:"security_advisory"` +} + // StatusPayload contains the information for GitHub's status hook event type StatusPayload struct { ID int64 `json:"id"` diff --git a/testdata/github/security-advisory.json b/testdata/github/security-advisory.json new file mode 100644 index 0000000..48797d4 --- /dev/null +++ b/testdata/github/security-advisory.json @@ -0,0 +1,51 @@ +{ + "action": "published", + "security_advisory": { + "ghsa_id": "GHSA-rf4j-j272-fj86", + "summary": "Moderate severity vulnerability that affects django", + "description": "django.contrib.auth.forms.AuthenticationForm in Django 2.0 before 2.0.2, and 1.11.8 and 1.11.9, allows remote attackers to obtain potentially sensitive information by leveraging data exposure from the confirm_login_allowed() method, as demonstrated by discovering whether a user account is inactive.", + "severity": "moderate", + "identifiers": [ + { + "value": "GHSA-rf4j-j272-fj86", + "type": "GHSA" + }, + { + "value": "CVE-2018-6188", + "type": "CVE" + } + ], + "references": [ + { + "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-6188" + } + ], + "published_at": "2018-10-03T21:13:54Z", + "updated_at": "2018-10-03T21:13:54Z", + "withdrawn_at": null, + "vulnerabilities": [ + { + "package": { + "ecosystem": "pip", + "name": "django" + }, + "severity": "moderate", + "vulnerable_version_range": ">= 2.0.0, < 2.0.2", + "first_patched_version": { + "identifier": "2.0.2" + } + }, + { + "package": { + "ecosystem": "pip", + "name": "django" + }, + "severity": "moderate", + "vulnerable_version_range": ">= 1.11.8, < 1.11.10", + "first_patched_version": { + "identifier": "1.11.10" + } + } + ] + } +}