From f1c75613a7219e8caa0b5778a6ef70fd7bce2325 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Tue, 22 Jan 2019 11:56:56 +0530 Subject: [PATCH 01/13] Made changes to report failures in .talismanrc as 'Warnings' --- detector/detection_results.go | 58 ++++++++++++++++++++++++++++++-- detector/filecontent_detector.go | 8 ++++- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/detector/detection_results.go b/detector/detection_results.go index 273ce6cd..cbb45681 100644 --- a/detector/detection_results.go +++ b/detector/detection_results.go @@ -6,7 +6,7 @@ import ( "talisman/git_repo" "github.com/olekukonko/tablewriter" - yaml "gopkg.in/yaml.v2" + "gopkg.in/yaml.v2" ) //DetectionResults represents all interesting information collected during a detection run. @@ -16,11 +16,12 @@ import ( type DetectionResults struct { failures map[git_repo.FilePath][]string ignores map[git_repo.FilePath][]string + warnings map[git_repo.FilePath][]string } //NewDetectionResults is a new DetectionResults struct. It represents the pre-run state of a Detection run. func NewDetectionResults() *DetectionResults { - result := DetectionResults{make(map[git_repo.FilePath][]string), make(map[git_repo.FilePath][]string)} + result := DetectionResults{make(map[git_repo.FilePath][]string), make(map[git_repo.FilePath][]string), make(map[git_repo.FilePath][]string)} return &result } @@ -36,6 +37,15 @@ func (r *DetectionResults) Fail(filePath git_repo.FilePath, message string) { } } +func (r * DetectionResults) Warn(filePath git_repo.FilePath, message string) { + warnings, ok := r.warnings[filePath] + if !ok { + r.warnings[filePath] = []string{message} + } else { + r.warnings[filePath] = append(warnings, message) + } +} + //Ignore is used to mark the supplied FilePath as being ignored. //The most common reason for this is that the FilePath is Denied by the Ignores supplied to the Detector, however, Detectors may use more sophisticated reasons to ignore files. func (r *DetectionResults) Ignore(filePath git_repo.FilePath, detector string) { @@ -57,6 +67,13 @@ func (r *DetectionResults) HasIgnores() bool { return len(r.ignores) > 0 } +func (r * DetectionResults) HasWarnings() bool { + return len(r.warnings) > 0 +} + +func (r *DetectionResults) HasDetectionMessages() bool { + return r.HasWarnings() || r.HasFailures() || r.HasIgnores() +} //Successful answers if no detector was able to find any possible result to fail the run func (r *DetectionResults) Successful() bool { return !r.HasFailures() @@ -67,11 +84,35 @@ func (r *DetectionResults) Failures(fileName git_repo.FilePath) []string { return r.failures[fileName] } +func (r * DetectionResults) ReportWarnings() string { + var result string + var filePathsForWarnings []string + var data [][]string + + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"File", "Warnings"}) + table.SetRowLine(true) + + for filePath := range r.warnings { + filePathsForWarnings = append(filePathsForWarnings, string(filePath)) + warningData := r.ReportFileWarnings(filePath) + data = append(data, warningData...) + } + filePathsForWarnings = unique(filePathsForWarnings) + if len(r.warnings) > 0 { + table.AppendBulk(data) + table.Render() + result = result + fmt.Sprintf("\n\x1b[33mPlease review the above file(s) to make sure that no sensitive content is being pushed\x1b[0m\n") + result = result + fmt.Sprintf("\n") + } + return result +} //Report returns a string documenting the various failures and ignored files for the current run func (r *DetectionResults) Report() string { var result string var filePathsForIgnoresAndFailures []string var data [][]string + table := tablewriter.NewWriter(os.Stdout) table.SetHeader([]string{"File", "Errors"}) table.SetRowLine(true) @@ -81,6 +122,7 @@ func (r *DetectionResults) Report() string { failureData := r.ReportFileFailures(filePath) data = append(data, failureData...) } + for filePath := range r.ignores { filePathsForIgnoresAndFailures = append(filePathsForIgnoresAndFailures, string(filePath)) // ignoreData := r.ReportFileIgnores(filePath) @@ -88,7 +130,6 @@ func (r *DetectionResults) Report() string { } filePathsForIgnoresAndFailures = unique(filePathsForIgnoresAndFailures) if len(r.failures) > 0 { - fmt.Printf("\n\x1b[1m\x1b[31mTalisman Report:\x1b[0m\x1b[0m\n") table.AppendBulk(data) table.Render() result = result + fmt.Sprintf("\n\x1b[33mIf you are absolutely sure that you want to ignore the above files from talisman detectors, consider pasting the following format in .talismanrc file in the project root\x1b[0m\n") @@ -123,6 +164,17 @@ func (r *DetectionResults) ReportFileFailures(filePath git_repo.FilePath) [][]st return data } +func (r *DetectionResults) ReportFileWarnings(filePath git_repo.FilePath) [][]string { + warnings := r.warnings[filePath] + var data [][]string + if len(warnings) > 0 { + for _, warning := range warnings { + data = append(data, []string{string(filePath), warning}) + } + } + return data +} + func (r *DetectionResults) failurePaths() []git_repo.FilePath { return keys(r.failures) } diff --git a/detector/filecontent_detector.go b/detector/filecontent_detector.go index 67758ee2..1d771a87 100644 --- a/detector/filecontent_detector.go +++ b/detector/filecontent_detector.go @@ -9,6 +9,8 @@ import ( log "github.com/Sirupsen/logrus" ) +const talismanrcfilename string = "talismanrc" + type fn func(fc *FileContentDetector, word string) string type FileContentDetector struct { @@ -56,7 +58,11 @@ func fillResults(results []string, addition git_repo.Addition, result *Detection log.WithFields(log.Fields{ "filePath": addition.Path, }).Info(info) - result.Fail(addition.Path, fmt.Sprintf(output, res)) + if strings.Contains(string(addition.Name), talismanrcfilename) { + result.Warn(addition.Path, fmt.Sprintf(output, res)) + } else { + result.Fail(addition.Path, fmt.Sprintf(output, res)) + } } } } From b471c01cca256d5ef092b0f034c4e89969cff7d3 Mon Sep 17 00:00:00 2001 From: Harsha Yarabarla Date: Sun, 3 Feb 2019 17:11:32 +0530 Subject: [PATCH 02/13] Corrected the recursive Hex detection on .talismanrc. --- detector/filecontent_detector.go | 17 ++++++++++++----- detector/pattern_detector.go | 18 +++++++++++++----- runner.go | 5 +++-- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/detector/filecontent_detector.go b/detector/filecontent_detector.go index 1d771a87..be71f8ed 100644 --- a/detector/filecontent_detector.go +++ b/detector/filecontent_detector.go @@ -2,6 +2,7 @@ package detector import ( "fmt" + "regexp" "strings" "talisman/git_repo" @@ -9,8 +10,6 @@ import ( log "github.com/Sirupsen/logrus" ) -const talismanrcfilename string = "talismanrc" - type fn func(fc *FileContentDetector, word string) string type FileContentDetector struct { @@ -41,6 +40,14 @@ func (fc *FileContentDetector) Test(additions []git_repo.Addition, ignoreConfig result.Ignore(addition.Path, "filecontent") continue } + + if string(addition.Name) == DefaultRCFileName { + re := regexp.MustCompile(`(?i)checksum[ \t]*:[ \t]*[0-9a-fA-F]+`) + content := re.ReplaceAllString(string(addition.Data), "") + data := []byte(content) + addition.Data = data + } + base64Results := fc.detectFile(addition.Data, checkBase64) fillBase46DetectionResults(base64Results, addition, result) @@ -58,7 +65,7 @@ func fillResults(results []string, addition git_repo.Addition, result *Detection log.WithFields(log.Fields{ "filePath": addition.Path, }).Info(info) - if strings.Contains(string(addition.Name), talismanrcfilename) { + if string(addition.Name) == DefaultRCFileName { result.Warn(addition.Path, fmt.Sprintf(output, res)) } else { result.Fail(addition.Path, fmt.Sprintf(output, res)) @@ -79,10 +86,10 @@ func fillCreditCardDetectionResults(creditCardResults []string, addition git_rep fillResults(creditCardResults, addition, result, info, output) } -func fillHexDetectionResults(creditCardResults []string, addition git_repo.Addition, result *DetectionResults) { +func fillHexDetectionResults(hexResults []string, addition git_repo.Addition, result *DetectionResults) { const info = "Failing file as it contains a hex encoded text." const output = "Expected file to not to contain hex encoded texts such as: %s" - fillResults(creditCardResults, addition, result, info, output) + fillResults(hexResults, addition, result, info, output) } func (fc *FileContentDetector) detectFile(data []byte, getResult fn) []string { diff --git a/detector/pattern_detector.go b/detector/pattern_detector.go index 64470c9a..db5de74c 100644 --- a/detector/pattern_detector.go +++ b/detector/pattern_detector.go @@ -24,11 +24,19 @@ func (detector PatternDetector) Test(additions []git_repo.Addition, ignoreConfig detections := detector.secretsPattern.check(string(addition.Data)) for _, detection := range detections { if detection != "" { - log.WithFields(log.Fields{ - "filePath": addition.Path, - "pattern": detection, - }).Info("Failing file as it matched pattern.") - result.Fail(addition.Path, fmt.Sprintf("Potential secret pattern : %s", detection)) + if string(addition.Name) == DefaultRCFileName { + log.WithFields(log.Fields{ + "filePath": addition.Path, + "pattern": detection, + }).Warn("Warning file as it matched pattern.") + result.Warn(addition.Path, fmt.Sprintf("Potential secret pattern : %s", detection)) + } else { + log.WithFields(log.Fields{ + "filePath": addition.Path, + "pattern": detection, + }).Info("Failing file as it matched pattern.") + result.Fail(addition.Path, fmt.Sprintf("Potential secret pattern : %s", detection)) + } } } } diff --git a/runner.go b/runner.go index 2b50f050..f45ab302 100644 --- a/runner.go +++ b/runner.go @@ -33,14 +33,15 @@ func (r *Runner) RunWithoutErrors() int { return r.exitStatus() } - - func (r *Runner) doRun() { ignoresNew := detector.ReadConfigFromRCFile(readRepoFile()) detector.DefaultChain().Test(r.additions, ignoresNew, r.results) } func (r *Runner) printReport() { + if r.results.HasWarnings() { + fmt.Println(r.results.ReportWarnings()) + } if r.results.HasIgnores() || r.results.HasFailures() { fmt.Println(r.results.Report()) } From 4aabdab198672af7beb2a16bd8f859c3a3eaa6bb Mon Sep 17 00:00:00 2001 From: Harsha Yarabarla Date: Sun, 3 Feb 2019 18:54:12 +0530 Subject: [PATCH 03/13] Corrected Failures variable in DetectionResults for rendering correct html reports when scanner is used. --- detector/detection_results.go | 42 +++++++++++++---------------------- 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/detector/detection_results.go b/detector/detection_results.go index 9f291f38..8a64da8b 100644 --- a/detector/detection_results.go +++ b/detector/detection_results.go @@ -19,7 +19,7 @@ type FailureData struct { //Currently, it keeps track of failures and ignored files. //The results are grouped by FilePath for easy reporting of all detected problems with individual files. type DetectionResults struct { - failures map[git_repo.FilePath]*FailureData + Failures map[git_repo.FilePath]*FailureData ignores map[git_repo.FilePath][]string warnings map[git_repo.FilePath][]string } @@ -34,17 +34,17 @@ func NewDetectionResults() *DetectionResults { //Detectors are encouraged to provide context sensitive messages so that fixing the errors is made simple for the end user //Fail may be called multiple times for each FilePath and the calls accumulate the provided reasons func (r *DetectionResults) Fail(filePath git_repo.FilePath, message string, commits []string) { - if r.failures[filePath] == nil { - r.failures[filePath] = &FailureData{make(map[string][]string)} + if r.Failures[filePath] == nil { + r.Failures[filePath] = &FailureData{make(map[string][]string)} } - if r.failures[filePath].FailuresInCommits == nil { - r.failures[filePath].FailuresInCommits = make(map[string][]string) + if r.Failures[filePath].FailuresInCommits == nil { + r.Failures[filePath].FailuresInCommits = make(map[string][]string) } - existingCommits := r.failures[filePath].FailuresInCommits[message] + existingCommits := r.Failures[filePath].FailuresInCommits[message] if len(existingCommits) == 0 { - r.failures[filePath].FailuresInCommits[message] = commits + r.Failures[filePath].FailuresInCommits[message] = commits } else { - r.failures[filePath].FailuresInCommits[message] = append(r.failures[filePath].FailuresInCommits[message], commits...) + r.Failures[filePath].FailuresInCommits[message] = append(r.Failures[filePath].FailuresInCommits[message], commits...) } } @@ -70,7 +70,7 @@ func (r *DetectionResults) Ignore(filePath git_repo.FilePath, detector string) { //HasFailures answers if any Failures were detected for any FilePath in the current run func (r *DetectionResults) HasFailures() bool { - return len(r.failures) > 0 + return len(r.Failures) > 0 } //HasIgnores answers if any FilePaths were ignored in the current run @@ -93,7 +93,7 @@ func (r *DetectionResults) Successful() bool { //GetFailures returns the various reasons that a given FilePath was marked as failing by all the detectors in the current run func (r *DetectionResults) GetFailures(fileName git_repo.FilePath) *FailureData { - return r.failures[fileName] + return r.Failures[fileName] } func (r *DetectionResults) ReportWarnings() string { @@ -110,7 +110,7 @@ func (r *DetectionResults) ReportWarnings() string { warningData := r.ReportFileWarnings(filePath) data = append(data, warningData...) } - filePathsForWarnings = unique(filePathsForWarnings) + filePathsForWarnings = utility.UniqueItems(filePathsForWarnings) if len(r.warnings) > 0 { table.AppendBulk(data) table.Render() @@ -130,7 +130,7 @@ func (r *DetectionResults) Report() string { table.SetHeader([]string{"File", "Errors"}) table.SetRowLine(true) - for filePath := range r.failures { + for filePath := range r.Failures { filePathsForIgnoresAndFailures = append(filePathsForIgnoresAndFailures, string(filePath)) failureData := r.ReportFileFailures(filePath) data = append(data, failureData...) @@ -141,8 +141,8 @@ func (r *DetectionResults) Report() string { // ignoreData := r.ReportFileIgnores(filePath) // data = append(data, ignoreData...) } - filePathsForIgnoresAndFailures = unique(filePathsForIgnoresAndFailures) - if len(r.failures) > 0 { + filePathsForIgnoresAndFailures = utility.UniqueItems(filePathsForIgnoresAndFailures) + if len(r.Failures) > 0 { fmt.Printf("\n\x1b[1m\x1b[31mTalisman Report:\x1b[0m\x1b[0m\n") table.AppendBulk(data) table.Render() @@ -168,7 +168,7 @@ func (r *DetectionResults) suggestTalismanRC(filePaths []string) string { //ReportFileFailures adds a string to table documenting the various failures detected on the supplied FilePath by all detectors in the current run func (r *DetectionResults) ReportFileFailures(filePath git_repo.FilePath) [][]string { - failures := r.failures[filePath] + failures := r.Failures[filePath] var data [][]string if len(failures.FailuresInCommits) > 0 { for failureMessage := range failures.FailuresInCommits { @@ -204,18 +204,6 @@ func keys(aMap map[git_repo.FilePath][]string) []git_repo.FilePath { return result } -func unique(stringSlice []string) []string { - keys := make(map[string]bool) - list := []string{} - for _, entry := range stringSlice { - if _, value := keys[entry]; !value { - keys[entry] = true - list = append(list, entry) - } - } - return list -} - func NewFailureData() FailureData { return FailureData{make(map[string][]string)} } From 9f9167e705625ca7e3b97046cc6273111046bc74 Mon Sep 17 00:00:00 2001 From: Harsha Yarabarla Date: Sun, 3 Feb 2019 19:04:50 +0530 Subject: [PATCH 04/13] Added heading for warnings table. --- detector/detection_results.go | 1 + 1 file changed, 1 insertion(+) diff --git a/detector/detection_results.go b/detector/detection_results.go index 8a64da8b..47e4d9ec 100644 --- a/detector/detection_results.go +++ b/detector/detection_results.go @@ -112,6 +112,7 @@ func (r *DetectionResults) ReportWarnings() string { } filePathsForWarnings = utility.UniqueItems(filePathsForWarnings) if len(r.warnings) > 0 { + fmt.Printf("\n\x1b[1m\x1b[31mTalisman Warnings:\x1b[0m\x1b[0m\n") table.AppendBulk(data) table.Render() result = result + fmt.Sprintf("\n\x1b[33mPlease review the above file(s) to make sure that no sensitive content is being pushed\x1b[0m\n") From dd41779b497cf81ebe7f8d5aab18bd95ea7233bb Mon Sep 17 00:00:00 2001 From: Harsha Yarabarla Date: Sun, 3 Feb 2019 19:28:28 +0530 Subject: [PATCH 05/13] Removed unnecessary debug logs. --- detector/detection_results_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/detector/detection_results_test.go b/detector/detection_results_test.go index 0c2219b9..8a4d968b 100644 --- a/detector/detection_results_test.go +++ b/detector/detection_results_test.go @@ -1,7 +1,6 @@ package detector import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -36,7 +35,6 @@ func TestResultsReportsFailures(t *testing.T) { results.Fail("another_filename", "Complete & utter failure", []string{}) actualErrorReport := results.ReportFileFailures("some_filename") - fmt.Println(actualErrorReport) assert.Regexp(t, "some_filename", actualErrorReport[0][0], "Error report does not contain expected output") assert.Regexp(t, "Bomb", actualErrorReport[0][1], "Error report does not contain expected output") From 221e2b1e46a054522608fa0f31743779da4f1cde Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Mon, 18 Feb 2019 19:01:48 +0530 Subject: [PATCH 06/13] Adds functionality to generate scan report in JSON format --- .talismanrc | 3 ++ detector/detection_results.go | 29 +++++++----- detector/filecontent_detector.go | 2 +- detector/json_detection_results.go | 72 ++++++++++++++++++++++++++++++ detector/pattern_detector.go | 2 +- report/report.go | 47 ++++++++++++++++--- runner.go | 12 ++++- 7 files changed, 148 insertions(+), 19 deletions(-) create mode 100644 detector/json_detection_results.go diff --git a/.talismanrc b/.talismanrc index 515594be..0d3a7135 100644 --- a/.talismanrc +++ b/.talismanrc @@ -2,3 +2,6 @@ fileignoreconfig: - filename : private.pem checksum : ignore_detectors : [filename,filecontent] +- filename: detector/pattern_detector.go + checksum: 1c46863e979796d929522d73c465643b8794cccbf0054cb1ca6903a143e54757 + ignore_detectors: []' diff --git a/detector/detection_results.go b/detector/detection_results.go index 47e4d9ec..96af5864 100644 --- a/detector/detection_results.go +++ b/detector/detection_results.go @@ -21,12 +21,12 @@ type FailureData struct { type DetectionResults struct { Failures map[git_repo.FilePath]*FailureData ignores map[git_repo.FilePath][]string - warnings map[git_repo.FilePath][]string + warnings map[git_repo.FilePath]*FailureData } //NewDetectionResults is a new DetectionResults struct. It represents the pre-run state of a Detection run. func NewDetectionResults() *DetectionResults { - result := DetectionResults{make(map[git_repo.FilePath]*FailureData), make(map[git_repo.FilePath][]string), make(map[git_repo.FilePath][]string)} + result := DetectionResults{make(map[git_repo.FilePath]*FailureData), make(map[git_repo.FilePath][]string), make(map[git_repo.FilePath]*FailureData)} return &result } @@ -48,12 +48,18 @@ func (r *DetectionResults) Fail(filePath git_repo.FilePath, message string, comm } } -func (r *DetectionResults) Warn(filePath git_repo.FilePath, message string) { - warnings, ok := r.warnings[filePath] - if !ok { - r.warnings[filePath] = []string{message} +func (r *DetectionResults) Warn(filePath git_repo.FilePath, message string, commits []string) { + if r.warnings[filePath] == nil { + r.warnings[filePath] = &FailureData{make(map[string][]string)} + } + if r.warnings[filePath].FailuresInCommits == nil { + r.warnings[filePath].FailuresInCommits = make(map[string][]string) + } + existingCommits := r.warnings[filePath].FailuresInCommits[message] + if len(existingCommits) == 0 { + r.warnings[filePath].FailuresInCommits[message] = commits } else { - r.warnings[filePath] = append(warnings, message) + r.warnings[filePath].FailuresInCommits[message] = append(r.warnings[filePath].FailuresInCommits[message], commits...) } } @@ -185,9 +191,12 @@ func (r *DetectionResults) ReportFileFailures(filePath git_repo.FilePath) [][]st func (r *DetectionResults) ReportFileWarnings(filePath git_repo.FilePath) [][]string { warnings := r.warnings[filePath] var data [][]string - if len(warnings) > 0 { - for _, warning := range warnings { - data = append(data, []string{string(filePath), warning}) + if len(warnings.FailuresInCommits) > 0 { + for warningMessage := range warnings.FailuresInCommits { + if len(warningMessage) > 150 { + warningMessage = warningMessage[:150] + "\n" + warningMessage[150:] + } + data = append(data, []string{string(filePath), warningMessage}) } } return data diff --git a/detector/filecontent_detector.go b/detector/filecontent_detector.go index 4fac1dcb..6a72181a 100644 --- a/detector/filecontent_detector.go +++ b/detector/filecontent_detector.go @@ -66,7 +66,7 @@ func fillResults(results []string, addition git_repo.Addition, result *Detection "filePath": addition.Path, }).Info(info) if string(addition.Name) == DefaultRCFileName { - result.Warn(addition.Path, fmt.Sprintf(output, res)) + result.Warn(addition.Path, fmt.Sprintf(output, res), []string{}) } else { result.Fail(addition.Path, fmt.Sprintf(output, res), []string{}) } diff --git a/detector/json_detection_results.go b/detector/json_detection_results.go new file mode 100644 index 00000000..b2873939 --- /dev/null +++ b/detector/json_detection_results.go @@ -0,0 +1,72 @@ +package detector + +import "talisman/git_repo" + +type FailureDetails struct { + Category string `json:"type"` + Message string `json:"message"` + Commits []string `json:"commits"` +} + +type ResultsDetails struct { + Filename git_repo.FilePath `json:"filename"` + FailureList []FailureDetails `json:"failure_list"` + WarningList []FailureDetails `json:"warning_list"` +} + +type FailureTypes struct { + Filecontent int `json:"filecontent"` + Filesize int `json:"filesize"` + Filename int `json:"filename"` +} + +type ResultsSummary struct { + Types FailureTypes `json:"types"` +} + +type JsonDetectionResults struct { + Summary ResultsSummary `json:"summary"` + Results []ResultsDetails `json:"results"` + +} + +func (result JsonDetectionResults) getResultObjectForFileName(filename git_repo.FilePath) ResultsDetails { + for _, resultDetails := range result.Results { + if resultDetails.Filename == filename { + return resultDetails + } + } + return ResultsDetails{"", make([]FailureDetails, 0), make([]FailureDetails, 0)} +} + +func GetJsonSchema(r *DetectionResults) JsonDetectionResults { + + jsonResults := JsonDetectionResults{} + failures := r.Failures + for path, data := range failures { + resultDetails := ResultsDetails{} + resultDetails.Filename = path + + for message, commits := range data.FailuresInCommits { + failureDetails := FailureDetails{} + failureDetails.Message = message + failureDetails.Commits = commits + resultDetails.FailureList = append(resultDetails.FailureList, failureDetails) + } + jsonResults.Results = append(jsonResults.Results, resultDetails) + } + warnings := r.warnings + for path, data := range warnings { + resultDetails := jsonResults.getResultObjectForFileName(path) + resultDetails.Filename = path + + for message, commits := range data.FailuresInCommits { + failureDetails := FailureDetails{} + failureDetails.Message = message + failureDetails.Commits = commits + resultDetails.WarningList = append(resultDetails.WarningList, failureDetails) + } + } + return jsonResults +} + diff --git a/detector/pattern_detector.go b/detector/pattern_detector.go index e30dea3e..566123ca 100644 --- a/detector/pattern_detector.go +++ b/detector/pattern_detector.go @@ -29,7 +29,7 @@ func (detector PatternDetector) Test(additions []git_repo.Addition, ignoreConfig "filePath": addition.Path, "pattern": detection, }).Warn("Warning file as it matched pattern.") - result.Warn(addition.Path, fmt.Sprintf("Potential secret pattern : %s", detection)) + result.Warn(addition.Path, fmt.Sprintf("Potential secret pattern : %s", detection), addition.Commits) } else { log.WithFields(log.Fields{ "filePath": addition.Path, diff --git a/report/report.go b/report/report.go index e4f142ca..7e05cf79 100644 --- a/report/report.go +++ b/report/report.go @@ -1,24 +1,61 @@ package report import ( + "encoding/json" + "fmt" "html/template" "log" "os" + "path/filepath" + "strings" "talisman/detector" ) +const htmlFileName string = "Reports/report.html" +const jsonFileName string = "Reports/report.json" // GenerateReport generates a talisman scan report in html format -func GenerateReport(r *detector.DetectionResults) { +func GenerateReport(r *detector.DetectionResults, directory string) { + + var path string + var htmlFilePath strings.Builder + var jsonFilePath strings.Builder + if directory == "" { + path = "Reports" + htmlFilePath.WriteString(htmlFileName) + jsonFilePath.WriteString(jsonFileName) + } else { + path = filepath.Join(directory, "/Reports") + htmlFilePath.WriteString(directory) + htmlFilePath.WriteString("/") + htmlFilePath.WriteString(htmlFileName) + jsonFilePath.WriteString(directory) + jsonFilePath.WriteString("/") + jsonFilePath.WriteString(jsonFileName) + } + fmt.Println(os.MkdirAll(path, 0755)) + reportHTML := getReportHTML() reportTemplate := template.New("report") reportTemplate, _ = reportTemplate.Parse(reportHTML) + htmlFile, err := os.Create(htmlFilePath.String()) + if err != nil { + log.Fatal("Cannot create report.html file", err) + } + reportTemplate.ExecuteTemplate(htmlFile, "report", r) + htmlFile.Close() + + jsonFile, err := os.Create(jsonFilePath.String()) + if err != nil { + log.Fatal("Cannot create report.json file", err) - file, err := os.Create("report.html") + } + jsonResultSchema := detector.GetJsonSchema(r) + jsonString, err := json.Marshal(jsonResultSchema) if err != nil { - log.Fatal("Cannot create file", err) + log.Fatal("Unable to marshal JSON") } - reportTemplate.ExecuteTemplate(file, "report", r) - file.Close() + jsonFile.Write(jsonString) + jsonFile.Close() } func getReportHTML() string { diff --git a/runner.go b/runner.go index e0391276..6743cc39 100644 --- a/runner.go +++ b/runner.go @@ -1,8 +1,10 @@ package main import ( + "bufio" "fmt" "os" + "strings" "talisman/checksumcalculator" "talisman/detector" "talisman/git_repo" @@ -38,12 +40,18 @@ func (r *Runner) RunWithoutErrors() int { //Scan scans git commit history for potential secrets and returns 0 or 1 as exit code func (r *Runner) Scan() int { + + fmt.Println("Please enter the directory where you want to save the scan results (Press enter if you want to save the scan results in the current directory) : ") + reader := bufio.NewReader(os.Stdin) + directory, _ := reader.ReadString('\n') + directory = strings.Replace(directory, "\n", "", -1) + fmt.Println("Please wait while talisman scans entire repository including the git history...") additions := scanner.GetAdditions() ignores := detector.TalismanRCIgnore{} detector.DefaultChain().Test(additions, ignores, r.results) - report.GenerateReport(r.results) - fmt.Println("Please check report.html in your current directory for the talisman scan report") + report.GenerateReport(r.results, directory) + fmt.Println("Please check 'Reports' in the directory you selected for the talisman scan report") return r.exitStatus() } From 5f43eea6119b471ef83fdef862faaba9884b03f0 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Mon, 18 Feb 2019 19:02:00 +0530 Subject: [PATCH 07/13] Adds functionality to generate scan report in JSON format This commit adds the below functionalities: - Generate scan report in JSON format, to be stored in report.json file. - Ask user for the directory where the reports need to be stored --- .talismanrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.talismanrc b/.talismanrc index 0d3a7135..e864ae33 100644 --- a/.talismanrc +++ b/.talismanrc @@ -4,4 +4,4 @@ fileignoreconfig: ignore_detectors : [filename,filecontent] - filename: detector/pattern_detector.go checksum: 1c46863e979796d929522d73c465643b8794cccbf0054cb1ca6903a143e54757 - ignore_detectors: []' + ignore_detectors: [] From 87018281a2af8c352df22b9c39d8cfc964e6dfcb Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Tue, 19 Feb 2019 14:22:59 +0530 Subject: [PATCH 08/13] Modified the name of reports folder --- report/report.go | 8 ++++---- runner.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/report/report.go b/report/report.go index 7e05cf79..63ab3261 100644 --- a/report/report.go +++ b/report/report.go @@ -11,8 +11,8 @@ import ( "talisman/detector" ) -const htmlFileName string = "Reports/report.html" -const jsonFileName string = "Reports/report.json" +const htmlFileName string = "talisman_reports/report.html" +const jsonFileName string = "talisman_reports/report.json" // GenerateReport generates a talisman scan report in html format func GenerateReport(r *detector.DetectionResults, directory string) { @@ -20,11 +20,11 @@ func GenerateReport(r *detector.DetectionResults, directory string) { var htmlFilePath strings.Builder var jsonFilePath strings.Builder if directory == "" { - path = "Reports" + path = "talisman_reports" htmlFilePath.WriteString(htmlFileName) jsonFilePath.WriteString(jsonFileName) } else { - path = filepath.Join(directory, "/Reports") + path = filepath.Join(directory, "/talisman_reports") htmlFilePath.WriteString(directory) htmlFilePath.WriteString("/") htmlFilePath.WriteString(htmlFileName) diff --git a/runner.go b/runner.go index 6743cc39..c1353048 100644 --- a/runner.go +++ b/runner.go @@ -51,7 +51,7 @@ func (r *Runner) Scan() int { ignores := detector.TalismanRCIgnore{} detector.DefaultChain().Test(additions, ignores, r.results) report.GenerateReport(r.results, directory) - fmt.Println("Please check 'Reports' in the directory you selected for the talisman scan report") + fmt.Println("Please check 'talisman_reports' folder in the directory you selected for the talisman scan report") return r.exitStatus() } From 004fa846f64fa527e7e8ad78284c500af0e72ea7 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Tue, 19 Feb 2019 17:57:26 +0530 Subject: [PATCH 09/13] Adds functionality to save reports in custom location --- README.md | 10 ++++++++++ report/report.go | 6 +++--- runner.go | 13 +++---------- talisman.go | 7 ++++++- 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 6f47b40b..6be8dfe0 100644 --- a/README.md +++ b/README.md @@ -310,6 +310,16 @@ To run the scanner please "cd" into the directory to be scanned and run the foll * `talisman --scan` +Running this command will create a folder named talisman_reports in the root of the current directory and store the report files there. + +In case you want to store the reports in some other location, it can be provided as an option with the command: + +* `talisman --scan --reportdirectory=/Users/username/Desktop` + + OR + +* `talisman --scan --rd=/Users/username/Desktop` + Talisman currently does not support ignoring of files for scanning. # Uninstallation diff --git a/report/report.go b/report/report.go index 63ab3261..97a56b7d 100644 --- a/report/report.go +++ b/report/report.go @@ -2,7 +2,6 @@ package report import ( "encoding/json" - "fmt" "html/template" "log" "os" @@ -14,7 +13,7 @@ import ( const htmlFileName string = "talisman_reports/report.html" const jsonFileName string = "talisman_reports/report.json" // GenerateReport generates a talisman scan report in html format -func GenerateReport(r *detector.DetectionResults, directory string) { +func GenerateReport(r *detector.DetectionResults, directory string) string { var path string var htmlFilePath strings.Builder @@ -32,7 +31,7 @@ func GenerateReport(r *detector.DetectionResults, directory string) { jsonFilePath.WriteString("/") jsonFilePath.WriteString(jsonFileName) } - fmt.Println(os.MkdirAll(path, 0755)) + os.MkdirAll(path, 0755) reportHTML := getReportHTML() reportTemplate := template.New("report") @@ -56,6 +55,7 @@ func GenerateReport(r *detector.DetectionResults, directory string) { } jsonFile.Write(jsonString) jsonFile.Close() + return path } func getReportHTML() string { diff --git a/runner.go b/runner.go index c1353048..a743f023 100644 --- a/runner.go +++ b/runner.go @@ -1,10 +1,8 @@ package main import ( - "bufio" "fmt" "os" - "strings" "talisman/checksumcalculator" "talisman/detector" "talisman/git_repo" @@ -39,19 +37,14 @@ func (r *Runner) RunWithoutErrors() int { } //Scan scans git commit history for potential secrets and returns 0 or 1 as exit code -func (r *Runner) Scan() int { - - fmt.Println("Please enter the directory where you want to save the scan results (Press enter if you want to save the scan results in the current directory) : ") - reader := bufio.NewReader(os.Stdin) - directory, _ := reader.ReadString('\n') - directory = strings.Replace(directory, "\n", "", -1) +func (r *Runner) Scan(reportDirectory string) int { fmt.Println("Please wait while talisman scans entire repository including the git history...") additions := scanner.GetAdditions() ignores := detector.TalismanRCIgnore{} detector.DefaultChain().Test(additions, ignores, r.results) - report.GenerateReport(r.results, directory) - fmt.Println("Please check 'talisman_reports' folder in the directory you selected for the talisman scan report") + reportsPath := report.GenerateReport(r.results, reportDirectory) + fmt.Printf("Please check %s folder for the talisman scan report", reportsPath) return r.exitStatus() } diff --git a/talisman.go b/talisman.go index bf660486..24dd540a 100644 --- a/talisman.go +++ b/talisman.go @@ -22,6 +22,7 @@ var ( Version = "Development Build" scan bool checksum string + reportdirectory string ) const ( @@ -41,6 +42,7 @@ type options struct { pattern string scan bool checksum string + reportdirectory string } //Logger is the default log device, set to emit at the Error level by default @@ -56,6 +58,8 @@ func main() { flag.BoolVar(&scan, "scan", false, "scanner scans the git commit history for potential secrets") flag.StringVar(&checksum, "c", "", "short form of checksum calculator") flag.StringVar(&checksum, "checksum", "", "checksum calculator calculates checksum and suggests .talsimarc format") + flag.StringVar(&reportdirectory, "reportdirectory", "", "directory where the scan reports will be stored") + flag.StringVar(&reportdirectory, "rd", "", "short form of report directory") flag.Parse() @@ -75,6 +79,7 @@ func main() { pattern: pattern, scan: scan, checksum: checksum, + reportdirectory: reportdirectory, } os.Exit(run(os.Stdin, _options)) @@ -97,7 +102,7 @@ func run(stdin io.Reader, _options options) (returnCode int) { return NewRunner(make([]git_repo.Addition, 0)).RunChecksumCalculator(strings.Fields(_options.checksum)) } else if _options.scan { log.Infof("Running scanner") - return NewRunner(make([]git_repo.Addition, 0)).Scan() + return NewRunner(make([]git_repo.Addition, 0)).Scan(_options.reportdirectory) } else if _options.pattern != "" { log.Infof("Running %s pattern", _options.pattern) directoryHook := NewDirectoryHook() From 0db92121f425a14fe4cb97b847f966e7ee306613 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Wed, 20 Feb 2019 17:02:43 +0530 Subject: [PATCH 10/13] Implemented code review comments --- detector/json_detection_results.go | 12 ++++++------ report/report.go | 23 +++++++---------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/detector/json_detection_results.go b/detector/json_detection_results.go index b2873939..aa32a0b0 100644 --- a/detector/json_detection_results.go +++ b/detector/json_detection_results.go @@ -2,7 +2,7 @@ package detector import "talisman/git_repo" -type FailureDetails struct { +type Details struct { Category string `json:"type"` Message string `json:"message"` Commits []string `json:"commits"` @@ -10,8 +10,8 @@ type FailureDetails struct { type ResultsDetails struct { Filename git_repo.FilePath `json:"filename"` - FailureList []FailureDetails `json:"failure_list"` - WarningList []FailureDetails `json:"warning_list"` + FailureList []Details `json:"failure_list"` + WarningList []Details `json:"warning_list"` } type FailureTypes struct { @@ -36,7 +36,7 @@ func (result JsonDetectionResults) getResultObjectForFileName(filename git_repo. return resultDetails } } - return ResultsDetails{"", make([]FailureDetails, 0), make([]FailureDetails, 0)} + return ResultsDetails{"", make([]Details, 0), make([]Details, 0)} } func GetJsonSchema(r *DetectionResults) JsonDetectionResults { @@ -48,7 +48,7 @@ func GetJsonSchema(r *DetectionResults) JsonDetectionResults { resultDetails.Filename = path for message, commits := range data.FailuresInCommits { - failureDetails := FailureDetails{} + failureDetails := Details{} failureDetails.Message = message failureDetails.Commits = commits resultDetails.FailureList = append(resultDetails.FailureList, failureDetails) @@ -61,7 +61,7 @@ func GetJsonSchema(r *DetectionResults) JsonDetectionResults { resultDetails.Filename = path for message, commits := range data.FailuresInCommits { - failureDetails := FailureDetails{} + failureDetails := Details{} failureDetails.Message = message failureDetails.Commits = commits resultDetails.WarningList = append(resultDetails.WarningList, failureDetails) diff --git a/report/report.go b/report/report.go index 97a56b7d..e85ea1d2 100644 --- a/report/report.go +++ b/report/report.go @@ -6,7 +6,6 @@ import ( "log" "os" "path/filepath" - "strings" "talisman/detector" ) @@ -16,23 +15,15 @@ const jsonFileName string = "talisman_reports/report.json" func GenerateReport(r *detector.DetectionResults, directory string) string { var path string - var htmlFilePath strings.Builder - var jsonFilePath strings.Builder - if directory == "" { - path = "talisman_reports" - htmlFilePath.WriteString(htmlFileName) - jsonFilePath.WriteString(jsonFileName) - } else { - path = filepath.Join(directory, "/talisman_reports") - htmlFilePath.WriteString(directory) - htmlFilePath.WriteString("/") - htmlFilePath.WriteString(htmlFileName) - jsonFilePath.WriteString(directory) - jsonFilePath.WriteString("/") - jsonFilePath.WriteString(jsonFileName) - } + var htmlFilePath string + var jsonFilePath string + + path = filepath.Join(directory, "talisman_reports") + htmlFilePath = filepath.Join(directory, htmlFileName) + jsonFilePath = filepath.Join(directory, jsonFileName) os.MkdirAll(path, 0755) + reportHTML := getReportHTML() reportTemplate := template.New("report") reportTemplate, _ = reportTemplate.Parse(reportHTML) From adb2f8b3067dbe1c3d7f9bf53a2fa98e9b387dc5 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Wed, 20 Feb 2019 17:33:36 +0530 Subject: [PATCH 11/13] Fixed build failure --- report/report.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/report/report.go b/report/report.go index e85ea1d2..729c783d 100644 --- a/report/report.go +++ b/report/report.go @@ -27,14 +27,14 @@ func GenerateReport(r *detector.DetectionResults, directory string) string { reportHTML := getReportHTML() reportTemplate := template.New("report") reportTemplate, _ = reportTemplate.Parse(reportHTML) - htmlFile, err := os.Create(htmlFilePath.String()) + htmlFile, err := os.Create(htmlFilePath) if err != nil { log.Fatal("Cannot create report.html file", err) } reportTemplate.ExecuteTemplate(htmlFile, "report", r) htmlFile.Close() - jsonFile, err := os.Create(jsonFilePath.String()) + jsonFile, err := os.Create(jsonFilePath) if err != nil { log.Fatal("Cannot create report.json file", err) From 8fa8cff8198ecdb456f371a6daa58da12ef9378a Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Wed, 20 Feb 2019 22:01:21 +0530 Subject: [PATCH 12/13] Updated the directory name for reports folder --- report/report.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/report/report.go b/report/report.go index 729c783d..a93f4720 100644 --- a/report/report.go +++ b/report/report.go @@ -9,8 +9,9 @@ import ( "talisman/detector" ) -const htmlFileName string = "talisman_reports/report.html" -const jsonFileName string = "talisman_reports/report.json" +const reportsFolder = "talisman_reports" +const htmlFileName string = "report.html" +const jsonFileName string = "report.json" // GenerateReport generates a talisman scan report in html format func GenerateReport(r *detector.DetectionResults, directory string) string { @@ -19,8 +20,8 @@ func GenerateReport(r *detector.DetectionResults, directory string) string { var jsonFilePath string path = filepath.Join(directory, "talisman_reports") - htmlFilePath = filepath.Join(directory, htmlFileName) - jsonFilePath = filepath.Join(directory, jsonFileName) + htmlFilePath = filepath.Join(directory, reportsFolder, htmlFileName) + jsonFilePath = filepath.Join(directory, reportsFolder, jsonFileName) os.MkdirAll(path, 0755) From 6bd7ceb30d877424e0da94569e7221306b3f8ba7 Mon Sep 17 00:00:00 2001 From: Aaquib Zama Date: Tue, 5 Mar 2019 12:49:12 +0530 Subject: [PATCH 13/13] Modified the scan logic for pre-commit hooks The scan logic has now been updated to scan only the diff for each file if Talisman is being used as a pre-commit hook. For pre-push hook and scan functionalities, Talisman will continue to scan the whole file. --- README.md | 7 ++++-- acceptance_test.go | 46 +++++++++++++++++++++++++++++++++++--- git_repo/git_repo.go | 29 ++++++++++++++++++++++++ git_testing/git_testing.go | 8 +++++-- pre_commit_hook.go | 2 +- 5 files changed, 84 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 6be8dfe0..8cb0ba52 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Find the instructions below. ## [Recommended approach] ## Installation as a global hook template -We recommend installing Talisman as a git hook template, as that will cause +We recommend installing Talisman as a **pre-commit git hook template**, as that will cause Talisman to be present, not only in your existing git repositories, but also in any new repository that you 'init' or 'clone'. @@ -226,6 +226,10 @@ In the above example, the file *danger.pem* has been flagged as a security breac * The filename matches one of the pre-configured patterns. * The file contains an awsSecretKey which is scanned and flagged by Talisman +If you have installed Talisman as a pre-commit hook, it will scan only the _diff_ within each commit. This means that it would only report errors for parts of the file that were changed. + +In case you have installed Talisman as a pre-push hook, it will scan the complete file in which changes are made. As mentioned above, it is recommended that you use Talisman as a **pre-commit hook**. + ## Validations The following detectors execute against the changesets to detect secrets/sensitive information: @@ -321,7 +325,6 @@ In case you want to store the reports in some other location, it can be provided * `talisman --scan --rd=/Users/username/Desktop` Talisman currently does not support ignoring of files for scanning. - # Uninstallation The uninstallation process depends on how you had installed Talisman. You could have chosen to install as a global hook template or at a single repository. diff --git a/acceptance_test.go b/acceptance_test.go index 41917800..d0f9940e 100644 --- a/acceptance_test.go +++ b/acceptance_test.go @@ -56,6 +56,15 @@ func TestAddingSimpleFileShouldExitZero(t *testing.T) { }) } +func TestShouldExitZeroIfFileNameIsIgnoredAndNoOtherSensitiveContentIsFound(t *testing.T) { + withNewTmpGitRepo(func(git *git_testing.GitTesting) { + git.SetupBaselineFiles("danger.pem") + git.AddAndcommit("*", "add private key") + + assert.Equal(t, 1, runTalisman(git), "Expected run() to return 1 and fail as pem file was present in the repo") + }) +} + func TestAddingSecretKeyShouldExitOne(t *testing.T) { withNewTmpGitRepo(func(git *git_testing.GitTesting) { git.SetupBaselineFiles("simple-file") @@ -93,13 +102,13 @@ func TestAddingSecretKeyShouldExitOneIfPEMFileIsPresentInTheGitHistory(t *testin _options := options{ debug: false, githook: PrePush, - scan: true, + scan: false, } git.SetupBaselineFiles("simple-file") git.CreateFileWithContents("private.pem", "secret") git.CreateFileWithContents(".talismanrc", talismanRCDataWithFileNameAndCorrectChecksum) git.AddAndcommit("private.pem", "add private key") - assert.Equal(t, 1, runTalismanWithOptions(git, _options), "Expected run() to return 0 and pass as pem file was ignored") + assert.Equal(t, 0, runTalismanWithOptions(git, _options), "Expected run() to return 0 and pass as pem file was ignored") }) } @@ -108,7 +117,7 @@ func TestScanningSimpleFileShouldExitZero(t *testing.T) { _options := options{ debug: false, githook: PrePush, - scan: true, + scan: false, } git.SetupBaselineFiles("simple-file") assert.Equal(t, 0, runTalismanWithOptions(git, _options), "Expected run() to return 0 and pass as pem file was ignored") @@ -130,6 +139,37 @@ func TestChecksumCalculatorShouldExitOne(t *testing.T) { }) } +func TestShouldExitOneWhenSecretIsCommitted(t *testing.T) { + withNewTmpGitRepo(func(git *git_testing.GitTesting) { + _options := options{ + debug: false, + githook: PreCommit, + scan: false, + } + git.SetupBaselineFiles("simple-file") + git.CreateFileWithContents("sample.txt", "password=somepassword \n") + git.Add("*") + assert.Equal(t, 1, runTalismanWithOptions(git, _options), "Expected run() to return 1 as given patterns are found") + }) +} + +func TestShouldExitZeroWhenNonSecretIsCommittedButFileContainsSecretPreviously(t *testing.T) { + withNewTmpGitRepo(func(git *git_testing.GitTesting) { + _options := options{ + debug: false, + githook: PreCommit, + scan: false, + } + git.SetupBaselineFiles("simple-file") + git.CreateFileWithContents("sample.txt", "password=somepassword \n") + git.AddAndcommit("*", "Initial Commit With Secret") + + git.AppendFileContent("sample.txt", "some text \n") + git.Add("*") + assert.Equal(t, 0, runTalismanWithOptions(git, _options), "Expected run() to return 1 as given patterns are found") + }) +} + // Need to work on this test case as talismanrc does not yet support comments // func TestAddingSecretKeyShouldExitZeroIfPEMFilesAreIgnoredAndCommented(t *testing.T) { // withNewTmpGitRepo(func(git *git_testing.GitTesting) { diff --git a/git_repo/git_repo.go b/git_repo/git_repo.go index 8d1f0978..637d838c 100644 --- a/git_repo/git_repo.go +++ b/git_repo/git_repo.go @@ -38,6 +38,21 @@ func RepoLocatedAt(path string) GitRepo { return GitRepo{absoluteRoot} } +//Gets all the staged files and collects the diff section in each file +func (repo GitRepo) GetDiffForStagedFiles() []Addition { + files := repo.stagedFiles() + result := make([]Addition, len(files)) + for i, file := range files { + data := repo.fetchStagedDiff(file) + result[i] = NewAddition(file, data) + } + + log.WithFields(log.Fields{ + "additions": result, + }).Info("Generating staged additions.") + return result +} + func (repo GitRepo) StagedAdditions() []Addition { files := repo.stagedFiles() result := make([]Addition, len(files)) @@ -208,6 +223,20 @@ func (repo *GitRepo) fetchStagedChanges() string { return string(repo.executeRepoCommand("git", "diff", "--cached", "--name-status", "--diff-filter=ACM")) } +//Fetches the currently staged diff and filters the command output to get only the modified sections of the file +func (repo *GitRepo) fetchStagedDiff(fileName string) []byte { + var result []byte + changes := strings.Split(string(repo.executeRepoCommand("git", "diff", "--staged", fileName)), "\n") + for _, c := range changes { + if !strings.HasPrefix(c, "+++") && !strings.HasPrefix(c, "---") && strings.HasPrefix(c, "+") { + + result = append(result, strings.TrimPrefix(c, "+")...) + result = append(result, "\n"...) + } + } + return result +} + func (repo GitRepo) fetchRawOutgoingDiff(oldCommit string, newCommit string) string { gitRange := oldCommit + ".." + newCommit return string(repo.executeRepoCommand("git", "diff", gitRange, "--name-only", "--diff-filter=ACM")) diff --git a/git_testing/git_testing.go b/git_testing/git_testing.go index 9bb3e874..8aa38dc4 100644 --- a/git_testing/git_testing.go +++ b/git_testing/git_testing.go @@ -107,14 +107,18 @@ func (git *GitTesting) FileContents(filePath string) []byte { } func (git *GitTesting) AddAndcommit(fileName string, message string) { - git.ExecCommand("git", "add", fileName) - git.ExecCommand("git", "commit", fileName, "-m", message) + git.Add(fileName) + git.Commit(fileName, message) } func (git *GitTesting) Add(fileName string) { git.ExecCommand("git", "add", fileName) } +func (git *GitTesting) Commit(fileName string, message string) { + git.ExecCommand("git", "commit", fileName, "-m", message) +} + func (git *GitTesting) GetBlobDetails(fileName string) string { var output []byte object_hash_and_filename := "" diff --git a/pre_commit_hook.go b/pre_commit_hook.go index 23bfbb21..af73e744 100644 --- a/pre_commit_hook.go +++ b/pre_commit_hook.go @@ -15,5 +15,5 @@ func NewPreCommitHook() *PreCommitHook { func (p *PreCommitHook) GetRepoAdditions() []git_repo.Addition { wd, _ := os.Getwd() repo := git_repo.RepoLocatedAt(wd) - return repo.StagedAdditions() + return repo.GetDiffForStagedFiles() }