Skip to content
Merged
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
5 changes: 5 additions & 0 deletions engine/chunk/chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ func (c *Chunk) PutBuf(window *bytes.Buffer) {
// GetPeekedBuf returns a fixed-size []byte from the pool
func (c *Chunk) GetPeekedBuf() (*[]byte, bool) {
b, ok := c.peekedBufPool.Get().(*[]byte)
if !ok {
return nil, false
}
// reslice to its full capacity so Read can fill it
*b = (*b)[:cap(*b)]
return b, ok
}

Expand Down
42 changes: 28 additions & 14 deletions engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,13 @@ type IEngine interface {
GetRuleBaseRiskScore(ruleId string) float64
}

type ctxKey string

const (
customRegexRuleIdFormat = "custom-regex-%d"
CxFileEndMarker = ";cx-file-end"
customRegexRuleIdFormat = "custom-regex-%d"
CxFileEndMarker = ";cx-file-end"
totalLinesKey ctxKey = "totalLines"
linesInChunkKey ctxKey = "linesInChunk"
)

type EngineConfig struct {
Expand Down Expand Up @@ -109,7 +113,7 @@ func (e *Engine) DetectFragment(item plugins.ISourceItem, secretsChannel chan *s
FilePath: item.GetSource(),
}

return e.detectSecrets(item, fragment, secretsChannel, pluginName)
return e.detectSecrets(context.Background(), item, fragment, secretsChannel, pluginName)
}

// DetectFile reads the given file and detects secrets in it
Expand Down Expand Up @@ -137,7 +141,7 @@ func (e *Engine) DetectFile(ctx context.Context, item plugins.ISourceItem, secre
}
defer e.semaphore.ReleaseMemoryWeight(weight)

return e.detectChunks(item, secretsChannel)
return e.detectChunks(ctx, item, secretsChannel)
}
// fileSize * 2 -> data file bytes and its conversion to string
weight := fileSize * 2
Expand All @@ -156,11 +160,11 @@ func (e *Engine) DetectFile(ctx context.Context, item plugins.ISourceItem, secre
FilePath: item.GetSource(),
}

return e.detectSecrets(item, fragment, secretsChannel, "filesystem")
return e.detectSecrets(ctx, item, fragment, secretsChannel, "filesystem")
}

// detectChunks reads the given file in chunks and detects secrets in each chunk
func (e *Engine) detectChunks(item plugins.ISourceItem, secretsChannel chan *secrets.Secret) error {
func (e *Engine) detectChunks(ctx context.Context, item plugins.ISourceItem, secretsChannel chan *secrets.Secret) error {
f, err := os.Open(item.GetSource())
if err != nil {
return fmt.Errorf("failed to open file %s: %w", item.GetSource(), err)
Expand Down Expand Up @@ -194,20 +198,22 @@ func (e *Engine) detectChunks(item plugins.ISourceItem, secretsChannel chan *sec
Raw: chunkStr,
FilePath: item.GetSource(),
}
if detectErr := e.detectSecrets(item, fragment, secretsChannel, "filesystem"); detectErr != nil {
ctx = context.WithValue(ctx, totalLinesKey, totalLines)
ctx = context.WithValue(ctx, linesInChunkKey, linesInChunk)
if detectErr := e.detectSecrets(ctx, item, fragment, secretsChannel, "filesystem"); detectErr != nil {
return fmt.Errorf("failed to detect secrets: %w", detectErr)
}
}
}

// detectSecrets detects secrets and sends them to the secrets channel
func (e *Engine) detectSecrets(item plugins.ISourceItem, fragment detect.Fragment, secrets chan *secrets.Secret,
func (e *Engine) detectSecrets(ctx context.Context, item plugins.ISourceItem, fragment detect.Fragment, secrets chan *secrets.Secret,
pluginName string) error {
fragment.Raw += CxFileEndMarker + "\n"

values := e.detector.Detect(fragment)
for _, value := range values {
secret, buildErr := buildSecret(item, value, pluginName)
secret, buildErr := buildSecret(ctx, item, value, pluginName)
if buildErr != nil {
return fmt.Errorf("failed to build secret: %w", buildErr)
}
Expand Down Expand Up @@ -306,10 +312,10 @@ func GetRulesCommand(engineConfig *EngineConfig) *cobra.Command {
}

// buildSecret creates a secret object from the given source item and finding
func buildSecret(item plugins.ISourceItem, value report.Finding, pluginName string) (*secrets.Secret, error) {
func buildSecret(ctx context.Context, item plugins.ISourceItem, value report.Finding, pluginName string) (*secrets.Secret, error) {
gitInfo := item.GetGitInfo()
itemId := getFindingId(item, value)
startLine, endLine, err := getStartAndEndLines(pluginName, gitInfo, value)
startLine, endLine, err := getStartAndEndLines(ctx, pluginName, gitInfo, value)
if err != nil {
return nil, fmt.Errorf("failed to get start and end lines for source %s: %w", item.GetSource(), err)
}
Expand Down Expand Up @@ -342,13 +348,21 @@ func getFindingId(item plugins.ISourceItem, finding report.Finding) string {
return fmt.Sprintf("%x", sha)
}

func getStartAndEndLines(pluginName string, gitInfo *plugins.GitInfo, value report.Finding) (int, int, error) {
func getStartAndEndLines(ctx context.Context, pluginName string, gitInfo *plugins.GitInfo, value report.Finding) (int, int, error) {
var startLine, endLine int
var err error

if pluginName == "filesystem" {
startLine = value.StartLine + 1
endLine = value.EndLine + 1
totalLines, totalOK := ctx.Value(totalLinesKey).(int)
chunkLines, chunkOK := ctx.Value(linesInChunkKey).(int)

offset := 1
if totalOK && chunkOK {
offset = (totalLines - chunkLines) + 1
}

startLine = value.StartLine + offset
endLine = value.EndLine + offset
} else if pluginName == "git" {
startLine, endLine, err = plugins.GetGitStartAndEndLine(gitInfo, value.StartLine, value.EndLine)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion engine/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ func TestDetectChunks(t *testing.T) {
tmp := t.TempDir()
src := tc.makeFile(tmp)

err := engine.detectChunks(&item{source: src}, make(chan *secrets.Secret, 1))
err := engine.detectChunks(context.Background(), &item{source: src}, make(chan *secrets.Secret, 1))
loggedMessage := logsBuffer.String()
if tc.expectedErr != nil {
require.ErrorContains(t, err, tc.expectedErr.Error())
Expand Down
Loading