Repository: google/go-github
Pull request #2993 (2023-11-17 16:47:20)

Implement global security advisories API
- implement global security advisories API

Fixes: https://github.com/google/go-github/issues/2851


cc @gmlewis 

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
Attention: `3 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`78c6de0`)](https://app.codecov.io/gh/google/go-github/commit/78c6de0b72ac4f5205eaa31a19c57fb18a510400?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) 97.93% compared to head [(`788c597`)](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) 97.91%.

| [Files](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Patch % | Lines |
|---|---|---|
| [github/security\_advisories.go](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3NlY3VyaXR5X2Fkdmlzb3JpZXMuZ28=) | 89.28% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #2993      +/-   ##
==========================================
- Coverage   97.93%   97.91%   -0.02%     
==========================================
  Files         150      150              
  Lines       12952    12980      +28     
==========================================
+ Hits        12685    12710      +25     
- Misses        190      192       +2     
- Partials       77       78       +1     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/google/go-github/pull/2993?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google).

cpanato: @gmlewis thanks so much for your review and sorry about the force-push
cpanato: @gmlewis Thanks again for your review, PTAL

Patch:
diff --git a/github/event_types.go b/github/event_types.go
index 6ff1eb84..327fc561 100644
--- a/github/event_types.go
+++ b/github/event_types.go
@@ -388,11 +388,12 @@ type GollumEvent struct {
 // EditChange represents the changes when an issue, pull request, comment,
 // or repository has been edited.
 type EditChange struct {
-	Title *EditTitle `json:"title,omitempty"`
-	Body  *EditBody  `json:"body,omitempty"`
-	Base  *EditBase  `json:"base,omitempty"`
-	Repo  *EditRepo  `json:"repository,omitempty"`
-	Owner *EditOwner `json:"owner,omitempty"`
+	Title         *EditTitle         `json:"title,omitempty"`
+	Body          *EditBody          `json:"body,omitempty"`
+	Base          *EditBase          `json:"base,omitempty"`
+	Repo          *EditRepo          `json:"repository,omitempty"`
+	Owner         *EditOwner         `json:"owner,omitempty"`
+	DefaultBranch *EditDefaultBranch `json:"default_branch,omitempty"`
 }
 
 // EditTitle represents a pull-request title change.
@@ -442,6 +443,11 @@ type EditSHA struct {
 	From *string `json:"from,omitempty"`
 }
 
+// EditDefaultBranch represents a change of repository's default branch name.
+type EditDefaultBranch struct {
+	From *string `json:"from,omitempty"`
+}
+
 // ProjectChange represents the changes when a project has been edited.
 type ProjectChange struct {
 	Name *ProjectName `json:"name,omitempty"`
diff --git a/github/github-accessors.go b/github/github-accessors.go
index 536ce5a8..bccc3b4e 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -4990,6 +4990,22 @@ func (c *CredentialAuthorization) GetTokenLastEight() string {
 	return *c.TokenLastEight
 }
 
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (c *Credit) GetType() string {
+	if c == nil || c.Type == nil {
+		return ""
+	}
+	return *c.Type
+}
+
+// GetUser returns the User field.
+func (c *Credit) GetUser() *User {
+	if c == nil {
+		return nil
+	}
+	return c.User
+}
+
 // GetDefaultValue returns the DefaultValue field if it's non-nil, zero value otherwise.
 func (c *CustomProperty) GetDefaultValue() string {
 	if c == nil || c.DefaultValue == nil {
@@ -6678,6 +6694,14 @@ func (e *EditChange) GetBody() *EditBody {
 	return e.Body
 }
 
+// GetDefaultBranch returns the DefaultBranch field.
+func (e *EditChange) GetDefaultBranch() *EditDefaultBranch {
+	if e == nil {
+		return nil
+	}
+	return e.DefaultBranch
+}
+
 // GetOwner returns the Owner field.
 func (e *EditChange) GetOwner() *EditOwner {
 	if e == nil {
@@ -6702,6 +6726,14 @@ func (e *EditChange) GetTitle() *EditTitle {
 	return e.Title
 }
 
+// GetFrom returns the From field if it's non-nil, zero value otherwise.
+func (e *EditDefaultBranch) GetFrom() string {
+	if e == nil || e.From == nil {
+		return ""
+	}
+	return *e.From
+}
+
 // GetOwnerInfo returns the OwnerInfo field.
 func (e *EditOwner) GetOwnerInfo() *OwnerInfo {
 	if e == nil {
@@ -7798,6 +7830,78 @@ func (g *GitObject) GetURL() string {
 	return *g.URL
 }
 
+// GetGithubReviewedAt returns the GithubReviewedAt field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetGithubReviewedAt() Timestamp {
+	if g == nil || g.GithubReviewedAt == nil {
+		return Timestamp{}
+	}
+	return *g.GithubReviewedAt
+}
+
+// GetID returns the ID field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetID() int64 {
+	if g == nil || g.ID == nil {
+		return 0
+	}
+	return *g.ID
+}
+
+// GetNVDPublishedAt returns the NVDPublishedAt field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetNVDPublishedAt() Timestamp {
+	if g == nil || g.NVDPublishedAt == nil {
+		return Timestamp{}
+	}
+	return *g.NVDPublishedAt
+}
+
+// GetRepositoryAdvisoryURL returns the RepositoryAdvisoryURL field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetRepositoryAdvisoryURL() string {
+	if g == nil || g.RepositoryAdvisoryURL == nil {
+		return ""
+	}
+	return *g.RepositoryAdvisoryURL
+}
+
+// GetSourceCodeLocation returns the SourceCodeLocation field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetSourceCodeLocation() string {
+	if g == nil || g.SourceCodeLocation == nil {
+		return ""
+	}
+	return *g.SourceCodeLocation
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityAdvisory) GetType() string {
+	if g == nil || g.Type == nil {
+		return ""
+	}
+	return *g.Type
+}
+
+// GetFirstPatchedVersion returns the FirstPatchedVersion field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityVulnerability) GetFirstPatchedVersion() string {
+	if g == nil || g.FirstPatchedVersion == nil {
+		return ""
+	}
+	return *g.FirstPatchedVersion
+}
+
+// GetPackage returns the Package field.
+func (g *GlobalSecurityVulnerability) GetPackage() *VulnerabilityPackage {
+	if g == nil {
+		return nil
+	}
+	return g.Package
+}
+
+// GetVulnerableVersionRange returns the VulnerableVersionRange field if it's non-nil, zero value otherwise.
+func (g *GlobalSecurityVulnerability) GetVulnerableVersionRange() string {
+	if g == nil || g.VulnerableVersionRange == nil {
+		return ""
+	}
+	return *g.VulnerableVersionRange
+}
+
 // GetInstallation returns the Installation field.
 func (g *GollumEvent) GetInstallation() *Installation {
 	if g == nil {
@@ -9390,6 +9494,14 @@ func (i *Issue) GetCreatedAt() Timestamp {
 	return *i.CreatedAt
 }
 
+// GetDraft returns the Draft field if it's non-nil, zero value otherwise.
+func (i *Issue) GetDraft() bool {
+	if i == nil || i.Draft == nil {
+		return false
+	}
+	return *i.Draft
+}
+
 // GetEventsURL returns the EventsURL field if it's non-nil, zero value otherwise.
 func (i *Issue) GetEventsURL() string {
 	if i == nil || i.EventsURL == nil {
@@ -10766,6 +10878,86 @@ func (l *ListExternalGroupsOptions) GetDisplayName() string {
 	return *l.DisplayName
 }
 
+// GetAffects returns the Affects field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetAffects() string {
+	if l == nil || l.Affects == nil {
+		return ""
+	}
+	return *l.Affects
+}
+
+// GetCVEID returns the CVEID field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetCVEID() string {
+	if l == nil || l.CVEID == nil {
+		return ""
+	}
+	return *l.CVEID
+}
+
+// GetEcosystem returns the Ecosystem field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetEcosystem() string {
+	if l == nil || l.Ecosystem == nil {
+		return ""
+	}
+	return *l.Ecosystem
+}
+
+// GetGHSAID returns the GHSAID field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetGHSAID() string {
+	if l == nil || l.GHSAID == nil {
+		return ""
+	}
+	return *l.GHSAID
+}
+
+// GetIsWithdrawn returns the IsWithdrawn field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetIsWithdrawn() bool {
+	if l == nil || l.IsWithdrawn == nil {
+		return false
+	}
+	return *l.IsWithdrawn
+}
+
+// GetModified returns the Modified field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetModified() string {
+	if l == nil || l.Modified == nil {
+		return ""
+	}
+	return *l.Modified
+}
+
+// GetPublished returns the Published field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetPublished() string {
+	if l == nil || l.Published == nil {
+		return ""
+	}
+	return *l.Published
+}
+
+// GetSeverity returns the Severity field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetSeverity() string {
+	if l == nil || l.Severity == nil {
+		return ""
+	}
+	return *l.Severity
+}
+
+// GetType returns the Type field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetType() string {
+	if l == nil || l.Type == nil {
+		return ""
+	}
+	return *l.Type
+}
+
+// GetUpdated returns the Updated field if it's non-nil, zero value otherwise.
+func (l *ListGlobalSecurityAdvisoriesOptions) GetUpdated() string {
+	if l == nil || l.Updated == nil {
+		return ""
+	}
+	return *l.Updated
+}
+
 // GetTotalCount returns the TotalCount field if it's non-nil, zero value otherwise.
 func (l *ListOrganizations) GetTotalCount() int {
 	if l == nil || l.TotalCount == nil {
diff --git a/github/github.go b/github/github.go
index 9c1bf084..c2706b0f 100644
--- a/github/github.go
+++ b/github/github.go
@@ -1133,7 +1133,7 @@ func (ae *AcceptedError) Is(target error) bool {
 }
 
 // AbuseRateLimitError occurs when GitHub returns 403 Forbidden response with the
-// "documentation_url" field value equal to "https://docs.github.com/rest/overview/resources-in-the-rest-api#secondary-rate-limits".
+// "documentation_url" field value equal to "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits".
 type AbuseRateLimitError struct {
 	Response *http.Response // HTTP response that caused this error
 	Message  string         `json:"message"` // error message
@@ -1259,7 +1259,7 @@ func CheckResponse(r *http.Response) error {
 		}
 	case r.StatusCode == http.StatusForbidden &&
 		(strings.HasSuffix(errorResponse.DocumentationURL, "#abuse-rate-limits") ||
-			strings.HasSuffix(errorResponse.DocumentationURL, "#secondary-rate-limits")):
+			strings.HasSuffix(errorResponse.DocumentationURL, "secondary-rate-limits")):
 		abuseRateLimitError := &AbuseRateLimitError{
 			Response: errorResponse.Response,
 			Message:  errorResponse.Message,
diff --git a/github/issues.go b/github/issues.go
index 1db99328..1c07fef8 100644
--- a/github/issues.go
+++ b/github/issues.go
@@ -54,6 +54,7 @@ type Issue struct {
 	Reactions         *Reactions        `json:"reactions,omitempty"`
 	Assignees         []*User           `json:"assignees,omitempty"`
 	NodeID            *string           `json:"node_id,omitempty"`
+	Draft             *bool             `json:"draft,omitempty"`
 
 	// TextMatches is only populated from search results that request text matches
 	// See: search.go and https://docs.github.com/rest/search/#text-match-metadata
diff --git a/github/security_advisories.go b/github/security_advisories.go
index 66e7dba1..63526374 100644
--- a/github/security_advisories.go
+++ b/github/security_advisories.go
@@ -47,6 +47,81 @@ type ListRepositorySecurityAdvisoriesOptions struct {
 	State string `url:"state,omitempty"`
 }
 
+// ListGlobalSecurityAdvisoriesOptions specifies the optional parameters to list the global security advisories.
+type ListGlobalSecurityAdvisoriesOptions struct {
+	ListCursorOptions
+
+	// If specified, only advisories with this GHSA (GitHub Security Advisory) identifier will be returned.
+	GHSAID *string `url:"ghsa_id,omitempty"`
+
+	// If specified, only advisories of this type will be returned.
+	// By default, a request with no other parameters defined will only return reviewed advisories that are not malware.
+	// Default: reviewed
+	// Can be one of: reviewed, malware, unreviewed
+	Type *string `url:"type,omitempty"`
+
+	// If specified, only advisories with this CVE (Common Vulnerabilities and Exposures) identifier will be returned.
+	CVEID *string `url:"cve_id,omitempty"`
+
+	// If specified, only advisories for these ecosystems will be returned.
+	// Can be one of: actions, composer, erlang, go, maven, npm, nuget, other, pip, pub, rubygems, rust
+	Ecosystem *string `url:"ecosystem,omitempty"`
+
+	// If specified, only advisories with these severities will be returned.
+	// Can be one of: unknown, low, medium, high, critical
+	Severity *string `url:"severity,omitempty"`
+
+	// If specified, only advisories with these Common Weakness Enumerations (CWEs) will be returned.
+	// Example: cwes=79,284,22 or cwes[]=79&cwes[]=284&cwes[]=22
+	CWEs []string `url:"cwes,omitempty"`
+
+	// Whether to only return advisories that have been withdrawn.
+	IsWithdrawn *bool `url:"is_withdrawn,omitempty"`
+
+	// If specified, only return advisories that affect any of package or package@version.
+	// A maximum of 1000 packages can be specified. If the query parameter causes
+	// the URL to exceed the maximum URL length supported by your client, you must specify fewer packages.
+	// Example: affects=package1,package2@1.0.0,package3@^2.0.0 or affects[]=package1&affects[]=package2@1.0.0
+	Affects *string `url:"affects,omitempty"`
+
+	// If specified, only return advisories that were published on a date or date range.
+	Published *string `url:"published,omitempty"`
+
+	// If specified, only return advisories that were updated on a date or date range.
+	Updated *string `url:"updated,omitempty"`
+
+	// If specified, only show advisories that were updated or published on a date or date range.
+	Modified *string `url:"modified,omitempty"`
+}
+
+// GlobalSecurityAdvisory represents the global security advisory object response.
+type GlobalSecurityAdvisory struct {
+	SecurityAdvisory
+	ID                    *int64                         `json:"id,omitempty"`
+	RepositoryAdvisoryURL *string                        `json:"repository_advisory_url,omitempty"`
+	Type                  *string                        `json:"type,omitempty"`
+	SourceCodeLocation    *string                        `json:"source_code_location,omitempty"`
+	References            []string                       `json:"references,omitempty"`
+	Vulnerabilities       []*GlobalSecurityVulnerability `json:"vulnerabilities,omitempty"`
+	GithubReviewedAt      *Timestamp                     `json:"github_reviewed_at,omitempty"`
+	NVDPublishedAt        *Timestamp                     `json:"nvd_published_at,omitempty"`
+	Credits               []*Credit                      `json:"credits,omitempty"`
+}
+
+// GlobalSecurityVulnerability represents a vulnerability for a global security advisory.
+type GlobalSecurityVulnerability struct {
+	Package                *VulnerabilityPackage `json:"package,omitempty"`
+	FirstPatchedVersion    *string               `json:"first_patched_version,omitempty"`
+	VulnerableVersionRange *string               `json:"vulnerable_version_range,omitempty"`
+	VulnerableFunctions    []string              `json:"vulnerable_functions,omitempty"`
+}
+
+// Credit represents the credit object for a global security advisory.
+type Credit struct {
+	User *User   `json:"user,omitempty"`
+	Type *string `json:"type,omitempty"`
+}
+
 // RequestCVE requests a Common Vulnerabilities and Exposures (CVE) for a repository security advisory.
 // The ghsaID is the GitHub Security Advisory identifier of the advisory.
 //
@@ -124,3 +199,50 @@ func (s *SecurityAdvisoriesService) ListRepositorySecurityAdvisories(ctx context
 
 	return advisories, resp, nil
 }
+
+// ListGlobalSecurityAdvisories lists all global security advisories.
+//
+// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#list-global-security-advisories
+//
+//meta:operation GET /advisories
+func (s *SecurityAdvisoriesService) ListGlobalSecurityAdvisories(ctx context.Context, opts *ListGlobalSecurityAdvisoriesOptions) ([]*GlobalSecurityAdvisory, *Response, error) {
+	url := "advisories"
+	url, err := addOptions(url, opts)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var advisories []*GlobalSecurityAdvisory
+	resp, err := s.client.Do(ctx, req, &advisories)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return advisories, resp, nil
+}
+
+// GetGlobalSecurityAdvisories gets a global security advisory using its GitHub Security Advisory (GHSA) identifier.
+//
+// GitHub API docs: https://docs.github.com/rest/security-advisories/global-advisories#get-a-global-security-advisory
+//
+//meta:operation GET /advisories/{ghsa_id}
+func (s *SecurityAdvisoriesService) GetGlobalSecurityAdvisories(ctx context.Context, ghsaID string) (*GlobalSecurityAdvisory, *Response, error) {
+	url := fmt.Sprintf("advisories/%s", ghsaID)
+	req, err := s.client.NewRequest("GET", url, nil)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var advisory *GlobalSecurityAdvisory
+	resp, err := s.client.Do(ctx, req, &advisory)
+	if err != nil {
+		return nil, resp, err
+	}
+
+	return advisory, resp, nil
+}
diff --git a/scrape/go.mod b/scrape/go.mod
index 95c03591..05f87b6b 100644
--- a/scrape/go.mod
+++ b/scrape/go.mod
@@ -7,5 +7,5 @@ require (
 	github.com/google/go-cmp v0.6.0
 	github.com/google/go-github/v56 v56.0.0
 	github.com/xlzd/gotp v0.1.0
-	golang.org/x/net v0.18.0
+	golang.org/x/net v0.19.0
 )
diff --git a/scrape/go.sum b/scrape/go.sum
index 78483af2..907678b1 100644
--- a/scrape/go.sum
+++ b/scrape/go.sum
@@ -15,7 +15,7 @@ github.com/xlzd/gotp v0.1.0/go.mod h1:ndLJ3JKzi3xLmUProq4LLxCuECL93dG9WASNLpHz8q
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
+golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -25,8 +25,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
-golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
+golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
+golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -38,12 +38,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
+golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index abe96ecf..84d104f1 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -5899,6 +5899,23 @@ func TestCredentialAuthorization_GetTokenLastEight(tt *testing.T) {
 	c.GetTokenLastEight()
 }
 
+func TestCredit_GetType(tt *testing.T) {
+	var zeroValue string
+	c := &Credit{Type: &zeroValue}
+	c.GetType()
+	c = &Credit{}
+	c.GetType()
+	c = nil
+	c.GetType()
+}
+
+func TestCredit_GetUser(tt *testing.T) {
+	c := &Credit{}
+	c.GetUser()
+	c = nil
+	c.GetUser()
+}
+
 func TestCustomProperty_GetDefaultValue(tt *testing.T) {
 	var zeroValue string
 	c := &CustomProperty{DefaultValue: &zeroValue}
@@ -7826,6 +7843,13 @@ func TestEditChange_GetBody(tt *testing.T) {
 	e.GetBody()
 }
 
+func TestEditChange_GetDefaultBranch(tt *testing.T) {
+	e := &EditChange{}
+	e.GetDefaultBranch()
+	e = nil
+	e.GetDefaultBranch()
+}
+
 func TestEditChange_GetOwner(tt *testing.T) {
 	e := &EditChange{}
 	e.GetOwner()
@@ -7847,6 +7871,16 @@ func TestEditChange_GetTitle(tt *testing.T) {
 	e.GetTitle()
 }
 
+func TestEditDefaultBranch_GetFrom(tt *testing.T) {
+	var zeroValue string
+	e := &EditDefaultBranch{From: &zeroValue}
+	e.GetFrom()
+	e = &EditDefaultBranch{}
+	e.GetFrom()
+	e = nil
+	e.GetFrom()
+}
+
 func TestEditOwner_GetOwnerInfo(tt *testing.T) {
 	e := &EditOwner{}
 	e.GetOwnerInfo()
@@ -9142,6 +9176,93 @@ func TestGitObject_GetURL(tt *testing.T) {
 	g.GetURL()
 }
 
+func TestGlobalSecurityAdvisory_GetGithubReviewedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	g := &GlobalSecurityAdvisory{GithubReviewedAt: &zeroValue}
+	g.GetGithubReviewedAt()
+	g = &GlobalSecurityAdvisory{}
+	g.GetGithubReviewedAt()
+	g = nil
+	g.GetGithubReviewedAt()
+}
+
+func TestGlobalSecurityAdvisory_GetID(tt *testing.T) {
+	var zeroValue int64
+	g := &GlobalSecurityAdvisory{ID: &zeroValue}
+	g.GetID()
+	g = &GlobalSecurityAdvisory{}
+	g.GetID()
+	g = nil
+	g.GetID()
+}
+
+func TestGlobalSecurityAdvisory_GetNVDPublishedAt(tt *testing.T) {
+	var zeroValue Timestamp
+	g := &GlobalSecurityAdvisory{NVDPublishedAt: &zeroValue}
+	g.GetNVDPublishedAt()
+	g = &GlobalSecurityAdvisory{}
+	g.GetNVDPublishedAt()
+	g = nil
+	g.GetNVDPublishedAt()
+}
+
+func TestGlobalSecurityAdvisory_GetRepositoryAdvisoryURL(tt *testing.T) {
+	var zeroValue string
+	g := &GlobalSecurityAdvisory{RepositoryAdvisoryURL: &zeroValue}
+	g.GetRepositoryAdvisoryURL()
+	g = &GlobalSecurityAdvisory{}
+	g.GetRepositoryAdvisoryURL()
+	g = nil
+	g.GetRepositoryAdvisoryURL()
+}
+
+func TestGlobalSecurityAdvisory_GetSourceCodeLocation(tt *testing.T) {
+	var zeroValue string
+	g := &GlobalSecurityAdvisory{SourceCodeLocation: &zeroValue}
+	g.GetSourceCodeLocation()
+	g = &GlobalSecurityAdvisory{}
+	g.GetSourceCodeLocation()
+	g = nil
+	g.GetSourceCodeLocation()
+}
+
+func TestGlobalSecurityAdvisory_GetType(tt *testing.T) {
+	var zeroValue string
+	g := &GlobalSecurityAdvisory{Type: &zeroValue}
+	g.GetType()
+	g = &GlobalSecurityAdvisory{}
+	g.GetType()
+	g = nil
+	g.GetType()
+}
+
+func TestGlobalSecurityVulnerability_GetFirstPatchedVersion(tt *testing.T) {
+	var zeroValue string
+	g := &GlobalSecurityVulnerability{FirstPatchedVersion: &zeroValue}
+	g.GetFirstPatchedVersion()
+	g = &GlobalSecurityVulnerability{}
+	g.GetFirstPatchedVersion()
+	g = nil
+	g.GetFirstPatchedVersion()
+}
+
+func TestGlobalSecurityVulnerability_GetPackage(tt *testing.T) {
+	g := &GlobalSecurityVulnerability{}
+	g.GetPackage()
+	g = nil
+	g.GetPackage()
+}
+
+func TestGlobalSecurityVulnerability_GetVulnerableVersionRange(tt *testing.T) {
+	var zeroValue string
+	g := &GlobalSecurityVulnerability{VulnerableVersionRange: &zeroValue}
+	g.GetVulnerableVersionRange()
+	g = &GlobalSecurityVulnerability{}
+	g.GetVulnerableVersionRange()
+	g = nil
+	g.GetVulnerableVersionRange()
+}
+
 func TestGollumEvent_GetInstallation(tt *testing.T) {
 	g := &GollumEvent{}
 	g.GetInstallation()
@@ -11024,6 +11145,16 @@ func TestIssue_GetCreatedAt(tt *testing.T) {
 	i.GetCreatedAt()
 }
 
+func TestIssue_GetDraft(tt *testing.T) {
+	var zeroValue bool
+	i := &Issue{Draft: &zeroValue}
+	i.GetDraft()
+	i = &Issue{}
+	i.GetDraft()
+	i = nil
+	i.GetDraft()
+}
+
 func TestIssue_GetEventsURL(tt *testing.T) {
 	var zeroValue string
 	i := &Issue{EventsURL: &zeroValue}
@@ -12612,6 +12743,106 @@ func TestListExternalGroupsOptions_GetDisplayName(tt *testing.T) {
 	l.GetDisplayName()
 }
 
+func TestListGlobalSecurityAdvisoriesOptions_GetAffects(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Affects: &zeroValue}
+	l.GetAffects()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetAffects()
+	l = nil
+	l.GetAffects()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetCVEID(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{CVEID: &zeroValue}
+	l.GetCVEID()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetCVEID()
+	l = nil
+	l.GetCVEID()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetEcosystem(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Ecosystem: &zeroValue}
+	l.GetEcosystem()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetEcosystem()
+	l = nil
+	l.GetEcosystem()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetGHSAID(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{GHSAID: &zeroValue}
+	l.GetGHSAID()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetGHSAID()
+	l = nil
+	l.GetGHSAID()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetIsWithdrawn(tt *testing.T) {
+	var zeroValue bool
+	l := &ListGlobalSecurityAdvisoriesOptions{IsWithdrawn: &zeroValue}
+	l.GetIsWithdrawn()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetIsWithdrawn()
+	l = nil
+	l.GetIsWithdrawn()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetModified(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Modified: &zeroValue}
+	l.GetModified()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetModified()
+	l = nil
+	l.GetModified()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetPublished(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Published: &zeroValue}
+	l.GetPublished()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetPublished()
+	l = nil
+	l.GetPublished()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetSeverity(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Severity: &zeroValue}
+	l.GetSeverity()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetSeverity()
+	l = nil
+	l.GetSeverity()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetType(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Type: &zeroValue}
+	l.GetType()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetType()
+	l = nil
+	l.GetType()
+}
+
+func TestListGlobalSecurityAdvisoriesOptions_GetUpdated(tt *testing.T) {
+	var zeroValue string
+	l := &ListGlobalSecurityAdvisoriesOptions{Updated: &zeroValue}
+	l.GetUpdated()
+	l = &ListGlobalSecurityAdvisoriesOptions{}
+	l.GetUpdated()
+	l = nil
+	l.GetUpdated()
+}
+
 func TestListOrganizations_GetTotalCount(tt *testing.T) {
 	var zeroValue int
 	l := &ListOrganizations{TotalCount: &zeroValue}
diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go
index 1dfd878f..a9b719c5 100644
--- a/github/github-stringify_test.go
+++ b/github/github-stringify_test.go
@@ -768,9 +768,10 @@ func TestIssue_String(t *testing.T) {
 		Repository:        &Repository{},
 		Reactions:         &Reactions{},
 		NodeID:            String(""),
+		Draft:             Bool(false),
 		ActiveLockReason:  String(""),
 	}
-	want := `github.Issue{ID:0, Number:0, State:"", StateReason:"", Locked:false, Title:"", Body:"", AuthorAssociation:"", User:github.User{}, Assignee:github.User{}, Comments:0, ClosedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, ClosedBy:github.User{}, URL:"", HTMLURL:"", CommentsURL:"", EventsURL:"", LabelsURL:"", RepositoryURL:"", Milestone:github.Milestone{}, PullRequestLinks:github.PullRequestLinks{}, Repository:github.Repository{}, Reactions:github.Reactions{}, NodeID:"", ActiveLockReason:""}`
+	want := `github.Issue{ID:0, Number:0, State:"", StateReason:"", Locked:false, Title:"", Body:"", AuthorAssociation:"", User:github.User{}, Assignee:github.User{}, Comments:0, ClosedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, ClosedBy:github.User{}, URL:"", HTMLURL:"", CommentsURL:"", EventsURL:"", LabelsURL:"", RepositoryURL:"", Milestone:github.Milestone{}, PullRequestLinks:github.PullRequestLinks{}, Repository:github.Repository{}, Reactions:github.Reactions{}, NodeID:"", Draft:false, ActiveLockReason:""}`
 	if got := v.String(); got != want {
 		t.Errorf("Issue.String = %v, want %v", got, want)
 	}
diff --git a/github/security_advisories_test.go b/github/security_advisories_test.go
index 5476ef61..918e3e05 100644
--- a/github/security_advisories_test.go
+++ b/github/security_advisories_test.go
@@ -7,9 +7,11 @@ package github
 
 import (
 	"context"
+	"fmt"
 	"net/http"
 	"strings"
 	"testing"
+	"time"
 
 	"github.com/google/go-cmp/cmp"
 )
@@ -315,3 +317,379 @@ func TestSecurityAdvisoriesService_ListRepositorySecurityAdvisories(t *testing.T
 		return resp, err
 	})
 }
+
+func TestListGlobalSecurityAdvisories(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/advisories", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+		testFormValues(t, r, values{"cve_id": "CVE-xoxo-1234"})
+
+		fmt.Fprint(w, `[{
+				"id": 1,
+				"ghsa_id": "GHSA-xoxo-1234-xoxo",
+				"cve_id": "CVE-xoxo-1234",
+				"url": "https://api.github.com/advisories/GHSA-xoxo-1234-xoxo",
+				"html_url": "https://github.com/advisories/GHSA-xoxo-1234-xoxo",
+				"repository_advisory_url": "https://api.github.com/repos/project/a-package/security-advisories/GHSA-xoxo-1234-xoxo",
+				"summary": "Heartbleed security advisory",
+				"description": "This bug allows an attacker to read portions of the affected server’s memory, potentially disclosing sensitive information.",
+				"type": "reviewed",
+				"severity": "high",
+				"source_code_location": "https://github.com/project/a-package",
+				"identifiers": [
+					{
+						"type": "GHSA",
+						"value": "GHSA-xoxo-1234-xoxo"
+					},
+					{
+						"type": "CVE",
+						"value": "CVE-xoxo-1234"
+					}
+				],
+				"references": ["https://nvd.nist.gov/vuln/detail/CVE-xoxo-1234"],
+				"published_at": "1996-06-20T00:00:00Z",
+				"updated_at": "1996-06-20T00:00:00Z",
+				"github_reviewed_at": "1996-06-20T00:00:00Z",
+				"nvd_published_at": "1996-06-20T00:00:00Z",
+				"withdrawn_at": null,
+				"vulnerabilities": [
+					{
+						"package": {
+							"ecosystem": "npm",
+							"name": "a-package"
+						},
+						"first_patched_version": "1.0.3",
+						"vulnerable_version_range": "<=1.0.2",
+						"vulnerable_functions": ["a_function"]
+					}
+				],
+				"cvss": {
+					"vector_string": "CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H",
+					"score": 7.6
+				},
+				"cwes": [
+					{
+						"cwe_id": "CWE-400",
+						"name": "Uncontrolled Resource Consumption"
+					}
+				],
+				"credits": [
+					{
+						"user": {
+							"login": "user",
+							"id": 1,
+							"node_id": "12=",
+							"avatar_url": "a",
+							"gravatar_id": "",
+							"url": "a",
+							"html_url": "b",
+							"followers_url": "b",
+							"following_url": "c",
+							"gists_url": "d",
+							"starred_url": "e",
+							"subscriptions_url": "f",
+							"organizations_url": "g",
+							"repos_url": "h",
+							"events_url": "i",
+							"received_events_url": "j",
+							"type": "User",
+							"site_admin": false
+						},
+						"type": "analyst"
+					}
+				]
+			}
+		]`)
+	})
+
+	ctx := context.Background()
+	opts := &ListGlobalSecurityAdvisoriesOptions{CVEID: String("CVE-xoxo-1234")}
+
+	advisories, _, err := client.SecurityAdvisories.ListGlobalSecurityAdvisories(ctx, opts)
+	if err != nil {
+		t.Errorf("SecurityAdvisories.ListGlobalSecurityAdvisories returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := []*GlobalSecurityAdvisory{
+		{
+			ID: Int64(1),
+			SecurityAdvisory: SecurityAdvisory{
+				GHSAID:      String("GHSA-xoxo-1234-xoxo"),
+				CVEID:       String("CVE-xoxo-1234"),
+				URL:         String("https://api.github.com/advisories/GHSA-xoxo-1234-xoxo"),
+				HTMLURL:     String("https://github.com/advisories/GHSA-xoxo-1234-xoxo"),
+				Severity:    String("high"),
+				Summary:     String("Heartbleed security advisory"),
+				Description: String("This bug allows an attacker to read portions of the affected server’s memory, potentially disclosing sensitive information."),
+				Identifiers: []*AdvisoryIdentifier{
+					{
+						Type:  String("GHSA"),
+						Value: String("GHSA-xoxo-1234-xoxo"),
+					},
+					{
+						Type:  String("CVE"),
+						Value: String("CVE-xoxo-1234"),
+					},
+				},
+				PublishedAt: &date,
+				UpdatedAt:   &date,
+				WithdrawnAt: nil,
+				CVSS: &AdvisoryCVSS{
+					VectorString: String("CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H"),
+					Score:        Float64(7.6),
+				},
+				CWEs: []*AdvisoryCWEs{
+					{
+						CWEID: String("CWE-400"),
+						Name:  String("Uncontrolled Resource Consumption"),
+					},
+				},
+			},
+			References: []string{"https://nvd.nist.gov/vuln/detail/CVE-xoxo-1234"},
+			Vulnerabilities: []*GlobalSecurityVulnerability{
+				{
+					Package: &VulnerabilityPackage{
+						Ecosystem: String("npm"),
+						Name:      String("a-package"),
+					},
+					FirstPatchedVersion:    String("1.0.3"),
+					VulnerableVersionRange: String("<=1.0.2"),
+					VulnerableFunctions:    []string{"a_function"},
+				},
+			},
+			RepositoryAdvisoryURL: String("https://api.github.com/repos/project/a-package/security-advisories/GHSA-xoxo-1234-xoxo"),
+			Type:                  String("reviewed"),
+			SourceCodeLocation:    String("https://github.com/project/a-package"),
+			GithubReviewedAt:      &date,
+			NVDPublishedAt:        &date,
+			Credits: []*Credit{
+				{
+					User: &User{
+						Login:             String("user"),
+						ID:                Int64(1),
+						NodeID:            String("12="),
+						AvatarURL:         String("a"),
+						GravatarID:        String(""),
+						URL:               String("a"),
+						HTMLURL:           String("b"),
+						FollowersURL:      String("b"),
+						FollowingURL:      String("c"),
+						GistsURL:          String("d"),
+						StarredURL:        String("e"),
+						SubscriptionsURL:  String("f"),
+						OrganizationsURL:  String("g"),
+						ReposURL:          String("h"),
+						EventsURL:         String("i"),
+						ReceivedEventsURL: String("j"),
+						Type:              String("User"),
+						SiteAdmin:         Bool(false),
+					},
+					Type: String("analyst"),
+				},
+			},
+		},
+	}
+
+	if !cmp.Equal(advisories, want) {
+		t.Errorf("SecurityAdvisories.ListGlobalSecurityAdvisories %+v, want %+v", advisories, want)
+	}
+
+	const methodName = "ListGlobalSecurityAdvisories"
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		_, resp, err := client.SecurityAdvisories.ListGlobalSecurityAdvisories(ctx, nil)
+		return resp, err
+	})
+}
+
+func TestGetGlobalSecurityAdvisories(t *testing.T) {
+	client, mux, _, teardown := setup()
+	defer teardown()
+
+	mux.HandleFunc("/advisories/GHSA-xoxo-1234-xoxo", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, "GET")
+
+		fmt.Fprint(w, `{
+			"id": 1,
+			"ghsa_id": "GHSA-xoxo-1234-xoxo",
+			"cve_id": "CVE-xoxo-1234",
+			"url": "https://api.github.com/advisories/GHSA-xoxo-1234-xoxo",
+			"html_url": "https://github.com/advisories/GHSA-xoxo-1234-xoxo",
+			"repository_advisory_url": "https://api.github.com/repos/project/a-package/security-advisories/GHSA-xoxo-1234-xoxo",
+			"summary": "Heartbleed security advisory",
+			"description": "This bug allows an attacker to read portions of the affected server’s memory, potentially disclosing sensitive information.",
+			"type": "reviewed",
+			"severity": "high",
+			"source_code_location": "https://github.com/project/a-package",
+			"identifiers": [
+				{
+					"type": "GHSA",
+					"value": "GHSA-xoxo-1234-xoxo"
+				},
+				{
+					"type": "CVE",
+					"value": "CVE-xoxo-1234"
+				}
+			],
+			"references": ["https://nvd.nist.gov/vuln/detail/CVE-xoxo-1234"],
+			"published_at": "1996-06-20T00:00:00Z",
+			"updated_at": "1996-06-20T00:00:00Z",
+			"github_reviewed_at": "1996-06-20T00:00:00Z",
+			"nvd_published_at": "1996-06-20T00:00:00Z",
+			"withdrawn_at": null,
+			"vulnerabilities": [
+				{
+					"package": {
+						"ecosystem": "npm",
+						"name": "a-package"
+					},
+					"first_patched_version": "1.0.3",
+					"vulnerable_version_range": "<=1.0.2",
+					"vulnerable_functions": ["a_function"]
+				}
+			],
+			"cvss": {
+				"vector_string": "CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H",
+				"score": 7.6
+			},
+			"cwes": [
+				{
+					"cwe_id": "CWE-400",
+					"name": "Uncontrolled Resource Consumption"
+				}
+			],
+			"credits": [
+				{
+					"user": {
+						"login": "user",
+						"id": 1,
+						"node_id": "12=",
+						"avatar_url": "a",
+						"gravatar_id": "",
+						"url": "a",
+						"html_url": "b",
+						"followers_url": "b",
+						"following_url": "c",
+						"gists_url": "d",
+						"starred_url": "e",
+						"subscriptions_url": "f",
+						"organizations_url": "g",
+						"repos_url": "h",
+						"events_url": "i",
+						"received_events_url": "j",
+						"type": "User",
+						"site_admin": false
+					},
+					"type": "analyst"
+				}
+			]
+		}`)
+	})
+
+	ctx := context.Background()
+	advisory, _, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, "GHSA-xoxo-1234-xoxo")
+	if err != nil {
+		t.Errorf("SecurityAdvisories.GetGlobalSecurityAdvisories returned error: %v", err)
+	}
+
+	date := Timestamp{time.Date(1996, time.June, 20, 00, 00, 00, 0, time.UTC)}
+	want := &GlobalSecurityAdvisory{
+		ID: Int64(1),
+		SecurityAdvisory: SecurityAdvisory{
+			GHSAID:      String("GHSA-xoxo-1234-xoxo"),
+			CVEID:       String("CVE-xoxo-1234"),
+			URL:         String("https://api.github.com/advisories/GHSA-xoxo-1234-xoxo"),
+			HTMLURL:     String("https://github.com/advisories/GHSA-xoxo-1234-xoxo"),
+			Severity:    String("high"),
+			Summary:     String("Heartbleed security advisory"),
+			Description: String("This bug allows an attacker to read portions of the affected server’s memory, potentially disclosing sensitive information."),
+			Identifiers: []*AdvisoryIdentifier{
+				{
+					Type:  String("GHSA"),
+					Value: String("GHSA-xoxo-1234-xoxo"),
+				},
+				{
+					Type:  String("CVE"),
+					Value: String("CVE-xoxo-1234"),
+				},
+			},
+			PublishedAt: &date,
+			UpdatedAt:   &date,
+			WithdrawnAt: nil,
+			CVSS: &AdvisoryCVSS{
+				VectorString: String("CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:H/I:H/A:H"),
+				Score:        Float64(7.6),
+			},
+			CWEs: []*AdvisoryCWEs{
+				{
+					CWEID: String("CWE-400"),
+					Name:  String("Uncontrolled Resource Consumption"),
+				},
+			},
+		},
+		RepositoryAdvisoryURL: String("https://api.github.com/repos/project/a-package/security-advisories/GHSA-xoxo-1234-xoxo"),
+		Type:                  String("reviewed"),
+		SourceCodeLocation:    String("https://github.com/project/a-package"),
+		References:            []string{"https://nvd.nist.gov/vuln/detail/CVE-xoxo-1234"},
+		GithubReviewedAt:      &date,
+		NVDPublishedAt:        &date,
+
+		Vulnerabilities: []*GlobalSecurityVulnerability{
+			{
+				Package: &VulnerabilityPackage{
+					Ecosystem: String("npm"),
+					Name:      String("a-package"),
+				},
+				FirstPatchedVersion:    String("1.0.3"),
+				VulnerableVersionRange: String("<=1.0.2"),
+				VulnerableFunctions:    []string{"a_function"},
+			},
+		},
+		Credits: []*Credit{
+			{
+				User: &User{
+					Login:             String("user"),
+					ID:                Int64(1),
+					NodeID:            String("12="),
+					AvatarURL:         String("a"),
+					GravatarID:        String(""),
+					URL:               String("a"),
+					HTMLURL:           String("b"),
+					FollowersURL:      String("b"),
+					FollowingURL:      String("c"),
+					GistsURL:          String("d"),
+					StarredURL:        String("e"),
+					SubscriptionsURL:  String("f"),
+					OrganizationsURL:  String("g"),
+					ReposURL:          String("h"),
+					EventsURL:         String("i"),
+					ReceivedEventsURL: String("j"),
+					Type:              String("User"),
+					SiteAdmin:         Bool(false),
+				},
+				Type: String("analyst"),
+			},
+		},
+	}
+
+	if !cmp.Equal(advisory, want) {
+		t.Errorf("SecurityAdvisories.GetGlobalSecurityAdvisories %+v, want %+v", advisory, want)
+	}
+
+	const methodName = "GetGlobalSecurityAdvisories"
+
+	testBadOptions(t, methodName, func() (err error) {
+		_, _, err = client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, "CVE-\n-1234")
+		return err
+	})
+
+	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
+		got, resp, err := client.SecurityAdvisories.GetGlobalSecurityAdvisories(ctx, "e")
+		if got != nil {
+			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
+		}
+		return resp, err
+	})
+}