Skip to content

Commit

Permalink
fix: unique id for secrets (#125)
Browse files Browse the repository at this point in the history
BREAKING CHANGES:
- new hashed `ID`
- `Description` changed to `RuleID`

Added:
- `--project-name` to `git` plugin
- `--project-name` to `filesystem` plugin

Close #124
Close #109 by implementing
#109 (comment)
  • Loading branch information
Baruch Odem (Rothkoff) authored Jul 12, 2023
1 parent b138f5d commit 9879b3b
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 34 deletions.
3 changes: 2 additions & 1 deletion plugins/confluence.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ func (p *ConfluencePlugin) getItem(page ConfluencePage, space ConfluenceSpaceRes

content := &Item{
Content: pageContent.Body.Storage.Value,
ID: pageContent.Links["base"] + pageContent.Links["webui"],
ID: fmt.Sprintf("%s-%s-%s-%s", p.GetName(), p.URL, space.Key, page.ID),
Source: pageContent.Links["base"] + pageContent.Links["webui"],
}
return content, pageContent.History.PreviousVersion.Number, nil
}
Expand Down
7 changes: 4 additions & 3 deletions plugins/discord.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func (p *DiscordPlugin) readChannelMessages(channel *discordgo.Channel) {
}
channelLogger.Info().Msgf("Found %d messages", len(messages))

items := convertMessagesToItems(channel.GuildID, &messages)
items := convertMessagesToItems(p.GetName(), channel.GuildID, &messages)
for _, item := range *items {
p.itemChan <- item
}
Expand Down Expand Up @@ -273,12 +273,13 @@ func (p *DiscordPlugin) getMessages(channelID string, logger zerolog.Logger) ([]
return append(messages, threadMessages...), nil
}

func convertMessagesToItems(guildId string, messages *[]*discordgo.Message) *[]Item {
func convertMessagesToItems(pluginName, guildId string, messages *[]*discordgo.Message) *[]Item {
items := []Item{}
for _, message := range *messages {
items = append(items, Item{
Content: message.Content,
ID: fmt.Sprintf("https://discord.com/channels/%s/%s/%s", guildId, message.ChannelID, message.ID),
ID: fmt.Sprintf("%s-%s-%s-%s", pluginName, guildId, message.ChannelID, message.ID),
Source: fmt.Sprintf("https://discord.com/channels/%s/%s/%s", guildId, message.ChannelID, message.ID),
})
}
return &items
Expand Down
16 changes: 11 additions & 5 deletions plugins/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ import (
"github.com/spf13/cobra"
)

const flagFolder = "path"
const flagIgnored = "ignore"
const (
flagFolder = "path"
flagProjectName = "project-name"
flagIgnored = "ignore"
)

var ignoredFolders = []string{".git"}

type FileSystemPlugin struct {
Plugin
Path string
Ignored []string
Path string
ProjectName string
Ignored []string
}

func (p *FileSystemPlugin) GetName() string {
Expand Down Expand Up @@ -46,6 +50,7 @@ func (p *FileSystemPlugin) DefineCommand(channels Channels) (*cobra.Command, err
}

flags.StringSliceVar(&p.Ignored, flagIgnored, []string{}, "Patterns to ignore")
flags.StringVar(&p.ProjectName, flagProjectName, "", "Project name to differentiate between filesystem scans")

return cmd, nil
}
Expand Down Expand Up @@ -112,7 +117,8 @@ func (p *FileSystemPlugin) getItem(wg *sync.WaitGroup, filePath string) (*Item,

content := &Item{
Content: string(b),
ID: filePath,
ID: fmt.Sprintf("%s-%s-%s", p.GetName(), p.ProjectName, filePath),
Source: filePath,
}
return content, nil
}
10 changes: 7 additions & 3 deletions plugins/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ import (
const (
argDepth = "depth"
argScanAllBranches = "all-branches"
argProjectName = "project-name"
)

type GitPlugin struct {
Plugin
Channels
depth int
scanAllBranches bool
projectName string
}

func (p *GitPlugin) GetName() string {
Expand All @@ -37,12 +39,13 @@ func (p *GitPlugin) DefineCommand(channels Channels) (*cobra.Command, error) {
Args: cobra.MatchAll(cobra.ExactArgs(1), validGitRepoArgs),
Run: func(cmd *cobra.Command, args []string) {
log.Info().Msg("Git plugin started")
scanGit(args[0], p.buildScanOptions(), channels.Items, channels.Errors)
p.scanGit(args[0], p.buildScanOptions(), channels.Items, channels.Errors)
},
}
flags := command.Flags()
flags.BoolVar(&p.scanAllBranches, argScanAllBranches, false, "scan all branches [default: false]")
flags.IntVar(&p.depth, argDepth, 0, "number of commits to scan from HEAD")
flags.StringVar(&p.projectName, argProjectName, "", "Project name to differentiate between filesystem scans")
return command, nil
}

Expand All @@ -57,7 +60,7 @@ func (p *GitPlugin) buildScanOptions() string {
return strings.Join(options, " ")
}

func scanGit(path string, scanOptions string, itemsChan chan Item, errChan chan error) {
func (p *GitPlugin) scanGit(path string, scanOptions string, itemsChan chan Item, errChan chan error) {
fileChan, err := git.GitLog(path, scanOptions)
if err != nil {
errChan <- fmt.Errorf("error while scanning git repository: %w", err)
Expand All @@ -80,7 +83,8 @@ func scanGit(path string, scanOptions string, itemsChan chan Item, errChan chan
if fileChanges != "" {
itemsChan <- Item{
Content: fileChanges,
ID: fmt.Sprintf("git show %s:%s", file.PatchHeader.SHA, file.NewName),
ID: fmt.Sprintf("%s-%s-%s-%s", p.GetName(), p.projectName, file.PatchHeader.SHA, file.NewName),
Source: fmt.Sprintf("git show %s:%s", file.PatchHeader.SHA, file.NewName),
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion plugins/paligo.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ func (p *PaligoPlugin) handleComponent(item PaligoItem) {

p.Items <- Item{
Content: document.Content,
ID: url,
ID: fmt.Sprintf("%s-%s-%d", p.GetName(), p.paligoApi.Instance, document.ID),
Source: url,
}
}

Expand Down
4 changes: 3 additions & 1 deletion plugins/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import (

type Item struct {
Content string
// Unique identifier of the item (page, document, file) with user-friendly content (e.g. URL, file path)
// Unique identifier of the item
ID string
// User friendly description and/or link to the item
Source string
}

type Plugin struct {
Expand Down
3 changes: 2 additions & 1 deletion plugins/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ func (p *SlackPlugin) getItemsFromChannel(slackApi *slack.Client, channel slack.
}
p.Items <- Item{
Content: message.Text,
ID: url,
ID: fmt.Sprintf("%s-%s-%s", p.GetName(), channel.ID, message.Timestamp),
Source: url,
}
}
counter++
Expand Down
5 changes: 3 additions & 2 deletions reporting/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package reporting

import (
"fmt"
"github.com/checkmarx/2ms/config"
"os"
"path/filepath"
"strings"

"github.com/checkmarx/2ms/config"
)

const (
Expand All @@ -23,7 +24,7 @@ type Report struct {
type Secret struct {
ID string `json:"id"`
Source string `json:"source"`
Description string `json:"description"`
RuleID string `json:"ruleId"`
StartLine int `json:"startLine"`
EndLine int `json:"endLine"`
StartColumn int `json:"startColumn"`
Expand Down
2 changes: 1 addition & 1 deletion reporting/report_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ JPcHeO7M6FohKgcEHX84koQDN98J/L7pFlSoU7WOl6f8BKavIdeSTPS9qQYWdQuT

results := map[string][]Secret{}
report := Report{len(results), 1, results}
secret := Secret{Description: "bla", StartLine: 0, StartColumn: 0, EndLine: 0, EndColumn: 0, Value: secretValue}
secret := Secret{Source: "bla", StartLine: 0, StartColumn: 0, EndLine: 0, EndColumn: 0, Value: secretValue}
source := "directory\\rawStringAsFile.txt"

report.Results[source] = append(report.Results[source], secret)
Expand Down
7 changes: 4 additions & 3 deletions reporting/sarif.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ package reporting
import (
"encoding/json"
"fmt"
"github.com/checkmarx/2ms/config"
"log"

"github.com/checkmarx/2ms/config"
)

func writeSarif(report Report, cfg *config.Config) string {
Expand Down Expand Up @@ -47,7 +48,7 @@ func hasNoResults(report Report) bool {
}

func messageText(secret Secret) string {
return fmt.Sprintf("%s has detected secret for file %s.", secret.Description, secret.ID)
return fmt.Sprintf("%s has detected secret for file %s.", secret.Source, secret.ID)
}

func getResults(report Report) []Results {
Expand All @@ -65,7 +66,7 @@ func getResults(report Report) []Results {
Message: Message{
Text: messageText(secret),
},
RuleId: secret.Description,
RuleId: secret.Source,
Locations: getLocation(secret),
}
results = append(results, r)
Expand Down
30 changes: 17 additions & 13 deletions secrets/secrets.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package secrets

import (
"crypto/sha1"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"sync"
Expand All @@ -15,6 +15,7 @@ import (
"github.com/zricethezav/gitleaks/v8/cmd/generate/config/rules"
"github.com/zricethezav/gitleaks/v8/config"
"github.com/zricethezav/gitleaks/v8/detect"
"github.com/zricethezav/gitleaks/v8/report"
)

type Secrets struct {
Expand Down Expand Up @@ -90,8 +91,17 @@ func (s *Secrets) Detect(secretsChannel chan reporting.Secret, item plugins.Item
Raw: item.Content,
}
for _, value := range s.detector.Detect(fragment) {
itemId := getItemId(item.ID)
secretsChannel <- reporting.Secret{ID: itemId, Source: item.ID, Description: value.Description, StartLine: value.StartLine, StartColumn: value.StartColumn, EndLine: value.EndLine, EndColumn: value.EndColumn, Value: value.Secret}
itemId := getFindingId(item, value)
secretsChannel <- reporting.Secret{
ID: itemId,
Source: item.Source,
RuleID: value.RuleID,
StartLine: value.StartLine,
StartColumn: value.StartColumn,
EndLine: value.EndLine,
EndColumn: value.EndColumn,
Value: value.Secret,
}
}
}

Expand All @@ -112,16 +122,10 @@ func (s *Secrets) AddRegexRules(patterns []string) error {
return nil
}

func getItemId(fullPath string) string {
var itemId string
if strings.Contains(fullPath, "/") {
itemLinkStrings := strings.Split(fullPath, "/")
itemId = itemLinkStrings[len(itemLinkStrings)-1]
}
if strings.Contains(fullPath, "\\") {
itemId = filepath.Base(fullPath)
}
return itemId
func getFindingId(item plugins.Item, finding report.Finding) string {
idParts := []string{item.ID, finding.RuleID, finding.Secret}
sha := sha1.Sum([]byte(strings.Join(idParts, "-")))
return fmt.Sprintf("%x", sha)
}

func selectRules(allRules []Rule, tags []string) map[string]config.Rule {
Expand Down

0 comments on commit 9879b3b

Please sign in to comment.