Skip to content

Commit c07aa5e

Browse files
author
Victor Chen
authored
Add support for api key metadata (#73)
* Add support for api key metadata * Test key * test * test * test * Fix quotes * Add key * Revert testing stuff * PR comments * Fix tests
1 parent 38c63fb commit c07aa5e

File tree

4 files changed

+124
-7
lines changed

4 files changed

+124
-7
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ require (
77
github.com/golang/mock v1.4.4
88
github.com/google/go-github/v33 v33.0.0
99
github.com/google/uuid v1.3.0
10-
github.com/nightfallai/nightfall-go-sdk v1.1.1
10+
github.com/nightfallai/nightfall-go-sdk v1.1.5
1111
github.com/pkg/errors v0.9.1 // indirect
1212
github.com/spf13/pflag v1.0.5
1313
github.com/stretchr/testify v1.6.1
1414
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99
15+
golang.org/x/text v0.3.3
1516
gotest.tools v2.2.0+incompatible
1617
)

go.sum

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
115115
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
116116
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
117117
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
118-
github.com/nightfallai/nightfall-go-sdk v1.1.1 h1:xx/e4ZP415oHQcJMOCBeU8kxOWiakrjtEEREZHJtE8Q=
119-
github.com/nightfallai/nightfall-go-sdk v1.1.1/go.mod h1:IQxS8JqhFEGRfnOpaLqv+ZEhQrUKbJgFAQ5qHU3Lcbg=
118+
github.com/nightfallai/nightfall-go-sdk v1.1.5 h1:QJ6SxZKTqmUDK/Jh2m4I3Dhk1NMJ8ThPX4aZVfnugwA=
119+
github.com/nightfallai/nightfall-go-sdk v1.1.5/go.mod h1:IQxS8JqhFEGRfnOpaLqv+ZEhQrUKbJgFAQ5qHU3Lcbg=
120120
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
121121
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
122122
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -172,7 +172,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
172172
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
173173
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
174174
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
175-
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
176175
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
177176
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
178177
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -245,6 +244,7 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
245244
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
246245
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
247246
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
247+
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
248248
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
249249
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
250250
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -288,7 +288,6 @@ golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roY
288288
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
289289
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
290290
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
291-
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d h1:W07d4xkoAUSNOkOzdzXCdFGxT7o2rW4q8M34tB2i//k=
292291
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
293292
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
294293
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

internal/clients/nightfall/nightfall.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"regexp"
10+
"strings"
1011
"sync"
1112
"time"
1213
"unicode/utf8"
@@ -17,6 +18,8 @@ import (
1718
"github.com/nightfallai/nightfall_code_scanner/internal/clients/diffreviewer"
1819
"github.com/nightfallai/nightfall_code_scanner/internal/clients/logger"
1920
"github.com/nightfallai/nightfall_code_scanner/internal/nightfallconfig"
21+
"golang.org/x/text/cases"
22+
"golang.org/x/text/language"
2023
)
2124

2225
const (
@@ -80,7 +83,7 @@ func getCommentMsg(finding *nf.Finding) string {
8083
content = finding.Finding
8184
}
8285

83-
return fmt.Sprintf("Suspicious content detected (%q, type %q)", content, finding.Detector.DisplayName)
86+
return fmt.Sprintf("Suspicious content detected (%q, type %s)", content, getDisplayType(finding))
8487
}
8588

8689
func getCommentTitle(finding *nf.Finding) string {
@@ -90,6 +93,24 @@ func getCommentTitle(finding *nf.Finding) string {
9093
return fmt.Sprintf("Detected %s", finding.Detector.DisplayName)
9194
}
9295

96+
func getDisplayType(finding *nf.Finding) string {
97+
displayType := fmt.Sprintf("%q", finding.Detector.DisplayName)
98+
// Check if there is additional context to add to the display type
99+
if finding.FindingMetadata != nil && finding.FindingMetadata.APIKeyMetadata != nil {
100+
apiKeyMd := finding.FindingMetadata.APIKeyMetadata
101+
if kind := apiKeyMd.Kind; strings.ToUpper(kind) != "UNSPECIFIED" {
102+
if status := apiKeyMd.Status; strings.ToUpper(status) != "UNVERIFIED" {
103+
titledStatus := cases.Title(language.English).String(strings.ToLower(status))
104+
displayType = fmt.Sprintf("%q (%s %s key)", finding.Detector.DisplayName, titledStatus, kind)
105+
} else {
106+
titledConfidence := cases.Title(language.English).String(strings.ToLower(finding.Confidence))
107+
displayType = fmt.Sprintf("%q (%s %s key)", finding.Detector.DisplayName, titledConfidence, kind)
108+
}
109+
}
110+
}
111+
return displayType
112+
}
113+
93114
// wordSplitter is of type bufio.SplitFunc (https://golang.org/pkg/bufio/#SplitFunc)
94115
// this function is used to determine how to chunk the reader input into bufio.Scanner.
95116
// This function will create chunks of input buffer size, but will not chunk in the middle of

internal/clients/nightfall/nightfall_test.go

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ import (
1414
"github.com/stretchr/testify/assert"
1515
)
1616

17-
var blurredCreditCard = "49*****************"
17+
var (
18+
blurredCreditCard = "49*****************"
19+
blurredAPIKey = "yr**************************************"
20+
)
1821

1922
type mockNightfall struct {
2023
scanFn func(context.Context, *nf.ScanTextRequest) (*nf.ScanTextResponse, error)
@@ -215,6 +218,99 @@ func TestReviewDiffDetectionRuleUUID(t *testing.T) {
215218
assert.Equal(t, expectedComments, comments, "Received incorrect response from ReviewDiff")
216219
}
217220

221+
func TestReviewDiffHasFindingMetadata(t *testing.T) {
222+
mockAPIClient := &mockNightfall{}
223+
client := Client{
224+
APIClient: mockAPIClient,
225+
DetectionRules: testDetectionRules,
226+
MaxNumberRoutines: 1,
227+
}
228+
229+
numLines := 20
230+
numFiles := 50
231+
numScanReq := ((numLines * numFiles) + maxItemsForAPIReq - 1) / maxItemsForAPIReq
232+
filePath := "test/data"
233+
lineNum := 0
234+
content := fmt.Sprintf("this has a api key %s", exampleAPIKey)
235+
236+
lines := make([]*diffreviewer.Line, numLines)
237+
for i := range lines {
238+
lines[i] = &diffreviewer.Line{
239+
LnumNew: lineNum,
240+
Content: content,
241+
}
242+
}
243+
244+
input := make([]*diffreviewer.FileDiff, numFiles)
245+
for i := range input {
246+
h := &diffreviewer.Hunk{
247+
Lines: lines,
248+
}
249+
input[i] = &diffreviewer.FileDiff{
250+
Hunks: []*diffreviewer.Hunk{h},
251+
PathNew: filePath,
252+
}
253+
}
254+
255+
c := diffreviewer.Comment{
256+
FilePath: filePath,
257+
LineNumber: lineNum,
258+
Body: fmt.Sprintf("Suspicious content detected (%q, type %q (%s %s key))", blurredAPIKey, "API_KEY", "Active", "Stripe"),
259+
Title: fmt.Sprintf("Detected API_KEY"),
260+
}
261+
expectedComments := []*diffreviewer.Comment{&c, &c, &c}
262+
263+
scanResp := &nf.ScanTextResponse{
264+
Findings: [][]*nf.Finding{
265+
{},
266+
{
267+
{
268+
Finding: exampleAPIKey,
269+
RedactedFinding: blurredAPIKey,
270+
Detector: nf.DetectorMetadata{
271+
DisplayName: "API_KEY",
272+
DetectorUUID: "2136e3c9-feb0-4aea-8d3e-a767afabf501",
273+
},
274+
Confidence: string(nf.ConfidencePossible),
275+
FindingMetadata: &nf.FindingMetadata{APIKeyMetadata: &nf.APIKeyMetadata{
276+
Status: "ACTIVE",
277+
Kind: "Stripe",
278+
}},
279+
},
280+
},
281+
},
282+
}
283+
284+
totalItems := make([]string, numLines*numFiles)
285+
for i := 0; i < numLines*numFiles; i++ {
286+
totalItems[i] = content
287+
}
288+
289+
var callCount int
290+
expectedRequests := make([]*nf.ScanTextRequest, 0, numScanReq)
291+
for i := 0; i < numScanReq; i++ {
292+
startIndex := i * maxItemsForAPIReq
293+
var endIndex int
294+
if len(totalItems) < startIndex+maxItemsForAPIReq {
295+
endIndex = len(totalItems)
296+
} else {
297+
endIndex = startIndex + maxItemsForAPIReq
298+
}
299+
300+
expectedScanReq := client.buildScanRequest(totalItems[startIndex:endIndex])
301+
expectedRequests = append(expectedRequests, expectedScanReq)
302+
mockAPIClient.scanFn = func(ctx context.Context, request *nf.ScanTextRequest) (*nf.ScanTextResponse, error) {
303+
assert.Equal(t, expectedRequests[callCount], request, "request object did not match")
304+
callCount++
305+
return scanResp, nil
306+
}
307+
}
308+
309+
comments, err := client.ReviewDiff(context.Background(), githublogger.NewDefaultGithubLogger(), input)
310+
assert.NoError(t, err, "Received error from ReviewDiff")
311+
assert.Equal(t, expectedComments, comments, "Received incorrect response from ReviewDiff")
312+
}
313+
218314
func TestScanPaths(t *testing.T) {
219315
client := Client{
220316
DetectionRules: testDetectionRules,

0 commit comments

Comments
 (0)