From cc4949465b6730ee398e49a096e0132f02078372 Mon Sep 17 00:00:00 2001 From: laurentsimon <64505099+laurentsimon@users.noreply.github.com> Date: Tue, 16 Nov 2021 11:57:14 -0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20[Check=20split]:=20Binary-Artifacts?= =?UTF-8?q?=20(#1244)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * split binary artifact check * fix * missing file * comments * linter * fix * comments * linter --- checks/binary_artifact.go | 88 +------------ checks/dangerous_workflow.go | 6 +- checks/dependency_update_tool.go | 7 +- checks/evaluation/binary_artifacts.go | 44 +++++++ checks/fileparser/errors.go | 5 +- .../{file_utils.go => fileparser/listing.go} | 55 +++++++- checks/fuzzing.go | 9 +- checks/permissions.go | 6 +- checks/pinned_dependencies.go | 43 ++++--- checks/raw/binary_artifact.go | 117 ++++++++++++++++++ checks/security_policy.go | 13 +- 11 files changed, 270 insertions(+), 123 deletions(-) create mode 100644 checks/evaluation/binary_artifacts.go rename checks/{file_utils.go => fileparser/listing.go} (79%) create mode 100644 checks/raw/binary_artifact.go diff --git a/checks/binary_artifact.go b/checks/binary_artifact.go index caae4ac7..521e75fe 100644 --- a/checks/binary_artifact.go +++ b/checks/binary_artifact.go @@ -15,14 +15,9 @@ package checks import ( - "fmt" - "path/filepath" - "strings" - - "github.com/h2non/filetype" - "github.com/h2non/filetype/types" - "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/evaluation" + "github.com/ossf/scorecard/v3/checks/raw" sce "github.com/ossf/scorecard/v3/errors" ) @@ -34,86 +29,13 @@ func init() { registerCheck(CheckBinaryArtifacts, BinaryArtifacts) } -// BinaryArtifacts will check the repository if it contains binary artifacts. +// BinaryArtifacts will check the repository contains binary artifacts. func BinaryArtifacts(c *checker.CheckRequest) checker.CheckResult { - var binFound bool - err := CheckFilesContent("*", false, c, checkBinaryFileContent, &binFound) + rawData, err := raw.BinaryArtifacts(c) if err != nil { e := sce.WithMessage(sce.ErrScorecardInternal, err.Error()) return checker.CreateRuntimeErrorResult(CheckBinaryArtifacts, e) } - if binFound { - return checker.CreateMinScoreResult(CheckBinaryArtifacts, "binaries present in source code") - } - return checker.CreateMaxScoreResult(CheckBinaryArtifacts, "no binaries found in the repo") -} - -func checkBinaryFileContent(path string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { - pfound := FileGetCbDataAsBoolPointer(data) - binaryFileTypes := map[string]bool{ - "crx": true, - "deb": true, - "dex": true, - "dey": true, - "elf": true, - "bin": true, - "o": true, - "so": true, - "iso": true, - "class": true, - "jar": true, - "bundle": true, - "dylib": true, - "lib": true, - "msi": true, - "acm": true, - "ax": true, - "cpl": true, - "dll": true, - "drv": true, - "efi": true, - "exe": true, - "mui": true, - "ocx": true, - "scr": true, - "sys": true, - "tsp": true, - "pyc": true, - "pyo": true, - "par": true, - "rpm": true, - "swf": true, - "torrent": true, - "cab": true, - "whl": true, - } - var t types.Type - var err error - if len(content) == 0 { - return true, nil - } - if t, err = filetype.Get(content); err != nil { - return false, sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("filetype.Get:%v", err)) - } - - if _, ok := binaryFileTypes[t.Extension]; ok { - dl.Warn3(&checker.LogMessage{ - Path: path, Type: checker.FileTypeBinary, - Text: "binary detected", - }) - *pfound = true - return true, nil - } else if _, ok := binaryFileTypes[strings.ReplaceAll(filepath.Ext(path), ".", "")]; ok { - // Falling back to file based extension. - dl.Warn3(&checker.LogMessage{ - Path: path, Type: checker.FileTypeBinary, - Text: "binary detected", - }) - *pfound = true - return true, nil - } - - return true, nil + return evaluation.BinaryArtifacts(CheckBinaryArtifacts, c.Dlogger, &rawData) } diff --git a/checks/dangerous_workflow.go b/checks/dangerous_workflow.go index 52575d4c..68e93d23 100644 --- a/checks/dangerous_workflow.go +++ b/checks/dangerous_workflow.go @@ -46,14 +46,14 @@ func DangerousWorkflow(c *checker.CheckRequest) checker.CheckResult { data := patternCbData{ workflowPattern: make(map[string]bool), } - err := CheckFilesContent(".github/workflows/*", false, + err := fileparser.CheckFilesContent(".github/workflows/*", false, c, validateGitHubActionWorkflowPatterns, &data) return createResultForDangerousWorkflowPatterns(data, err) } // Check file content. func validateGitHubActionWorkflowPatterns(path string, content []byte, dl checker.DetailLogger, - data FileCbData) (bool, error) { + data fileparser.FileCbData) (bool, error) { if !fileparser.IsWorkflowFile(path) { return true, nil } @@ -65,7 +65,7 @@ func validateGitHubActionWorkflowPatterns(path string, content []byte, dl checke panic("invalid type") } - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { return true, nil } diff --git a/checks/dependency_update_tool.go b/checks/dependency_update_tool.go index 70387b27..76e576cd 100644 --- a/checks/dependency_update_tool.go +++ b/checks/dependency_update_tool.go @@ -18,6 +18,7 @@ import ( "strings" "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/fileparser" sce "github.com/ossf/scorecard/v3/errors" ) @@ -32,7 +33,7 @@ func init() { // UsesDependencyUpdateTool will check the repository uses a dependency update tool. func UsesDependencyUpdateTool(c *checker.CheckRequest) checker.CheckResult { var r bool - err := CheckIfFileExists(CheckDependencyUpdateTool, c, fileExists, &r) + err := fileparser.CheckIfFileExists(CheckDependencyUpdateTool, c, fileExists, &r) if err != nil { e := sce.WithMessage(sce.ErrScorecardInternal, err.Error()) return checker.CreateRuntimeErrorResult(CheckDependencyUpdateTool, e) @@ -54,8 +55,8 @@ func UsesDependencyUpdateTool(c *checker.CheckRequest) checker.CheckResult { } // fileExists will validate the if frozen dependencies file name exists. -func fileExists(name string, dl checker.DetailLogger, data FileCbData) (bool, error) { - pdata := FileGetCbDataAsBoolPointer(data) +func fileExists(name string, dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { + pdata := fileparser.FileGetCbDataAsBoolPointer(data) switch strings.ToLower(name) { case ".github/dependabot.yml": diff --git a/checks/evaluation/binary_artifacts.go b/checks/evaluation/binary_artifacts.go new file mode 100644 index 00000000..045101f6 --- /dev/null +++ b/checks/evaluation/binary_artifacts.go @@ -0,0 +1,44 @@ +// Copyright 2021 Security Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package evaluation + +import ( + "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/raw" + sce "github.com/ossf/scorecard/v3/errors" +) + +// BinaryArtifacts applies the score policy for the Binary-Artiacts check. +func BinaryArtifacts(name string, dl checker.DetailLogger, + r *raw.BinaryArtifactData) checker.CheckResult { + if r == nil { + e := sce.WithMessage(sce.ErrScorecardInternal, "empty raw data") + return checker.CreateRuntimeErrorResult(name, e) + } + + // Apply the policy evaluation. + if r.Files == nil || len(r.Files) == 0 { + return checker.CreateMaxScoreResult(name, "no binaries found in the repo") + } + + for _, f := range r.Files { + dl.Warn3(&checker.LogMessage{ + Path: f.Path, Type: checker.FileTypeBinary, + Text: "binary detected", + }) + } + + return checker.CreateMinScoreResult(name, "binaries present in source code") +} diff --git a/checks/fileparser/errors.go b/checks/fileparser/errors.go index 4e4a5abd..2ca8f1e0 100644 --- a/checks/fileparser/errors.go +++ b/checks/fileparser/errors.go @@ -18,4 +18,7 @@ import ( "errors" ) -var errInvalidGitHubWorkflow = errors.New("invalid GitHub workflow") +var ( + errInvalidGitHubWorkflow = errors.New("invalid GitHub workflow") + errInternalFilenameMatch = errors.New("filename match error") +) diff --git a/checks/file_utils.go b/checks/fileparser/listing.go similarity index 79% rename from checks/file_utils.go rename to checks/fileparser/listing.go index 8a2ef779..c1689567 100644 --- a/checks/file_utils.go +++ b/checks/fileparser/listing.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package checks +package fileparser import ( "bufio" @@ -21,6 +21,7 @@ import ( "strings" "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/clients" sce "github.com/ossf/scorecard/v3/errors" ) @@ -115,6 +116,58 @@ func CheckFilesContent(shellPathFnPattern string, return nil } +// FileContentCbV6 is the callback. +// The bool returned indicates whether the CheckFilesContent2 +// should continue iterating over files or not. +type FileContentCbV6 func(path string, content []byte, data FileCbData) (bool, error) + +// CheckFilesContentV6 is the same as CheckFilesContent +// but for use with separated check/policy code. +func CheckFilesContentV6(shellPathFnPattern string, + caseSensitive bool, + repoClient clients.RepoClient, + onFileContent FileContentCbV6, + data FileCbData, +) error { + predicate := func(filepath string) (bool, error) { + // Filter out test files. + if isTestdataFile(filepath) { + return false, nil + } + // Filter out files based on path/names using the pattern. + b, err := isMatchingPath(shellPathFnPattern, filepath, caseSensitive) + if err != nil { + return false, err + } + return b, nil + } + + matchedFiles, err := repoClient.ListFiles(predicate) + if err != nil { + // nolint: wrapcheck + return err + } + + for _, file := range matchedFiles { + content, err := repoClient.GetFileContent(file) + if err != nil { + //nolint + return err + } + + continueIter, err := onFileContent(file, content, data) + if err != nil { + return err + } + + if !continueIter { + break + } + } + + return nil +} + // FileCb represents a callback fn. type FileCb func(path string, dl checker.DetailLogger, data FileCbData) (bool, error) diff --git a/checks/fuzzing.go b/checks/fuzzing.go index d71de4c1..9159df6b 100644 --- a/checks/fuzzing.go +++ b/checks/fuzzing.go @@ -21,6 +21,7 @@ import ( "go.uber.org/zap" "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/fileparser" "github.com/ossf/scorecard/v3/clients" "github.com/ossf/scorecard/v3/clients/githubrepo" sce "github.com/ossf/scorecard/v3/errors" @@ -44,13 +45,13 @@ func init() { func checkCFLite(c *checker.CheckRequest) (bool, error) { result := false - e := CheckFilesContent(".clusterfuzzlite/Dockerfile", true, c, - func(path string, content []byte, dl checker.DetailLogger, data FileCbData) (bool, error) { - result = CheckFileContainsCommands(content, "#") + e := fileparser.CheckFilesContent(".clusterfuzzlite/Dockerfile", true, c, + func(path string, content []byte, dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { + result = fileparser.CheckFileContainsCommands(content, "#") return false, nil }, nil) - return result, e + return result, fmt.Errorf("%w", e) } func checkOSSFuzz(c *checker.CheckRequest) (bool, error) { diff --git a/checks/permissions.go b/checks/permissions.go index 3a8d2a43..fb85a7a9 100644 --- a/checks/permissions.go +++ b/checks/permissions.go @@ -48,7 +48,7 @@ func TokenPermissions(c *checker.CheckRequest) checker.CheckResult { topLevelWritePermissions: make(map[string]bool), runLevelWritePermissions: make(map[string]bool), } - err := CheckFilesContent(".github/workflows/*", false, + err := fileparser.CheckFilesContent(".github/workflows/*", false, c, validateGitHubActionTokenPermissions, &data) return createResultForLeastPrivilegeTokens(data, err) } @@ -326,7 +326,7 @@ func testValidateGitHubActionTokenPermissions(pathfn string, // Check file content. func validateGitHubActionTokenPermissions(path string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { if !fileparser.IsWorkflowFile(path) { return true, nil } @@ -337,7 +337,7 @@ func validateGitHubActionTokenPermissions(path string, content []byte, panic("invalid type") } - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { return true, nil } diff --git a/checks/pinned_dependencies.go b/checks/pinned_dependencies.go index 95acd3f3..b0a8f124 100644 --- a/checks/pinned_dependencies.go +++ b/checks/pinned_dependencies.go @@ -131,7 +131,7 @@ func addPinnedResult(r *pinnedResult, to bool) { } } -func dataAsWorkflowResultPointer(data FileCbData) *worklowPinningResult { +func dataAsWorkflowResultPointer(data fileparser.FileCbData) *worklowPinningResult { pdata, ok := data.(*worklowPinningResult) if !ok { // panic if it is not correct type @@ -169,7 +169,7 @@ func createReturnValuesForGitHubActionsWorkflowPinned(r worklowPinningResult, in return score, nil } -func dataAsResultPointer(data FileCbData) *pinnedResult { +func dataAsResultPointer(data fileparser.FileCbData) *pinnedResult { pdata, ok := data.(*pinnedResult) if !ok { // This never happens. @@ -197,7 +197,8 @@ func createReturnValues(r pinnedResult, infoMsg string, dl checker.DetailLogger, func isShellScriptFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { var r pinnedResult - err := CheckFilesContent("*", false, c, validateShellScriptIsFreeOfInsecureDownloads, &r) + err := fileparser.CheckFilesContent("*", false, + c, validateShellScriptIsFreeOfInsecureDownloads, &r) return createReturnForIsShellScriptFreeOfInsecureDownloads(r, c.Dlogger, err) } @@ -216,7 +217,7 @@ func testValidateShellScriptIsFreeOfInsecureDownloads(pathfn string, } func validateShellScriptIsFreeOfInsecureDownloads(pathfn string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { pdata := dataAsResultPointer(data) // Validate the file type. @@ -236,7 +237,8 @@ func validateShellScriptIsFreeOfInsecureDownloads(pathfn string, content []byte, func isDockerfileFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { var r pinnedResult - err := CheckFilesContent("*Dockerfile*", false, c, validateDockerfileIsFreeOfInsecureDownloads, &r) + err := fileparser.CheckFilesContent("*Dockerfile*", + false, c, validateDockerfileIsFreeOfInsecureDownloads, &r) return createReturnForIsDockerfileFreeOfInsecureDownloads(r, c.Dlogger, err) } @@ -256,7 +258,7 @@ func testValidateDockerfileIsFreeOfInsecureDownloads(pathfn string, } func validateDockerfileIsFreeOfInsecureDownloads(pathfn string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { pdata := dataAsResultPointer(data) // Return early if this is a script, e.g. script_dockerfile_something.sh @@ -265,7 +267,7 @@ func validateDockerfileIsFreeOfInsecureDownloads(pathfn string, content []byte, return true, nil } - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { addPinnedResult(pdata, true) return true, nil } @@ -312,7 +314,8 @@ func validateDockerfileIsFreeOfInsecureDownloads(pathfn string, content []byte, func isDockerfilePinned(c *checker.CheckRequest) (int, error) { var r pinnedResult - err := CheckFilesContent("*Dockerfile*", false, c, validateDockerfileIsPinned, &r) + err := fileparser.CheckFilesContent("*Dockerfile*", false, + c, validateDockerfileIsPinned, &r) return createReturnForIsDockerfilePinned(r, c.Dlogger, err) } @@ -330,7 +333,7 @@ func testValidateDockerfileIsPinned(pathfn string, content []byte, dl checker.De } func validateDockerfileIsPinned(pathfn string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { // Users may use various names, e.g., // Dockerfile.aarch64, Dockerfile.template, Dockerfile_template, dockerfile, Dockerfile-name.template // Templates may trigger false positives, e.g. FROM { NAME }. @@ -342,7 +345,7 @@ func validateDockerfileIsPinned(pathfn string, content []byte, return true, nil } - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { addPinnedResult(pdata, true) return true, nil } @@ -429,7 +432,8 @@ func validateDockerfileIsPinned(pathfn string, content []byte, func isGitHubWorkflowScriptFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { var r pinnedResult - err := CheckFilesContent(".github/workflows/*", false, c, validateGitHubWorkflowIsFreeOfInsecureDownloads, &r) + err := fileparser.CheckFilesContent(".github/workflows/*", false, + c, validateGitHubWorkflowIsFreeOfInsecureDownloads, &r) return createReturnForIsGitHubWorkflowScriptFreeOfInsecureDownloads(r, c.Dlogger, err) } @@ -451,14 +455,14 @@ func testValidateGitHubWorkflowScriptFreeOfInsecureDownloads(pathfn string, // validateGitHubWorkflowIsFreeOfInsecureDownloads checks if the workflow file downloads dependencies that are unpinned. // Returns true if the check should continue executing after this file. func validateGitHubWorkflowIsFreeOfInsecureDownloads(pathfn string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { if !fileparser.IsWorkflowFile(pathfn) { return true, nil } pdata := dataAsResultPointer(data) - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { addPinnedResult(pdata, true) return true, nil } @@ -513,7 +517,8 @@ func validateGitHubWorkflowIsFreeOfInsecureDownloads(pathfn string, content []by // Check pinning of github actions in workflows. func isGitHubActionsWorkflowPinned(c *checker.CheckRequest) (int, error) { var r worklowPinningResult - err := CheckFilesContent(".github/workflows/*", true, c, validateGitHubActionWorkflow, &r) + err := fileparser.CheckFilesContent(".github/workflows/*", + true, c, validateGitHubActionWorkflow, &r) return createReturnForIsGitHubActionsWorkflowPinned(r, c.Dlogger, err) } @@ -534,14 +539,14 @@ func testIsGitHubActionsWorkflowPinned(pathfn string, content []byte, dl checker // validateGitHubActionWorkflow checks if the workflow file contains unpinned actions. Returns true if the check // should continue executing after this file. func validateGitHubActionWorkflow(pathfn string, content []byte, - dl checker.DetailLogger, data FileCbData) (bool, error) { + dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { if !fileparser.IsWorkflowFile(pathfn) { return true, nil } pdata := dataAsWorkflowResultPointer(data) - if !CheckFileContainsCommands(content, "#") { + if !fileparser.CheckFileContainsCommands(content, "#") { addWorkflowPinnedResult(pdata, true, true) addWorkflowPinnedResult(pdata, true, true) return true, nil @@ -598,9 +603,9 @@ func addWorkflowPinnedResult(w *worklowPinningResult, to, isGitHub bool) { // Check presence of lock files thru validatePackageManagerFile(). func isPackageManagerLockFilePresent(c *checker.CheckRequest) (int, error) { var r pinnedResult - err := CheckIfFileExists(CheckPinnedDependencies, c, validatePackageManagerFile, &r) + err := fileparser.CheckIfFileExists(CheckPinnedDependencies, c, validatePackageManagerFile, &r) if err != nil { - return checker.InconclusiveResultScore, err + return checker.InconclusiveResultScore, fmt.Errorf("%w", err) } if r != pinned { c.Dlogger.Warn("no lock files detected for a package manager") @@ -613,7 +618,7 @@ func isPackageManagerLockFilePresent(c *checker.CheckRequest) (int, error) { // validatePackageManagerFile will validate the if frozen dependecies file name exists. // TODO(laurent): need to differentiate between libraries and programs. // TODO(laurent): handle multi-language repos. -func validatePackageManagerFile(name string, dl checker.DetailLogger, data FileCbData) (bool, error) { +func validatePackageManagerFile(name string, dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { switch strings.ToLower(name) { // TODO(laurent): "go.mod" is for libraries default: diff --git a/checks/raw/binary_artifact.go b/checks/raw/binary_artifact.go new file mode 100644 index 00000000..a6b2090b --- /dev/null +++ b/checks/raw/binary_artifact.go @@ -0,0 +1,117 @@ +// Copyright 2021 Security Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package raw + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/h2non/filetype" + "github.com/h2non/filetype/types" + + "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/fileparser" + sce "github.com/ossf/scorecard/v3/errors" +) + +// File represents a file. +type File struct { + Path string + // TODO: add hash if needed. +} + +// BinaryArtifactData contains the raw results. +type BinaryArtifactData struct { + // Files contains a list of files. + Files []File +} + +// BinaryArtifacts retrieves the raw data for the Binary-Artifacts check. +func BinaryArtifacts(c *checker.CheckRequest) (BinaryArtifactData, error) { + var files []File + err := fileparser.CheckFilesContentV6("*", false, c.RepoClient, checkBinaryFileContent, &files) + if err != nil { + return BinaryArtifactData{}, err + } + + // No error, return the files. + return BinaryArtifactData{Files: files}, nil +} + +func checkBinaryFileContent(path string, content []byte, + data fileparser.FileCbData) (bool, error) { + pfiles, ok := data.(*[]File) + if !ok { + // This never happens. + panic("invalid type") + } + + binaryFileTypes := map[string]bool{ + "crx": true, + "deb": true, + "dex": true, + "dey": true, + "elf": true, + "bin": true, + "o": true, + "so": true, + "iso": true, + "class": true, + "jar": true, + "bundle": true, + "dylib": true, + "lib": true, + "msi": true, + "acm": true, + "ax": true, + "cpl": true, + "dll": true, + "drv": true, + "efi": true, + "exe": true, + "mui": true, + "ocx": true, + "scr": true, + "sys": true, + "tsp": true, + "pyc": true, + "pyo": true, + "par": true, + "rpm": true, + "swf": true, + "torrent": true, + "cab": true, + "whl": true, + } + var t types.Type + var err error + if len(content) == 0 { + return true, nil + } + if t, err = filetype.Get(content); err != nil { + return false, sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("filetype.Get:%v", err)) + } + + exists1 := binaryFileTypes[t.Extension] + exists2 := binaryFileTypes[strings.ReplaceAll(filepath.Ext(path), ".", "")] + if exists1 || exists2 { + *pfiles = append(*pfiles, File{ + Path: path, + }) + } + + return true, nil +} diff --git a/checks/security_policy.go b/checks/security_policy.go index a7e92f62..8ac829e1 100644 --- a/checks/security_policy.go +++ b/checks/security_policy.go @@ -21,6 +21,7 @@ import ( "go.uber.org/zap" "github.com/ossf/scorecard/v3/checker" + "github.com/ossf/scorecard/v3/checks/fileparser" "github.com/ossf/scorecard/v3/clients/githubrepo" sce "github.com/ossf/scorecard/v3/errors" ) @@ -39,8 +40,8 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult { var r bool // Check repository for repository-specific policy. // https://docs.github.com/en/github/building-a-strong-community/creating-a-default-community-health-file. - onFile := func(name string, dl checker.DetailLogger, data FileCbData) (bool, error) { - pdata := FileGetCbDataAsBoolPointer(data) + onFile := func(name string, dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { + pdata := fileparser.FileGetCbDataAsBoolPointer(data) if strings.EqualFold(name, "security.md") || strings.EqualFold(name, ".github/security.md") || strings.EqualFold(name, "docs/security.md") { @@ -66,7 +67,7 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult { } return true, nil } - err := CheckIfFileExists(CheckSecurityPolicy, c, onFile, &r) + err := fileparser.CheckIfFileExists(CheckSecurityPolicy, c, onFile, &r) if err != nil { return checker.CreateRuntimeErrorResult(CheckSecurityPolicy, err) } @@ -90,8 +91,8 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult { switch { case err == nil: defer dotGitHub.RepoClient.Close() - onFile = func(name string, dl checker.DetailLogger, data FileCbData) (bool, error) { - pdata := FileGetCbDataAsBoolPointer(data) + onFile = func(name string, dl checker.DetailLogger, data fileparser.FileCbData) (bool, error) { + pdata := fileparser.FileGetCbDataAsBoolPointer(data) if strings.EqualFold(name, "security.md") || strings.EqualFold(name, ".github/security.md") || strings.EqualFold(name, "docs/security.md") { @@ -107,7 +108,7 @@ func SecurityPolicy(c *checker.CheckRequest) checker.CheckResult { } return true, nil } - err = CheckIfFileExists(CheckSecurityPolicy, dotGitHub, onFile, &r) + err = fileparser.CheckIfFileExists(CheckSecurityPolicy, dotGitHub, onFile, &r) if err != nil { return checker.CreateRuntimeErrorResult(CheckSecurityPolicy, err) }