| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package sarif defines Static Analysis Results Interchange Format |
| // (SARIF) types supported by govulncheck. |
| // |
| // The implementation covers the subset of the specification available |
| // at https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=sarif. |
| // |
| // The sarif encoding models govulncheck findings as Results. Each |
| // Result encodes findings for a unique OSV entry at the most precise |
| // detected level only. CodeFlows summarize call stacks, similar to govulncheck |
| // textual output, while Stacks contain call stack information verbatim. |
| // |
| // The result Levels are defined by the govulncheck.ScanLevel and the most |
| // precise level at which the finding was detected. Result error is produced |
| // when the finding level matches the user desired level of scan precision; |
| // all other finding levels are then classified as progressively weaker. |
| // For instance, if the user specified symbol scan level and govulncheck |
| // detected a use of a vulnerable symbol, then the Result will have error |
| // Level. If the symbol was not used but its package was imported, then the |
| // Result Level is warning, and so on. |
| // |
| // Each Result is attached to the first line of the go.mod file. Other |
| // ArtifactLocations are paths relative to their enclosing modules. |
| // Similar to JSON output format, this makes govulncheck sarif locations |
| // portable. |
| // |
| // The relative paths in PhysicalLocations also come with a URIBaseID offset. |
| // Paths for the source module analyzed, the Go standard library, and third-party |
| // dependencies are relative to %SRCROOT%, %GOROOT%, and %GOMODCACHE% offsets, |
| // resp. We note that the URIBaseID offsets are not explicitly defined in |
| // the sarif output. It is the clients responsibility to set them to resolve |
| // paths at their local machines. |
| // |
| // All paths use "/" delimiter for portability. |
| // |
| // Properties field of a Tool.Driver is a govulncheck.Config used for the |
| // invocation of govulncheck producing the Results. Properties field of |
| // a Rule contains information on CVE and GHSA aliases for the corresponding |
| // rule OSV. Clients can use this information to, say, supress and filter |
| // vulnerabilities. |
| // |
| // Please see the definition of types below for more information. |
| package sarif |
| |
| import "golang.org/x/vuln/internal/govulncheck" |
| |
| // Log is the top-level SARIF object encoded in UTF-8. |
| type Log struct { |
| // Version should always be "2.1.0" |
| Version string `json:"version,omitempty"` |
| |
| // Schema should always be "https://json.schemastore.org/sarif-2.1.0.json" |
| Schema string `json:"$schema,omitempty"` |
| |
| // Runs describes executions of static analysis tools. For govulncheck, |
| // there will be only one run object. |
| Runs []Run `json:"runs,omitempty"` |
| } |
| |
| // Run summarizes results of a single invocation of a static analysis tool, |
| // in this case govulncheck. |
| type Run struct { |
| Tool Tool `json:"tool,omitempty"` |
| // Results contain govulncheck findings. There should be exactly one |
| // Result per a detected use of an OSV. |
| Results []Result `json:"results,omitempty"` |
| } |
| |
| // Tool captures information about govulncheck analysis that was run. |
| type Tool struct { |
| Driver Driver `json:"driver,omitempty"` |
| } |
| |
| // Driver provides details about the govulncheck binary being executed. |
| type Driver struct { |
| // Name is "govulncheck" |
| Name string `json:"name,omitempty"` |
| // Version is the govulncheck version |
| Version string `json:"semanticVersion,omitempty"` |
| // InformationURI points to the description of govulncheck tool |
| InformationURI string `json:"informationUri,omitempty"` |
| // Properties are govulncheck run metadata, such as vuln db, Go version, etc. |
| Properties govulncheck.Config `json:"properties,omitempty"` |
| |
| Rules []Rule `json:"rules,omitempty"` |
| } |
| |
| // Rule corresponds to the static analysis rule/analyzer that |
| // produces findings. For govulncheck, rules are OSVs. |
| type Rule struct { |
| // ID is OSV.ID |
| ID string `json:"id,omitempty"` |
| ShortDescription Description `json:"shortDescription,omitempty"` |
| FullDescription Description `json:"fullDescription,omitempty"` |
| Help Description `json:"help,omitempty"` |
| HelpURI string `json:"helpUri,omitempty"` |
| // Properties contain OSV.Aliases (CVEs and GHSAs) as tags. |
| // Consumers of govulncheck SARIF can use these tags to filter |
| // results. |
| Properties RuleTags `json:"properties,omitempty"` |
| } |
| |
| // RuleTags defines properties.tags. |
| type RuleTags struct { |
| Tags []string `json:"tags,omitempty"` |
| } |
| |
| // Description is a text in its raw or markdown form. |
| type Description struct { |
| Text string `json:"text,omitempty"` |
| Markdown string `json:"markdown,omitempty"` |
| } |
| |
| // Result is a set of govulncheck findings for an OSV. For call stack |
| // mode, it will contain call stacks for the OSV. There is exactly |
| // one Result per detected OSV. Only findings at the most precise |
| // detected level appear in the Result. For instance, if there are |
| // symbol findings for an OSV, those findings will be in the Result, |
| // but not the package and module level findings for the same OSV. |
| type Result struct { |
| // RuleID is the Rule.ID/OSV producing the finding. |
| RuleID string `json:"ruleId,omitempty"` |
| // Level is one of "error", "warning", and "note". |
| Level string `json:"level,omitempty"` |
| // Message explains the overall findings. |
| Message Description `json:"message,omitempty"` |
| // Locations to which the findings are associated. Always |
| // a single location pointing to the first line of the go.mod |
| // file. The path to the file is "go.mod". |
| Locations []Location `json:"locations,omitempty"` |
| // CodeFlows summarize call stacks produced by govulncheck. |
| CodeFlows []CodeFlow `json:"codeFlows,omitempty"` |
| // Stacks encode call stacks produced by govulncheck. |
| Stacks []Stack `json:"stacks,omitempty"` |
| } |
| |
| // CodeFlow summarizes a detected offending flow of information in terms of |
| // code locations. More precisely, it can contain several related information |
| // flows, keeping them together. In govulncheck, those can be all call stacks |
| // for, say, a particular symbol or package. |
| type CodeFlow struct { |
| // ThreadFlows is effectively a set of related information flows. |
| ThreadFlows []ThreadFlow `json:"threadFlows,omitempty"` |
| Message Description `json:"message,omitempty"` |
| } |
| |
| // ThreadFlow encodes an information flow as a sequence of locations. |
| // For govulncheck, it can encode a call stack. |
| type ThreadFlow struct { |
| Locations []ThreadFlowLocation `json:"locations,omitempty"` |
| } |
| |
| type ThreadFlowLocation struct { |
| // Module is module information in the form <module-path>@<version>. |
| // <version> can be empty when the module version is not known as |
| // with, say, the source module analyzed. |
| Module string `json:"module,omitempty"` |
| // Location also contains a Message field. |
| Location Location `json:"location,omitempty"` |
| } |
| |
| // Stack is a sequence of frames and can encode a govulncheck call stack. |
| type Stack struct { |
| Message Description `json:"message,omitempty"` |
| Frames []Frame `json:"frames,omitempty"` |
| } |
| |
| // Frame is effectively a module location. It can also contain thread and |
| // parameter info, but those are not needed for govulncheck. |
| type Frame struct { |
| // Module is module information in the form <module-path>@<version>. |
| // <version> can be empty when the module version is not known as |
| // with, say, the source module analyzed. |
| Module string `json:"module,omitempty"` |
| Location Location `json:"location,omitempty"` |
| } |
| |
| // Location is currently a physical location annotated with a message. |
| type Location struct { |
| PhysicalLocation PhysicalLocation `json:"physicalLocation,omitempty"` |
| Message Description `json:"message,omitempty"` |
| } |
| |
| type PhysicalLocation struct { |
| ArtifactLocation ArtifactLocation `json:"artifactLocation,omitempty"` |
| Region Region `json:"region,omitempty"` |
| } |
| |
| const ( |
| SrcRootID = "%SRCROOT%" |
| GoRootID = "%GOROOT%" |
| GoModCacheID = "%GOMODCACHE%" |
| ) |
| |
| // ArtifactLocation is a path to an offending file. |
| type ArtifactLocation struct { |
| // URI is a path relative to URIBaseID. |
| URI string `json:"uri,omitempty"` |
| // URIBaseID is offset for URI, one of %SRCROOT%, %GOROOT%, |
| // and %GOMODCACHE%. |
| URIBaseID string `json:"uriBaseId,omitempty"` |
| } |
| |
| // Region is a target region within a file. |
| type Region struct { |
| StartLine int `json:"startLine,omitempty"` |
| StartColumn int `json:"startColumn,omitempty"` |
| EndLine int `json:"endLine,omitempty"` |
| EndColumn int `json:"endColumn,omitempty"` |
| } |