Skip to content

Commit

Permalink
gitleaks:bugfix - updating formatter to gitleaks v8
Browse files Browse the repository at this point in the history
When the v8 version of gitaleks was released, the way to do an analysis
and the output of that analysis changed. This pr updates the formatter
to the new format and updates gitleaks to v8.3.0. It also contains some
improvements in the formatter code.

Signed-off-by: Nathan Martins <nathan.martins@zup.com.br>
  • Loading branch information
nathanmartinszup committed Mar 3, 2022
1 parent df2e20c commit 21a52c6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 74 deletions.
2 changes: 1 addition & 1 deletion internal/enums/images/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const (
Go = "horuszup/horusec-go:v1.2.1"
HCL = "horuszup/horusec-hcl:v1.1.0"
Javascript = "horuszup/horusec-js:v1.2.0"
Leaks = "horuszup/horusec-leaks:v1.1.0"
Leaks = "horuszup/horusec-leaks:v1.2.0"
PHP = "horuszup/horusec-php:v1.0.1"
Python = "horuszup/horusec-python:v1.0.0"
Ruby = "horuszup/horusec-ruby:v1.1.1"
Expand Down
2 changes: 1 addition & 1 deletion internal/services/formatters/leaks/deployments/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM zricethezav/gitleaks:v8.2.7
FROM zricethezav/gitleaks:v8.3.0

COPY ./internal/services/formatters/leaks/deployments/rules.toml /rules/rules.toml

Expand Down
13 changes: 6 additions & 7 deletions internal/services/formatters/leaks/gitleaks/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//nolint
package gitleaks

const CMD = `
{{WORK_DIR}}
if ! gitleaks --config-path /rules/rules.toml --path . --leaks-exit-code 0 --format json --report /tmp/leaks-result.json &> /tmp/leaks-runner-output.txt; then
echo /tmp/leaks-runner-output.txt
else
cat /tmp/leaks-result.json
fi
{{WORK_DIR}}
if ! gitleaks detect -c /rules/rules.toml -f json -r /tmp/leaks.json --exit-code 0 &> /tmp/leaks-output.txt; then
cat /tmp/leaks-output.txt
else
cat /tmp/leaks.json
fi
`
100 changes: 47 additions & 53 deletions internal/services/formatters/leaks/gitleaks/formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package gitleaks
import (
"encoding/json"
"errors"
"strconv"
"strings"

"github.com/ZupIT/horusec-devkit/pkg/entities/vulnerability"
Expand All @@ -29,7 +30,6 @@ import (
"github.com/ZupIT/horusec/internal/enums/images"
"github.com/ZupIT/horusec/internal/helpers/messages"
"github.com/ZupIT/horusec/internal/services/formatters"
"github.com/ZupIT/horusec/internal/services/formatters/leaks/gitleaks/entities"
vulnhash "github.com/ZupIT/horusec/internal/utils/vuln_hash"
)

Expand Down Expand Up @@ -62,78 +62,72 @@ func (f *Formatter) startGitLeaks(projectSubPath string) (string, error) {
return output, err
}

return output, f.formatOutputGitLeaks(output)
if err := f.checkOutputErrors(output); err != nil {
return output, err
}

return output, f.parseOutput(output)
}

func (f *Formatter) formatOutputGitLeaks(output string) error {
if output == "" || (len(output) >= 4 && output[:4] == "null") {
func (f *Formatter) getDockerConfig(projectSubPath string) *dockerEntities.AnalysisData {
analysisData := &dockerEntities.AnalysisData{
CMD: f.AddWorkDirInCmd(CMD, projectSubPath, tools.GitLeaks),
Language: languages.Leaks,
}

return analysisData.SetImage(f.GetCustomImageByLanguage(languages.Leaks), images.Leaks)
}

func (f *Formatter) parseOutput(output string) error {
var issues []*Issue

if err := json.Unmarshal([]byte(output), &issues); err != nil {
return err
}

if len(issues) == 0 {
logger.LogDebugWithLevel(messages.MsgDebugOutputEmpty,
map[string]interface{}{"tool": tools.GitLeaks.ToString()})
f.setGitLeaksOutPutInHorusecAnalysis([]entities.Issue{})
return nil
}

issues, err := f.parseOutputToIssues(output)
if err != nil {
return err
}
f.forEachIssueCreateNewVuln(issues)

f.setGitLeaksOutPutInHorusecAnalysis(issues)
return nil
}

func (f *Formatter) parseOutputToIssues(output string) ([]entities.Issue, error) {
var issues []entities.Issue
err := json.Unmarshal([]byte(output), &issues)
if err != nil && strings.Contains(err.Error(), "invalid character") {
err = errors.New(output)
}
return issues, err
}

func (f *Formatter) setGitLeaksOutPutInHorusecAnalysis(issues []entities.Issue) {
for key := range issues {
vuln := f.setupVulnerabilitiesSeveritiesGitLeaks(&issues[key])
f.AddNewVulnerabilityIntoAnalysis(vuln)
func (f *Formatter) forEachIssueCreateNewVuln(issues []*Issue) {
for _, issue := range issues {
f.AddNewVulnerabilityIntoAnalysis(f.newVulnerability(issue))
}
}

func (f *Formatter) setupVulnerabilitiesSeveritiesGitLeaks(issue *entities.Issue) (
vulnerabilitySeverity *vulnerability.Vulnerability,
) {
vulnerabilitySeverity = f.getDefaultSeverity()
vulnerabilitySeverity.Severity = severities.Critical
vulnerabilitySeverity.RuleID = vulnhash.HashRuleID(issue.Rule)
vulnerabilitySeverity.Details = issue.Rule
vulnerabilitySeverity.Code = f.GetCodeWithMaxCharacters(issue.Line, 0)
vulnerabilitySeverity.File = issue.File
vulnerabilitySeverity = vulnhash.Bind(vulnerabilitySeverity)
return f.setCommitAuthor(vulnerabilitySeverity, issue)
}

func (f *Formatter) setCommitAuthor(vuln *vulnerability.Vulnerability,
issue *entities.Issue,
) *vulnerability.Vulnerability {
//nolint:funlen // necessary to be long
func (f *Formatter) newVulnerability(issue *Issue) *vulnerability.Vulnerability {
vuln := &vulnerability.Vulnerability{}

vuln.Language = languages.Leaks
vuln.SecurityTool = tools.GitLeaks
vuln.Severity = severities.Critical
vuln.RuleID = vulnhash.HashRuleID(issue.Description)
vuln.Details = issue.Description
vuln.Code = f.GetCodeWithMaxCharacters(issue.Secret, 0)
vuln.File = issue.File
vuln.Line = strconv.Itoa(issue.StartLine)
vuln.Column = strconv.Itoa(issue.StartColumn)
vuln.CommitAuthor = issue.Author
vuln.CommitMessage = strings.ReplaceAll(issue.CommitMessage, "\n", "")
vuln.CommitMessage = f.GetCodeWithMaxCharacters(issue.Message, 0)
vuln.CommitEmail = issue.Email
vuln.CommitDate = issue.Date
vuln.CommitHash = issue.Commit
return vuln

return vulnhash.Bind(vuln)
}

func (f *Formatter) getDockerConfig(projectSubPath string) *dockerEntities.AnalysisData {
analysisData := &dockerEntities.AnalysisData{
CMD: f.AddWorkDirInCmd(CMD, projectSubPath, tools.GitLeaks),
Language: languages.Leaks,
func (f *Formatter) checkOutputErrors(output string) error {
if strings.Contains(output, "not a git repository") {
return errors.New("the current path it's not a valid git repository")
}

return analysisData.SetImage(f.GetCustomImageByLanguage(languages.Leaks), images.Leaks)
}

func (f *Formatter) getDefaultSeverity() *vulnerability.Vulnerability {
vulnerabilitySeverity := &vulnerability.Vulnerability{}
vulnerabilitySeverity.Language = languages.Leaks
vulnerabilitySeverity.SecurityTool = tools.GitLeaks
return vulnerabilitySeverity
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package entities
package gitleaks

type Issue struct {
Line string `json:"line"`
Offender string `json:"offender"`
Commit string `json:"commit"`
Repo string `json:"repo"`
Rule string `json:"rule"`
CommitMessage string `json:"commitMessage"`
Author string `json:"author"`
Email string `json:"email"`
File string `json:"file"`
Date string `json:"date"`
Tags string `json:"tags"`
Description string
StartLine int
EndLine int
StartColumn int
EndColumn int
Match string
Secret string
File string
Commit string
Entropy int
Author string
Email string
Date string
Message string
}

0 comments on commit 21a52c6

Please # to comment.