Skip to content

Commit

Permalink
Refactored Vulnerability Builder (#2531)
Browse files Browse the repository at this point in the history
Co-authored-by: Rogério Peixoto <[email protected]>
  • Loading branch information
cx-joao-reigota and rogeriopeixotocx authored Apr 5, 2021
1 parent 595c9f9 commit 2bf7a18
Show file tree
Hide file tree
Showing 26 changed files with 1,780 additions and 1,325 deletions.
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -1566,7 +1565,6 @@ golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roY
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand Down
8 changes: 4 additions & 4 deletions internal/console/helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ func printFiles(query *model.VulnerableQuery, printer *Printer) {
query.Files[fileIdx].FileName, printer.Success.Sprint(query.Files[fileIdx].Line))
if !printer.minimal {
fmt.Println()
for lineIdx, line := range query.Files[fileIdx].VulnLines.Lines {
if query.Files[fileIdx].VulnLines.Positions[lineIdx] == query.Files[fileIdx].Line {
printer.Line.Printf("\t\t%03d: %s\n", query.Files[fileIdx].VulnLines.Positions[lineIdx], line)
for _, line := range query.Files[fileIdx].VulnLines {
if line.Position == query.Files[fileIdx].Line {
printer.Line.Printf("\t\t%03d: %s\n", line.Position, line.Line)
} else {
fmt.Printf("\t\t%03d: %s\n", query.Files[fileIdx].VulnLines.Positions[lineIdx], line)
fmt.Printf("\t\t%03d: %s\n", line.Position, line.Line)
}
}
fmt.Print("\n\n")
Expand Down
5 changes: 5 additions & 0 deletions internal/constants/constants.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package constants

import "math"

// Version - current KICS version
var Version = "dev"

Expand All @@ -20,3 +22,6 @@ const MinimumPreviewLines = 1

// MaximumPreviewLines - default maximum preview lines number
const MaximumPreviewLines = 30

// MaxInteger - max possible integer in golang
const MaxInteger = math.MaxInt64
56 changes: 56 additions & 0 deletions pkg/detector/default_detect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package detector

import (
"strconv"
"strings"

"github.com/Checkmarx/kics/pkg/model"
"github.com/rs/zerolog"
)

const (
undetectedVulnerabilityLine = -1
)

type defaultDetectLine struct {
}

// DetectLine searches vulnerability line if kindDetectLine is not in detectors
func (d defaultDetectLine) DetectLine(file *model.FileMetadata, searchKey string,
logWithFields *zerolog.Logger, outputLines int) model.VulnerabilityLines {
text := strings.ReplaceAll(file.OriginalData, "\r", "")
lines := strings.Split(text, "\n")
foundAtLeastOne := false
currentLine := 0
isBreak := false
var extractedString [][]string
extractedString = GetBracketValues(searchKey, extractedString, "")
sanitizedSubstring := searchKey
for idx, str := range extractedString {
sanitizedSubstring = strings.Replace(sanitizedSubstring, str[0], `{{`+strconv.Itoa(idx)+`}}`, -1)
}

for _, key := range strings.Split(sanitizedSubstring, ".") {
substr1, substr2 := GenerateSubstrings(key, extractedString)

foundAtLeastOne, currentLine, isBreak = DetectCurrentLine(lines, substr1, substr2, currentLine, foundAtLeastOne)

if isBreak {
break
}
}

if foundAtLeastOne {
return model.VulnerabilityLines{
Line: currentLine + 1,
VulnLines: GetAdjacentVulnLines(currentLine, outputLines, lines),
}
}

logWithFields.Warn().Msgf("Failed to detect line, query response %s", searchKey)

return model.VulnerabilityLines{
Line: undetectedVulnerabilityLine,
VulnLines: []model.CodeLine{},
}
}
156 changes: 156 additions & 0 deletions pkg/detector/default_detect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package detector

import (
"reflect"
"testing"

"github.com/Checkmarx/kics/pkg/model"
"github.com/Checkmarx/kics/test"
"github.com/rs/zerolog"
"github.com/stretchr/testify/require"
)

// Test_detectLine tests the functions [detectLine()] and all the methods called by them
func Test_detectLine(t *testing.T) { //nolint
type args struct {
file *model.FileMetadata
searchKey string
}
type feilds struct {
outputLines int
}
tests := []struct {
name string
args args
feilds feilds
want model.VulnerabilityLines
}{
{
name: "detect_line",
args: args{
file: &model.FileMetadata{
ScanID: "scanID",
ID: "Test",
Kind: model.KindTerraform,
OriginalData: `resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "authenticated-read"
tags = {
Name = "My bucket"
Environment = "Dev"
}
}
`,
},
searchKey: "aws_s3_bucket[b].acl",
},
feilds: feilds{
outputLines: 3,
},
want: model.VulnerabilityLines{
Line: 3,
VulnLines: []model.CodeLine{
{
Position: 2,
Line: ` bucket = "my-tf-test-bucket"`,
},
{
Position: 3,
Line: ` acl = "authenticated-read"`,
},
{
Position: 4,
Line: "",
},
},
LineWithVulnerabilty: "",
},
},
{
name: "detect_line_with_curly_brackets",
args: args{
file: &model.FileMetadata{
ScanID: "scanID",
ID: "Test",
Kind: model.KindTerraform,
OriginalData: `resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "authenticated-read"
tags = {
Name = "My bucket"
Environment = "Dev.123"
Environment = "test"
}
}
`,
},
searchKey: "aws_s3_bucket[b].Environment={{Dev.123}}",
},
feilds: feilds{
outputLines: 3,
},
want: model.VulnerabilityLines{
Line: 7,
VulnLines: []model.CodeLine{
{
Position: 6,
Line: ` Name = "My bucket"`,
},
{
Position: 7,
Line: ` Environment = "Dev.123"`,
},
{
Position: 8,
Line: ` Environment = "test"`,
},
},
LineWithVulnerabilty: "",
},
},
{
name: "detect_line_error",
args: args{
file: &model.FileMetadata{
ScanID: "scanID",
ID: "Test",
Kind: model.KindTerraform,
OriginalData: `resource "aws_s3_bucket" "b" {
bucket = "my-tf-test-bucket"
acl = "authenticated-read"
tags = {
Name = "My bucket"
Environment = "Dev.123"
Environment = "test"
}
}
`,
},
searchKey: "testing.error",
},
feilds: feilds{
outputLines: 3,
},
want: model.VulnerabilityLines{
Line: -1,
VulnLines: []model.CodeLine{},
},
},
}
for _, tt := range tests {
detector := NewDetectLine(tt.feilds.outputLines)
t.Run(tt.name, func(t *testing.T) {
got := detector.defaultDetector.DetectLine(tt.args.file, tt.args.searchKey, &zerolog.Logger{}, 3)
gotStrVulnerabilities, err := test.StringifyStruct(got)
require.Nil(t, err)
wantStrVulnerabilities, err := test.StringifyStruct(tt.want)
require.Nil(t, err)
if !reflect.DeepEqual(gotStrVulnerabilities, wantStrVulnerabilities) {
t.Errorf("detectLine() = %v, want %v", gotStrVulnerabilities, wantStrVulnerabilities)
}
})
}
}
49 changes: 49 additions & 0 deletions pkg/detector/detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package detector

import (
"github.com/Checkmarx/kics/pkg/model"
"github.com/rs/zerolog"
)

type kindDetectLine interface {
DetectLine(file *model.FileMetadata, searchKey string,
logWithFields *zerolog.Logger, outputLines int) model.VulnerabilityLines
}

// DetectLine is a struct that associates a kindDetectLine to its FileKind
type DetectLine struct {
detectors map[model.FileKind]kindDetectLine
outputLines int
logWithFields *zerolog.Logger
defaultDetector kindDetectLine
}

// NewDetectLine creates a new DetectLine's reference
func NewDetectLine(outputLines int) *DetectLine {
return &DetectLine{
detectors: make(map[model.FileKind]kindDetectLine),
logWithFields: &zerolog.Logger{},
outputLines: outputLines,
defaultDetector: defaultDetectLine{},
}
}

// SetupLogs will change the logger feild to be used in kindDetectLine DetectLine method
func (d *DetectLine) SetupLogs(logger *zerolog.Logger) {
d.logWithFields = logger
}

// Add adds a new kindDetectLine to the caller and returns it
func (d *DetectLine) Add(detector kindDetectLine, kind model.FileKind) *DetectLine {
d.detectors[kind] = detector
return d
}

// DetectLine will use the correct kindDetectLine according to the files kind
// if file kind is not in detectors default detect line is called
func (d *DetectLine) DetectLine(file *model.FileMetadata, searchKey string) model.VulnerabilityLines {
if det, ok := d.detectors[file.Kind]; ok {
return det.DetectLine(file, searchKey, d.logWithFields, d.outputLines)
}
return d.defaultDetector.DetectLine(file, searchKey, d.logWithFields, d.outputLines)
}
Loading

0 comments on commit 2bf7a18

Please sign in to comment.