Skip to content

Commit

Permalink
internal/sarif: add stacks
Browse files Browse the repository at this point in the history
Location information will be added later.

Updates golang/go#61347

Change-Id: Ibd6a2f7f6dfd4ac6e333c5de070b76a68e8e462c
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/550735
TryBot-Result: Gopher Robot <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Maceo Thompson <[email protected]>
Run-TryBot: Zvonimir Pavlinovic <[email protected]>
  • Loading branch information
zpavlinovic committed Mar 25, 2024
1 parent cb159d5 commit 3c9f048
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 4 deletions.
133 changes: 130 additions & 3 deletions cmd/govulncheck/testdata/testfiles/source-call/source_call_sarif.ct
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,148 @@ $ govulncheck -C ${moddir}/vuln -format sarif ./...
"level": "error",
"message": {
"text": "Your code calls vulnerable functions in 1 package (github.com/tidwall/gjson)."
}
},
"stacks": [
{
"message": {
"text": "A call stack for vulnerable function github.com/tidwall/gjson.Result.ForEach"
},
"frames": [
{
"module": "golang.org/vuln",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
}
]
}
]
},
{
"ruleId": "GO-2021-0113",
"level": "error",
"message": {
"text": "Your code calls vulnerable functions in 1 package (golang.org/x/text/language)."
}
},
"stacks": [
{
"message": {
"text": "A call stack for vulnerable function golang.org/x/text/language.Parse"
},
"frames": [
{
"module": "golang.org/vuln",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "golang.org/x/text",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
}
]
}
]
},
{
"ruleId": "GO-2021-0265",
"level": "error",
"message": {
"text": "Your code calls vulnerable functions in 1 package (github.com/tidwall/gjson)."
}
},
"stacks": [
{
"message": {
"text": "A call stack for vulnerable function github.com/tidwall/gjson.Result.Get"
},
"frames": [
{
"module": "golang.org/vuln",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
},
{
"module": "github.com/tidwall/gjson",
"location": {
"physicalLocation": {
"artifactLocation": {},
"region": {}
},
"message": {}
}
}
]
}
]
},
{
"ruleId": "GO-2022-0969",
Expand Down
44 changes: 43 additions & 1 deletion internal/sarif/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ func results(h *handler) []Result {
RuleID: fs[0].OSV,
Level: level(fs[0], h.cfg),
Message: Description{Text: resultMessage(fs, h.cfg)},
// TODO: add location, code flows, and stacks
// TODO: add location and code flows
Stacks: stacks(fs),
}
results = append(results, res)
}
Expand Down Expand Up @@ -236,3 +237,44 @@ func level(f *govulncheck.Finding, cfg *govulncheck.Config) string {
return errorLevel
}
}

func stacks(fs []*govulncheck.Finding) []Stack {
if fs[0].Trace[0].Function == "" { // not call level findings
return nil
}

var stacks []Stack
for _, f := range fs {
stacks = append(stacks, stack(f))
}
// Sort stacks for deterministic output. We sort by message
// which is effectively sorting by full symbol name. The
// performance should not be an issue here.
sort.SliceStable(stacks, func(i, j int) bool { return stacks[i].Message.Text < stacks[j].Message.Text })
return stacks
}

// stack transforms call stack in f to a sarif stack.
func stack(f *govulncheck.Finding) Stack {
trace := f.Trace

var frames []Frame
for i := len(trace) - 1; i >= 0; i-- { // vulnerable symbol is at the top frame
frame := trace[i]
frames = append(frames, Frame{
Module: frame.Module,
// TODO: add location
})
}

vuln := trace[0]
vulnSym := vuln.Function
if vuln.Receiver != "" {
vulnSym = vuln.Receiver + "." + vulnSym
}
vulnSym = vuln.Package + "." + vulnSym
return Stack{
Frames: frames,
Message: Description{Text: fmt.Sprintf("A call stack for vulnerable function %s", vulnSym)},
}
}

0 comments on commit 3c9f048

Please sign in to comment.