diff --git a/report/sarif/builder.go b/report/sarif/builder.go index 827a57b..cf72072 100644 --- a/report/sarif/builder.go +++ b/report/sarif/builder.go @@ -95,6 +95,18 @@ func NewResult(ruleID string, ruleIndex int, level Level, message string, suppre Text: autofix, // TODO: ensure this is plain text Markdown: autofix, }, + ArtifactChanges: []*ArtifactChange{ // TODO: this is a placeholder to pass validation. The values are not of use right now + { + ArtifactLocation: &ArtifactLocation{ + Description: NewMessage("unknown"), + }, + Replacements: []*Replacement{ + { + DeletedRegion: NewRegion(1, 1, 1, 1, "unknown"), + }, + }, + }, + }, }, } } diff --git a/report/sarif/common_test.go b/report/sarif/common_test.go new file mode 100644 index 0000000..5de9ce2 --- /dev/null +++ b/report/sarif/common_test.go @@ -0,0 +1,72 @@ +package sarif_test + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "net/http" + "sync" + "time" + + . "github.com/onsi/ginkgo/v2" + "github.com/santhosh-tekuri/jsonschema/v6" + + "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) +} diff --git a/report/sarif/sarif_test.go b/report/sarif/sarif_test.go index 39aba70..79be1f0 100644 --- a/report/sarif/sarif_test.go +++ b/report/sarif/sarif_test.go @@ -1,80 +1,17 @@ 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() { }) @@ -91,6 +28,40 @@ var _ = Describe("Sarif Formatter", func() { Expect(validateSarifSchema(sarifReport)).To(Succeed()) }) + It("sarif formatted report should contain proper autofix", func() { + ruleID := "G101" + cwe := issue.GetCweByRule(ruleID) + autofixIssue := []*issue.Issue{ + { + File: "/home/src/project/test.go", + Line: "1", + Col: "1", + RuleID: ruleID, + What: "test", + Confidence: issue.High, + Severity: issue.High, + Code: "1: testcode", + Cwe: cwe, + Suppressions: []issue.SuppressionInfo{ + { + Kind: "inSource", + Justification: "justification", + }, + }, + Autofix: "some random autofix", + }, + } + reportInfo := gosec.NewReportInfo(autofixIssue, &gosec.Metrics{}, map[string][]gosec.Error{}).WithVersion("v2.7.0") + buf := new(bytes.Buffer) + err := sarif.WriteReport(buf, reportInfo, []string{}) + 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() { ruleID := "G101" cwe := issue.GetCweByRule(ruleID)