blob: 40676a0ae488bd8ad77852cc2937b18b755e4c8c [file] [log] [blame] [view]
# Vulnerability Report Format & Style Guide
The Go security team uses an internal YAML format to create vulnerability
reports, which are automatically converted to OSV JSON and served to the
vulnerability database at [vuln.go.dev](https://vuln.go.dev).
The YAML format is subject to change without warning and should not be
relied on by external tools. (See [go.dev/security/vuln/database](https://go.dev/security/vuln/database) for information on the public Go Vulnerability
database API and the OSV schema.)
This page documents the fields of the internal YAML file format.
## `id`
type `string`
**required**
The unique Go identifier assigned to this report.
This is automatically assigned via `vulnreport create`. It should be of
the form `GO-YYYY-NNNN` where `YYYY` is the year the report was created,
and `NNNN` is the x/vulndb issue tracker number associated with the report.
## `modules`
type `[]module`
**required**
Information on each Go module affected by the vulnerability.
### `module.module`
type `string`
**required**
The module path of the vulnerable module.
Use `"std"` for vulnerabilities in the standard library.
Use `"cmd"` for vulnerabilities in the Go tools (`cmd/...`).
### `module.versions`
type `[]version`
The version ranges in which the package is vulnerable.
If omitted, it is assumed that _every_ version of the module is
vulnerable.
Versions must be SemVer 2.0.0 versions, with no "v" or "go" prefix.
Version ranges must not overlap.
Don't expend effort finding the first `introduced` version unless
it's obvious.
The version ranges in announcements, CVE text, GHSAs, and so forth are
frequently wrong. Always verify the fixed version from the repository history.
If the vulnerability is fixed in multiple minor versions, define sorted,
non-overlapping version ranges thats describe the affected revisions.
For example, for a fix in 1.17.2, 1.18.4, and 1.19.0:
```yaml
- fixed: 1.17.2
- introduced: 1.18.0
fixed: 1.18.4
```
Note that we don't need to mention 1.19.0 in the version ranges, since it
comes after 1.18.4.
#### `version.introduced`
type `string`
The version at which the vulnerability was introduced.
If this field is omitted, it is assumed that every version, from the
initial commit, up to the `fixed` version is vulnerable.
#### `version.fixed`
type `string`
The version at which the vulnerability was fixed.
If this field is omitted, it is assumed that every version since the
`introduced` version is vulnerable.
### `module.non_go_versions`
type `string`
(Optional - used only in special cases, usually for binary reports.)
The non-Go version range(s) at which the package is vulnerable.
A non-Go version range can be used to specify versions used by
module maintainers that do not conform to [Go's module
version conventions](https://go.dev/doc/modules/version-numbers).
An example is data/reports/GO-2024-2539.yaml, whose vulnerable versions
are listed as:
```yaml
versions:
- fixed: 1.1.2-0.20230830170046-f4cf4c6de017
non_go_versions:
- fixed: 4.0.0-rc2
vulnerable_at: 1.1.2-0.20230829214939-57856e474934
```
The [GHSA](https://github.com/advisories/GHSA-4fp6-574p-fc35) for this report
lists a fixed version, `4.0.0-rc2`, which is not known to the module proxy.
To encode this, we list that version as a "non-Go" version, and put the
pseudo-version corresponding to the fix commit in the regular `versions` section.
### `module.vulnerable_at`
type `string`
The version at which the vulnerable symbols were obtained. Ideally, this
is the version just prior to the fix.
In many cases, this can be inferred automatically via `vulnreport fix`.
### `module.vulnerable_at_requires`
type `[]string`
List of module@version to require when performing static analysis.
It is rare that we need to specify this.
Example from [GO-2021-0072](../data/reports/GO-2021-0072.yaml):
```yaml
vulnerable_at_requires:
- github.com/Sirupsen/logrus@v1.0.6
```
### `module.packages`
type `[]package`
**required**
Information on each package affected by the vulnerability.
Include every importable package containing a root vulnerable symbol.
If `"internal/foo".F` is vulnerable and `"foo".F` calls it, only include
the innermost (internal) package.
If a vulnerability occurs in multiple major versions of a module,
include an entry for each major version.
#### `package.package`
type `string`
**required**
The import path of the vulnerable package.
#### `package.symbols`
type `[]string`
The symbols affected by this vulnerability.
If included, only programs which use these symbols will be marked as
vulnerable. If omitted, any program which imports this module will be
marked vulnerable.
These should be the symbols initially detected or identified in the CVE
or other source.
#### `package.derived_symbols`
type `[]string`
Derived symbols that are calculated from `symbols`,
such as by static analysis tools like `govulncheck`.
This is generated automatically by the `vulnreport fix` command.
Don't edit this field manually.
Potentially, the set of derived symbols can differ with the module
version. We don't attempt to capture that level of detail. Most of the
values of `derived_symbols` as of this writing were obtained from a
module version that was just prior to the version that the report
listed as fixed.
#### `package.skip_fix`
type `string`
A text justification for why static analysis should not be performed
on this package (perhaps because it causes an error). It is rare
that we need to specify this.
## `summary`
type `string`
**required**
A short (<=100 characters) textual description of the vulnerability,
usually of the form "PROBLEM in MODULE(s)", e.g:
`summary: "Man-in-the-middle attack in golang.org/x/crypto/ssh`.
To allow for easy visual differentiation, each report must have a unique
summary.
## `description`
type `string`
**required** if first-party.
Optional for third-party when there is an advisory link.
A textual description of the vulnerability and its impact. Should be
wrapped to 80 columns. Does not use Markdown formatting.
The first paragraph should be a short, succinct description of the
nature and impact of the vulnerability, ideally one line. Assume
the person reading this knows what the vulnerable package does.
Use additional paragraphs to describe the issue in more detail as
necessary.
Use the present tense: "This is vulnerable" rather than "this was
vulnerable".
This field may be omitted for third-party reports that have an
external canonical advisory linked in the references section.
## `published`
type `time.Time`
(Handled automatically, do not edit manually)
Date the report was added to the vulnerability database.
This is normally determined from the git repository history, and
does not need to be set in the report YAML except when the first
commit of the report YAML doesn't match the publication date.
Older reports moved from a previous location have this set.
## `last_modified`
type `time.Time`
(Handled automatically, do not edit manually)
Last time the report was changed. This is normally determined from
the repository history, and does not need to be set in the report
YAML.
## `cves`
type `[]string`
The Common Vulnerabilities and Exposures (CVE) ID(s) for the
vulnerability.
## `ghsas`
type `[]string`
The GitHub Security Advisory (GHSA) IDs for the vulnerability.
## `credits`
type `[]string`
The name(s) of the person/organization that discovered/reported the
vulnerability.
This should be filled in for Go project reports (standard library,
golang.org/x, etc.). Use the text from the golang-announce email
when available.
For third-party reports, if `vulnreport create` finds CVE or GHSA metadata, use
that. Also, look for a "Credits" heading on the GHSA report linked from the
GitHub issue. Otherwise, it's okay to leave this blank.
## `references`
type `[]reference`
Links to further information about the vulnerability.
Include a `fix` link to the fix pull request, Gerrit code review, or commit.
No need to link both the PR and the commit.
Prefer to link to the PR or code review rather than the commit.
Don't include links to CVEs and GHSAs just because they exist.
(That's what the cve/ghsa fields are for.)
DO include an `advisory` link to an authoritative *first-party*
advisory when one exists.
If the first-party advisory is a GHSA, then link to that.
If the first-party advisory is a CVE, then link to the CVE page on
nvd.nist.gov/vuln.
Include a `report` link to a first-party bug or issue when one exists.
Don't include links to random third-party issue trackers (e.g.,
Debian announcements). CVEs often contain a bunch of random links
of dubious value; be aggressive in pruning these out.
The internal representation of a `Reference` is a struct with `Type`
and `URL` fields. For convenience, the YAML representation is a
single-element map from type to URL. For example:
```yaml
references:
- fix: https://go.dev/cl/25010
- report: https://go.dev/issue/16405
```
### `reference.type`
type `string`
The type of reference, as in the
[OSV references field](https://ossf.github.io/osv-schema/#references-field).
OSV types are upper-case, but the type in the YAML should be lower case.
Types we use:
* `ADVISORY`: A link to an authoritative, first-party advisory.
* `ARTICLE`: An article or blog post about the vulnerability.
* `REPORT`: A bug or issue tracker link.
* `FIX`: A link to the PR/CL which fixes the vulnerability.
* `PACKAGE`: The home page for the package. (We usually do not include this.)
* `EVIDENCE`: A demonstration of the vulnerability. (We usually do not include this.)
* `WEB`: Anything that doesn't fit into the above.
### `reference.url`
type `string`
The URL of the reference.
## `cve_metadata`
type `cve_metadata`
Information used to generate a CVE record based on this report. This
should be populated only if the Go CNA assigned the CVE for this report.
### `cve_metadata.id`
type `string`
The CVE ID assigned by the Go CNA for this report.
### `cve_metadata.cwe`
type `string`
The [CWE](https://cwe.mitre.org/index.html) most closely associated
with this vulnerability, of the form "CWE-XXX: Description".
### `cve_metadata.description`
type `string`
The description of the vulnerability to use in the CVE record. If blank,
the top-level description is used.
This was used to preserve existing descriptions. For new reports, this
does not need to be set.
### `cve_metadata.references`
type `[]string`
References that should be published in the CVE record, but not the OSV
record. This is used to preserve references added by the CVE program,
and is rarely used.
Example: [GO-2022-0476](../data/reports/GO-2022-0476.yaml)
## `notes`
type `[]string`
Optional, freeform notes about the report. This field is ignored when creating
OSV and CVE records, so it does not need to be polished.
It can be used to document decisions made when creating the report,
outstanding issues, or anything else worth mentioning.
## `source`
**required** for new reports
Auto-generated metadata indicating the source of this report.
### `source.id`
type `string`
The CVE or GHSA ID of the vulnerability used to generate this report.
For original reports, this is "go-security-team".
### `source.created`
type `string`
The timestamp at which the report was generated based on the indicated source.
## `review_status`
type `string`
**required**
The status of this report, either UNREVIEWED or REVIEWED.
Unreviewed reports are generally auto-generated or nearly so. Their
details have not been verified and no attempt has been made to determine
packages or symbols. These reports must have an advisory link.
Reviewed reports are reports for which we have made a good faith effort
to determine correct affected versions, packages, and symbols. (In some
cases it is not possible to determine all of these, which is OK). Descriptions
are optional, except for reports affecting the Go standard library, toolchain
or x/ repos.
## `excluded`
type `string`
A reason the report is excluded from the database.
When a CVE or GHSA is evaluated and determined to be out of scope
for the Go Vulnerability Database, the reason for excluding it may
be recorded in a report. This report should include a value for the
`excluded` enum (this field) as well as a list of CVEs and/or GHSAs.
Excluded reports are placed in the `excluded/` directory.
Valid values are:
* `NOT_GO_CODE`: The vulnerability is not in a Go package, and
cannot affect any Go packages. (For example, a vulnerability in
a C++ library.)
* `NOT_IMPORTABLE`: The vulnerability occurs in package `main`,
an `internal/` package only imported by package `main`, or some
other location which can never be imported by another module.
* `EFFECTIVELY_PRIVATE`: While the vulnerability occurs in a Go
package which can be imported by another module, the package is
not intended for external use and is not likely to ever be imported
outside the module in which it is defined.
* `DEPENDENT_VULNERABILITY`: This vulnerability is a subset of another
vulnerability in the database. For example, if package A contains a
vulnerability, package B depends on package A, and there are separate
CVEs for packages A and B, we might mark the report for B as a dependent
vulnerability entirely superseded by the report for A.
* `NOT_A_VULNERABILITY`: While a CVE or GHSA has been assigned,
there is no known vulnerability associated with it.
* `LEGACY_FALSE_POSITIVE`: This is the label used for excluded reports
that were marked as false positive in the initial triage process (in 2020),
before we stored excluded reports in the repo. This label must not be used
for any new reports.
## Example Reports
* Standard library: [GO-2021-0067](../data/reports/GO-2021-0067.yaml)
* Toolchain: [GO-2021-0068](../data/reports/GO-2021-0068.yaml)
* x/ repo: [GO-2020-0012](../data/reports/GO-2020-0012.yaml)
* Third-party: [GO-2021-0075](../data/reports/GO-2021-0075.yaml)
* Excluded:[GO-2022-0559](../data/excluded/GO-2022-0559.yaml)