Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/mozilla/tls-observatory v0.0.0-20250923143331-eef96233227e
github.com/onsi/ginkgo/v2 v2.27.2
github.com/onsi/gomega v1.38.2
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.43.0
golang.org/x/text v0.30.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
Expand Down Expand Up @@ -340,6 +342,8 @@ github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWN
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
Expand Down
82 changes: 77 additions & 5 deletions report/sarif/sarif_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
package sarif_test

import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"net/http"
"regexp"
"sync"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/santhosh-tekuri/jsonschema/v6"

"github.com/securego/gosec/v2"
"github.com/securego/gosec/v2/issue"
"github.com/securego/gosec/v2/report/sarif"
)

var (
sarifSchemaOnce sync.Once
sarifSchema *jsonschema.Schema
sarifSchemaErr error
sarifSchemaClient = &http.Client{Timeout: 30 * time.Second}
)

func validateSarifSchema(report *sarif.Report) error {
GinkgoHelper()
sarifSchemaOnce.Do(func() {
resp, err := sarifSchemaClient.Get(sarif.Schema)
if err != nil {
sarifSchemaErr = fmt.Errorf("fetch sarif schema: %w", err)
return
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
sarifSchemaErr = fmt.Errorf("fetch sarif schema: unexpected status %s", resp.Status)
return
}

schema, err := jsonschema.UnmarshalJSON(resp.Body)
if err != nil {
sarifSchemaErr = fmt.Errorf("error unmarshaling schema: %w", err)
return
}

compiler := jsonschema.NewCompiler()
if err := compiler.AddResource(sarif.Schema, schema); err != nil {
sarifSchemaErr = fmt.Errorf("compile sarif schema: %w", err)
return
}

sarifSchema, sarifSchemaErr = compiler.Compile(sarif.Schema)
})

if sarifSchemaErr != nil {
return sarifSchemaErr
}

// Marshal the report to JSON
v, err := json.MarshalIndent(report, "", "\t")
if err != nil {
return err
}

// Unmarshal into any for schema validation
data, err := jsonschema.UnmarshalJSON(bufio.NewReader(bytes.NewReader(v)))
if err != nil {
return err
}

return sarifSchema.Validate(data)
}

var _ = Describe("Sarif Formatter", func() {
BeforeEach(func() {
})
Expand All @@ -23,6 +86,9 @@ var _ = Describe("Sarif Formatter", func() {
result := buf.String()
Expect(err).ShouldNot(HaveOccurred())
Expect(result).To(ContainSubstring("\"results\": ["))
sarifReport, err := sarif.GenerateReport([]string{}, reportInfo)
Expect(err).ShouldNot(HaveOccurred())
Expect(validateSarifSchema(sarifReport)).To(Succeed())
})

It("sarif formatted report should contain the suppressed results", func() {
Expand All @@ -40,7 +106,7 @@ var _ = Describe("Sarif Formatter", func() {
Cwe: cwe,
Suppressions: []issue.SuppressionInfo{
{
Kind: "kind",
Kind: "inSource",
Justification: "justification",
},
},
Expand All @@ -57,6 +123,9 @@ var _ = Describe("Sarif Formatter", func() {

hasSuppressions, _ := regexp.MatchString(`"suppressions": \[(\s*){`, result)
Expect(hasSuppressions).To(BeTrue())
sarifReport, err := sarif.GenerateReport([]string{}, reportInfo)
Expect(err).ShouldNot(HaveOccurred())
Expect(validateSarifSchema(sarifReport)).To(Succeed())
})
It("sarif formatted report should contain the formatted one line code snippet", func() {
ruleID := "G101"
Expand All @@ -75,7 +144,7 @@ var _ = Describe("Sarif Formatter", func() {
Cwe: cwe,
Suppressions: []issue.SuppressionInfo{
{
Kind: "kind",
Kind: "inSource",
Justification: "justification",
},
},
Expand All @@ -84,6 +153,7 @@ var _ = Describe("Sarif Formatter", func() {
sarifReport, err := sarif.GenerateReport([]string{}, reportInfo)
Expect(err).ShouldNot(HaveOccurred())
Expect(sarifReport.Runs[0].Results[0].Locations[0].PhysicalLocation.Region.Snippet.Text).Should(Equal(expectedCode))
Expect(validateSarifSchema(sarifReport)).To(Succeed())
})
It("sarif formatted report should contain the formatted multiple line code snippet", func() {
ruleID := "G101"
Expand All @@ -102,7 +172,7 @@ var _ = Describe("Sarif Formatter", func() {
Cwe: cwe,
Suppressions: []issue.SuppressionInfo{
{
Kind: "kind",
Kind: "inSource",
Justification: "justification",
},
},
Expand All @@ -111,6 +181,7 @@ var _ = Describe("Sarif Formatter", func() {
sarifReport, err := sarif.GenerateReport([]string{}, reportInfo)
Expect(err).ShouldNot(HaveOccurred())
Expect(sarifReport.Runs[0].Results[0].Locations[0].PhysicalLocation.Region.Snippet.Text).Should(Equal(expectedCode))
Expect(validateSarifSchema(sarifReport)).To(Succeed())
})
It("sarif formatted report should have proper rule index", func() {
rules := []string{"G404", "G101", "G102", "G103"}
Expand All @@ -128,7 +199,7 @@ var _ = Describe("Sarif Formatter", func() {
Cwe: cwe,
Suppressions: []issue.SuppressionInfo{
{
Kind: "kind",
Kind: "inSource",
Justification: "justification",
},
},
Expand All @@ -150,7 +221,7 @@ var _ = Describe("Sarif Formatter", func() {
Cwe: cwe,
Suppressions: []issue.SuppressionInfo{
{
Kind: "kind",
Kind: "inSource",
Justification: "justification",
},
},
Expand All @@ -171,6 +242,7 @@ var _ = Describe("Sarif Formatter", func() {
driverRuleIndexes[rule.ID] = ruleIndex
}
Expect(resultRuleIndexes).Should(Equal(driverRuleIndexes))
Expect(validateSarifSchema(sarifReport)).To(Succeed())
})
})
})
Loading