Skip to content

Commit

Permalink
feat(report): add new jsonv2 format for security (#1401)
Browse files Browse the repository at this point in the history
* feat(report): add new jsonv2 format for security

* chore: add tests for jsonv2

* chore: appease linter

* chore: update snapshots
  • Loading branch information
cfabianski authored Nov 15, 2023
1 parent 1fe0af7 commit 5b5a1c8
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 5 deletions.
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
golang 1.21.1
5 changes: 5 additions & 0 deletions e2e/flags/.snapshots/TestReportFlagsShouldFail-format-jsonv2
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{"source":"Bearer","version":"dev","findings":[{"cwe_ids":["42"],"id":"test_ruby_logger","title":"Ruby logger","description":"Ruby logger","documentation_url":"","line_number":1,"full_filename":"e2e/flags/testdata/simple/main.rb","filename":"main.rb","data_type":{"category_uuid":"cef587dd-76db-430b-9e18-7b031e1a193b","name":"Email Address"},"category_groups":["PII","Personal Data"],"source":{"start":1,"end":1,"column":{"start":26,"end":36}},"sink":{"start":1,"end":1,"column":{"start":1,"end":37},"content":"logger.info(\"user info\", user.email)"},"parent_line_number":1,"snippet":"logger.info(\"user info\", user.email)","fingerprint":"fa5e03644738e4c17cbbd04a580506b1_0","old_fingerprint":"8240e1537878783bac845d1163c80555_0","code_extract":"logger.info(\"user info\", user.email)","severity":"critical"}]}

--
Analyzing codebase

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

--
Error: flag error: report flags error: invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html
Error: flag error: report flags error: invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html, jsonv2
Usage:
bearer scan [flags] <path>
Aliases:
Expand Down Expand Up @@ -46,5 +46,5 @@ General Flags
--no-color Disable color in output


flag error: report flags error: invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html
flag error: report flags error: invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html, jsonv2

2 changes: 1 addition & 1 deletion e2e/flags/report_flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ func TestReportFlagsShouldFail(t *testing.T) {
newScanTest("invalid-format-flag-security", []string{"--format=testing"}),
newScanTest("invalid-format-flag-privacy", []string{"--report=privacy", "--format=testing"}),
newScanTest("invalid-context-flag", []string{"--context=testing"}),
newScanTest("format-jsonv2", []string{"--format=jsonv2", "--external-rule-dir=e2e/testdata/rules"}),
}

for i := range tests {
tests[i].ShouldSucceed = false
}

testhelper.RunTests(t, tests)

}

func TestOuputFlag(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions internal/flag/report_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ var (
FormatGitLabSast = "gitlab-sast"
FormatSarif = "sarif"
FormatJSON = "json"
FormatJSONV2 = "jsonv2"
FormatYAML = "yaml"
FormatHTML = "html"
FormatCSV = "csv"
Expand All @@ -28,7 +29,7 @@ var (
)

var (
ErrInvalidFormatSecurity = errors.New("invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html")
ErrInvalidFormatSecurity = errors.New("invalid format argument for security report; supported values: json, yaml, sarif, gitlab-sast, rdjson, html, jsonv2")
ErrInvalidFormatPrivacy = errors.New("invalid format argument for privacy report; supported values: csv, json, yaml, html")
ErrInvalidFormatDefault = errors.New("invalid format argument; supported values: json, yaml")
ErrInvalidReport = errors.New("invalid report argument; supported values: security, privacy")
Expand Down Expand Up @@ -153,7 +154,7 @@ func (f *ReportFlagGroup) ToOptions() (ReportOptions, error) {
if report != ReportPrivacy {
return ReportOptions{}, invalidFormat
}
case FormatSarif, FormatGitLabSast, FormatReviewDog:
case FormatSarif, FormatGitLabSast, FormatReviewDog, FormatJSONV2:
if report != ReportSecurity {
return ReportOptions{}, invalidFormat
}
Expand Down
13 changes: 13 additions & 0 deletions internal/report/output/security/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/hhatto/gocloc"

"github.com/bearer/bearer/cmd/bearer/build"
"github.com/bearer/bearer/internal/commands/process/settings"
"github.com/bearer/bearer/internal/flag"
"github.com/bearer/bearer/internal/report/output/gitlab"
Expand All @@ -24,6 +25,12 @@ type Formatter struct {
EndTime time.Time
}

type RawFindingsOutput struct {
Source string `json:"source" yaml:"source"`
Version string `json:"version" yaml:"version"`
Findings RawFindings `json:"findings" yaml:"findings"`
}

func NewFormatter(reportData *outputtypes.ReportData, config settings.Config, goclocResult *gocloc.Result, startTime time.Time, endTime time.Time) *Formatter {
return &Formatter{
ReportData: reportData,
Expand Down Expand Up @@ -58,6 +65,12 @@ func (f Formatter) Format(format string) (output string, err error) {
return outputhandler.ReportJSON(sastContent)
case flag.FormatJSON:
return outputhandler.ReportJSON(f.ReportData.FindingsBySeverity)
case flag.FormatJSONV2:
return outputhandler.ReportJSON(RawFindingsOutput{
Source: "Bearer",
Version: build.Version,
Findings: f.ReportData.RawFindings,
})
case flag.FormatYAML:
return outputhandler.ReportYAML(f.ReportData.FindingsBySeverity)
case flag.FormatHTML:
Expand Down
7 changes: 7 additions & 0 deletions internal/report/output/security/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ var severityColorFns = map[string]func(x ...interface{}) string{
globaltypes.LevelWarning: color.New(color.FgCyan).SprintFunc(),
}

type RawFindings = []types.RawFinding
type Findings = map[string][]types.Finding
type IgnoredFindings = map[string][]types.IgnoredFinding

Expand Down Expand Up @@ -99,6 +100,12 @@ func AddReportData(
return err
}

for severity, findingsSlice := range summaryFindings {
for _, finding := range findingsSlice {
reportData.RawFindings = append(reportData.RawFindings, finding.ToRawFinding(severity))
}
}

if !config.Scan.Quiet {
fingerprintOutput(
append(fingerprints, builtInFingerprints...),
Expand Down
19 changes: 19 additions & 0 deletions internal/report/output/security/types/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package types

import (
"encoding/json"
"fmt"
"strings"

Expand All @@ -10,6 +11,11 @@ import (
ignoretypes "github.com/bearer/bearer/internal/util/ignore/types"
)

type RawFinding struct {
*Finding
Severity string `json:"severity" yaml:"severity"`
}

type Finding struct {
*Rule
LineNumber int `json:"line_number,omitempty" yaml:"line_number,omitempty"`
Expand All @@ -36,9 +42,22 @@ type IgnoredFinding struct {

type GenericFinding interface {
GetFinding() Finding
ToRawFinding(severity string) RawFinding
GetIgnoreMeta() *ignoretypes.IgnoredFingerprint
}

func (f Finding) ToRawFinding(severity string) RawFinding {
rawFindingJson, _ := json.Marshal(f)
var rawFinding RawFinding
err := json.Unmarshal(rawFindingJson, &rawFinding)
if err != nil {
return RawFinding{}
}

rawFinding.Severity = f.SeverityMeta.DisplaySeverity
return rawFinding
}

func (f Finding) GetFinding() Finding {
return f
}
Expand Down
1 change: 1 addition & 0 deletions internal/report/output/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type ReportData struct {
FoundLanguages map[string]int32 // language => loc e.g. { "Ruby": 6742, "JavaScript": 122 }
Detectors []any
Dataflow *DataFlow
RawFindings []securitytypes.RawFinding `json:"findings"`
FindingsBySeverity map[string][]securitytypes.Finding
IgnoredFindingsBySeverity map[string][]securitytypes.IgnoredFinding
PrivacyReport *privacytypes.Report
Expand Down

0 comments on commit 5b5a1c8

Please sign in to comment.