From 719e52baf55a474e470037d7c613022b8ac832fd Mon Sep 17 00:00:00 2001 From: laurentsimon Date: Wed, 29 Jun 2022 00:05:11 +0000 Subject: [PATCH] update --- checker/raw_result.go | 1 - checks/evaluation/permissions.go | 9 +- checks/permissions.go | 5 + checks/pinned_dependencies.go | 561 +----------------------------- checks/raw/permissions.go | 8 - checks/raw/pinned_dependencies.go | 1 + checks/raw/remediations.go | 89 ----- checks/remediations.go | 88 ----- pkg/json_raw_results.go | 7 - 9 files changed, 15 insertions(+), 754 deletions(-) delete mode 100644 checks/raw/remediations.go delete mode 100644 checks/remediations.go diff --git a/checker/raw_result.go b/checker/raw_result.go index ee5ae4013be9..b36cb5fa7fec 100644 --- a/checker/raw_result.go +++ b/checker/raw_result.go @@ -280,7 +280,6 @@ const ( // TokenPermission defines a token permission result. type TokenPermission struct { Job *WorkflowJob - Remediation *Remediation LocationType *PermissionLocation Name *string Value *string diff --git a/checks/evaluation/permissions.go b/checks/evaluation/permissions.go index 5db146a6e322..27bc94182443 100644 --- a/checks/evaluation/permissions.go +++ b/checks/evaluation/permissions.go @@ -19,6 +19,7 @@ import ( "github.com/ossf/scorecard/v4/checker" sce "github.com/ossf/scorecard/v4/errors" + "github.com/ossf/scorecard/v4/remediation" ) type permissions struct { @@ -55,13 +56,19 @@ func applyScorePolicy(results *checker.TokenPermissionsData, dl checker.DetailLo hm := make(map[string]permissions) for _, r := range results.TokenPermissions { - msg := checker.LogMessage{Remediation: r.Remediation} + var msg checker.LogMessage + if r.File != nil { msg.Path = r.File.Path msg.Offset = r.File.Offset msg.Type = r.File.Type msg.Snippet = r.File.Snippet + + if msg.Path != "" { + msg.Remediation = remediation.CreateWorkflowPermissionRemediation(r.File.Path) + } } + text, err := createMessage(r) if err != nil { return checker.MinResultScore, err diff --git a/checks/permissions.go b/checks/permissions.go index da2536f3a643..1ad82d5930be 100644 --- a/checks/permissions.go +++ b/checks/permissions.go @@ -19,6 +19,7 @@ import ( "github.com/ossf/scorecard/v4/checks/evaluation" "github.com/ossf/scorecard/v4/checks/raw" sce "github.com/ossf/scorecard/v4/errors" + "github.com/ossf/scorecard/v4/remediation" ) // CheckTokenPermissions is the exported name for Token-Permissions check. @@ -38,6 +39,10 @@ func init() { // TokenPermissions will run the Token-Permissions check. func TokenPermissions(c *checker.CheckRequest) checker.CheckResult { + if err := remediation.Setup(c); err != nil { + return checker.CreateRuntimeErrorResult(CheckTokenPermissions, err) + } + rawData, err := raw.TokenPermissions(c) if err != nil { e := sce.WithMessage(sce.ErrScorecardInternal, err.Error()) diff --git a/checks/pinned_dependencies.go b/checks/pinned_dependencies.go index e36e682ee58e..0374518474de 100644 --- a/checks/pinned_dependencies.go +++ b/checks/pinned_dependencies.go @@ -15,8 +15,6 @@ package checks import ( - "fmt" - "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/checks/evaluation" "github.com/ossf/scorecard/v4/checks/raw" @@ -39,29 +37,10 @@ func init() { } } -<<<<<<< HEAD // PinningDependencies will check the repository for its use of dependencies. func PinningDependencies(c *checker.CheckRequest) checker.CheckResult { if err := remediation.Setup(c); err != nil { - e := sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("remdiationSetup: %v", err)) - return checker.CreateRuntimeErrorResult(CheckPinnedDependencies, e) -======= -// PinnedDependencies will check the repository if it contains frozen dependecies. -func PinnedDependencies(c *checker.CheckRequest) checker.CheckResult { - // Lock file. - /* WARNING: this code is inherently incorrect: - - does not differentiate between libs and main - - only looks at root folder. - => disabling to avoid false positives. - lockScore, lockErr := isPackageManagerLockFilePresent(c) - if lockErr != nil { - return checker.CreateRuntimeErrorResult(CheckPinnedDependencies, lockErr) - } - */ - - if remErr := remediation.Setup(c); remErr != nil { - return checker.CreateRuntimeErrorResult(CheckPinnedDependencies, remErr) ->>>>>>> 465fc76a (updates) + return checker.CreateRuntimeErrorResult(CheckPinnedDependencies, err) } rawData, err := raw.PinningDependencies(c) @@ -75,543 +54,5 @@ func PinnedDependencies(c *checker.CheckRequest) checker.CheckResult { c.RawResults.PinningDependenciesResults = rawData } -<<<<<<< HEAD return evaluation.PinningDependencies(CheckPinnedDependencies, c.Dlogger, &rawData) -======= - if r.thirdParties != notPinned { - score += 8 - dl.Info(&checker.LogMessage{ - Type: checker.FileTypeSource, - Offset: checker.OffsetDefault, - Text: fmt.Sprintf("%s %s", "Third-party", infoMsg), - }) - } - - return score, nil -} - -func createReturnValues(r pinnedResult, infoMsg string, dl checker.DetailLogger, err error) (int, error) { - if err != nil { - return checker.InconclusiveResultScore, err - } - - switch r { - default: - panic("invalid value") - case pinned, pinnedUndefined: - dl.Info(&checker.LogMessage{ - Text: infoMsg, - }) - return checker.MaxResultScore, nil - case notPinned: - // No logging needed as it's done by the checks. - return checker.MinResultScore, nil - } -} - -func isShellScriptFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { - var r pinnedResult - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ - Pattern: "*", - CaseSensitive: false, - }, validateShellScriptIsFreeOfInsecureDownloads, c.Dlogger, &r) - return createReturnForIsShellScriptFreeOfInsecureDownloads(r, c.Dlogger, err) -} - -func createReturnForIsShellScriptFreeOfInsecureDownloads(r pinnedResult, - dl checker.DetailLogger, err error, -) (int, error) { - return createReturnValues(r, - "no insecure (not pinned by hash) dependency downloads found in shell scripts", - dl, err) -} - -var validateShellScriptIsFreeOfInsecureDownloads fileparser.DoWhileTrueOnFileContent = func( - pathfn string, - content []byte, - args ...interface{}, -) (bool, error) { - if len(args) != 2 { - return false, fmt.Errorf( - "validateShellScriptIsFreeOfInsecureDownloads requires exactly 2 arguments: %w", errInvalidArgLength) - } - - pdata := dataAsResultPointer(args[1]) - dl := dataAsDetailLogger(args[0]) - - // Validate the file type. - if !isSupportedShellScriptFile(pathfn, content) { - addPinnedResult(pdata, true) - return true, nil - } - r, err := validateShellFile(pathfn, 0, 0 /*unknown*/, content, map[string]bool{}, dl) - if err != nil { - // Ignore parsing errors. - if errors.Is(err, sce.ErrorShellParsing) { - addPinnedResult(pdata, true) - } - - return false, nil - } - - addPinnedResult(pdata, r) - return true, nil -} - -func isDockerfileFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { - var r pinnedResult - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ - Pattern: "*Dockerfile*", - CaseSensitive: false, - }, validateDockerfileIsFreeOfInsecureDownloads, c.Dlogger, &r) - return createReturnForIsDockerfileFreeOfInsecureDownloads(r, c.Dlogger, err) -} - -// Create the result. -func createReturnForIsDockerfileFreeOfInsecureDownloads(r pinnedResult, - dl checker.DetailLogger, err error, -) (int, error) { - return createReturnValues(r, - "no insecure (not pinned by hash) dependency downloads found in Dockerfiles", - dl, err) -} - -func isDockerfile(pathfn string, content []byte) bool { - if strings.HasSuffix(pathfn, ".go") || - strings.HasSuffix(pathfn, ".c") || - strings.HasSuffix(pathfn, ".cpp") || - strings.HasSuffix(pathfn, ".rs") || - strings.HasSuffix(pathfn, ".js") || - strings.HasSuffix(pathfn, ".py") || - strings.HasSuffix(pathfn, ".pyc") || - strings.HasSuffix(pathfn, ".java") || - isShellScriptFile(pathfn, content) { - return false - } - return true -} - -var validateDockerfileIsFreeOfInsecureDownloads fileparser.DoWhileTrueOnFileContent = func( - pathfn string, - content []byte, - args ...interface{}, -) (bool, error) { - if len(args) != 2 { - return false, fmt.Errorf( - "validateDockerfileIsFreeOfInsecureDownloads requires exactly 2 arguments: %w", errInvalidArgLength) - } - pdata := dataAsResultPointer(args[1]) - dl := dataAsDetailLogger(args[0]) - - // Return early if this is not a docker file. - if !isDockerfile(pathfn, content) { - addPinnedResult(pdata, true) - return true, nil - } - - if !fileparser.CheckFileContainsCommands(content, "#") { - addPinnedResult(pdata, true) - return true, nil - } - - contentReader := strings.NewReader(string(content)) - res, err := parser.Parse(contentReader) - if err != nil { - return false, sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("%v: %v", errInternalInvalidDockerFile, err)) - } - - // Walk the Dockerfile's AST. - taintedFiles := make(map[string]bool) - for i := range res.AST.Children { - var bytes []byte - - child := res.AST.Children[i] - cmdType := child.Value - - // Only look for the 'RUN' command. - if cmdType != "RUN" { - continue - } - - var valueList []string - for n := child.Next; n != nil; n = n.Next { - valueList = append(valueList, n.Value) - } - - if len(valueList) == 0 { - return false, sce.WithMessage(sce.ErrScorecardInternal, errInternalInvalidDockerFile.Error()) - } - - // Build a file content. - cmd := strings.Join(valueList, " ") - bytes = append(bytes, cmd...) - r, err := validateShellFile(pathfn, uint(child.StartLine)-1, uint(child.EndLine)-1, - bytes, taintedFiles, dl) - if err != nil { - // Ignore parsing errors. - if errors.Is(err, sce.ErrorShellParsing) { - addPinnedResult(pdata, true) - } - return false, err - } - addPinnedResult(pdata, r) - } - - return true, nil -} - -func isDockerfilePinned(c *checker.CheckRequest) (int, error) { - var r pinnedResult - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ - Pattern: "*Dockerfile*", - CaseSensitive: false, - }, validateDockerfileIsPinned, c.Dlogger, &r) - return createReturnForIsDockerfilePinned(r, c.Dlogger, err) -} - -// Create the result. -func createReturnForIsDockerfilePinned(r pinnedResult, dl checker.DetailLogger, err error) (int, error) { - return createReturnValues(r, - "Dockerfile dependencies are pinned", - dl, err) -} - -var validateDockerfileIsPinned fileparser.DoWhileTrueOnFileContent = func( - pathfn string, - content []byte, - args ...interface{}, -) (bool, error) { - // Users may use various names, e.g., - // Dockerfile.aarch64, Dockerfile.template, Dockerfile_template, dockerfile, Dockerfile-name.template - - if len(args) != 2 { - return false, fmt.Errorf( - "validateDockerfileIsPinned requires exactly 2 arguments: %w", errInvalidArgLength) - } - pdata := dataAsResultPointer(args[1]) - dl := dataAsDetailLogger(args[0]) - // Return early if this is not a dockerfile. - if !isDockerfile(pathfn, content) { - addPinnedResult(pdata, true) - return true, nil - } - - if !fileparser.CheckFileContainsCommands(content, "#") { - addPinnedResult(pdata, true) - return true, nil - } - - if fileparser.IsTemplateFile(pathfn) { - addPinnedResult(pdata, true) - return true, nil - } - - // We have what looks like a docker file. - // Let's interpret the content as utf8-encoded strings. - contentReader := strings.NewReader(string(content)) - // The dependency must be pinned by sha256 hash, e.g., - // FROM something@sha256:${ARG}, - // FROM something:@sha256:45b23dee08af5e43a7fea6c4cf9c25ccf269ee113168c19722f87876677c5cb2 - regex := regexp.MustCompile(`.*@sha256:([a-f\d]{64}|\${.*})`) - - ret := true - pinnedAsNames := make(map[string]bool) - res, err := parser.Parse(contentReader) - if err != nil { - return false, sce.WithMessage(sce.ErrScorecardInternal, fmt.Sprintf("%v: %v", errInternalInvalidDockerFile, err)) - } - - for _, child := range res.AST.Children { - cmdType := child.Value - if cmdType != "FROM" { - continue - } - - var valueList []string - for n := child.Next; n != nil; n = n.Next { - valueList = append(valueList, n.Value) - } - - switch { - // scratch is no-op. - case len(valueList) > 0 && strings.EqualFold(valueList[0], "scratch"): - continue - - // FROM name AS newname. - case len(valueList) == 3 && strings.EqualFold(valueList[1], "as"): - name := valueList[0] - asName := valueList[2] - // Check if the name is pinned. - // (1): name = <>@sha245:hash - // (2): name = XXX where XXX was pinned - pinned := pinnedAsNames[name] - if pinned || regex.MatchString(name) { - // Record the asName. - pinnedAsNames[asName] = true - continue - } - - // Not pinned. - ret = false - dl.Warn(&checker.LogMessage{ - Path: pathfn, - Type: checker.FileTypeSource, - Offset: uint(child.StartLine), - EndOffset: uint(child.EndLine), - Text: "docker image not pinned by hash", - Snippet: child.Original, - }) - - // FROM name. - case len(valueList) == 1: - name := valueList[0] - pinned := pinnedAsNames[name] - if !pinned && !regex.MatchString(name) { - ret = false - dl.Warn(&checker.LogMessage{ - Path: pathfn, - Type: checker.FileTypeSource, - Offset: uint(child.StartLine), - EndOffset: uint(child.EndLine), - Text: "docker image not pinned by hash", - Snippet: child.Original, - }) - } - - default: - // That should not happen. - return false, sce.WithMessage(sce.ErrScorecardInternal, errInternalInvalidDockerFile.Error()) - } - } - - //nolint - // The file need not have a FROM statement, - // https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/dockerfiles/partials/jupyter.partial.Dockerfile. - - addPinnedResult(pdata, ret) - return true, nil -} - -func isGitHubWorkflowScriptFreeOfInsecureDownloads(c *checker.CheckRequest) (int, error) { - var r pinnedResult - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ - Pattern: ".github/workflows/*", - CaseSensitive: false, - }, validateGitHubWorkflowIsFreeOfInsecureDownloads, c.Dlogger, &r) - return createReturnForIsGitHubWorkflowScriptFreeOfInsecureDownloads(r, c.Dlogger, err) -} - -// Create the result. -func createReturnForIsGitHubWorkflowScriptFreeOfInsecureDownloads(r pinnedResult, - dl checker.DetailLogger, err error, -) (int, error) { - return createReturnValues(r, - "no insecure (not pinned by hash) dependency downloads found in GitHub workflows", - dl, err) -} - -// validateGitHubWorkflowIsFreeOfInsecureDownloads checks if the workflow file downloads dependencies that are unpinned. -// Returns true if the check should continue executing after this file. -var validateGitHubWorkflowIsFreeOfInsecureDownloads fileparser.DoWhileTrueOnFileContent = func( - pathfn string, - content []byte, - args ...interface{}, -) (bool, error) { - if !fileparser.IsWorkflowFile(pathfn) { - return true, nil - } - - if len(args) != 2 { - return false, fmt.Errorf( - "validateGitHubWorkflowIsFreeOfInsecureDownloads requires exactly 2 arguments: %w", errInvalidArgLength) - } - pdata := dataAsResultPointer(args[1]) - dl := dataAsDetailLogger(args[0]) - - if !fileparser.CheckFileContainsCommands(content, "#") { - addPinnedResult(pdata, true) - return true, nil - } - - workflow, errs := actionlint.Parse(content) - if len(errs) > 0 && workflow == nil { - // actionlint is a linter, so it will return errors when the yaml file does not meet its linting standards. - // Often we don't care about these errors. - return false, fileparser.FormatActionlintError(errs) - } - - githubVarRegex := regexp.MustCompile(`{{[^{}]*}}`) - for jobName, job := range workflow.Jobs { - jobName := jobName - job := job - if len(fileparser.GetJobName(job)) > 0 { - jobName = fileparser.GetJobName(job) - } - taintedFiles := make(map[string]bool) - for _, step := range job.Steps { - step := step - if !fileparser.IsStepExecKind(step, actionlint.ExecKindRun) { - continue - } - - execRun, ok := step.Exec.(*actionlint.ExecRun) - if !ok { - stepName := fileparser.GetStepName(step) - return false, sce.WithMessage(sce.ErrScorecardInternal, - fmt.Sprintf("unable to parse step '%v' for job '%v'", jobName, stepName)) - } - - if execRun == nil || execRun.Run == nil { - // Cannot check further, continue. - continue - } - - run := execRun.Run.Value - // https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsrun. - shell, err := fileparser.GetShellForStep(step, job) - if err != nil { - return false, err - } - // Skip unsupported shells. We don't support Windows shells or some Unix shells. - if !isSupportedShell(shell) { - continue - } - - // We replace the `${{ github.variable }}` to avoid shell parsing failures. - script := githubVarRegex.ReplaceAll([]byte(run), []byte("GITHUB_REDACTED_VAR")) - validated, err := validateShellFile(pathfn, uint(execRun.Run.Pos.Line), uint(execRun.Run.Pos.Line), - script, taintedFiles, dl) - if err != nil { - // Ignore parsing errors. - if errors.Is(err, sce.ErrorShellParsing) { - addPinnedResult(pdata, true) - } - return false, err - } - addPinnedResult(pdata, validated) - } - } - - return true, nil -} - -// Check pinning of github actions in workflows. -func isGitHubActionsWorkflowPinned(c *checker.CheckRequest) (int, error) { - var r worklowPinningResult - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ - Pattern: ".github/workflows/*", - CaseSensitive: true, - }, validateGitHubActionWorkflow, c.Dlogger, &r) - return createReturnForIsGitHubActionsWorkflowPinned(r, c.Dlogger, err) -} - -// Create the result. -func createReturnForIsGitHubActionsWorkflowPinned(r worklowPinningResult, dl checker.DetailLogger, - err error, -) (int, error) { - return createReturnValuesForGitHubActionsWorkflowPinned(r, - "actions are pinned", - dl, err) -} - -func generateOwnerToDisplay(gitHubOwned bool) string { - if gitHubOwned { - return "GitHub-owned" - } - return "third-party" -} - -// validateGitHubActionWorkflow checks if the workflow file contains unpinned actions. Returns true if the check -// should continue executing after this file. -var validateGitHubActionWorkflow fileparser.DoWhileTrueOnFileContent = func( - pathfn string, - content []byte, - args ...interface{}, -) (bool, error) { - if !fileparser.IsWorkflowFile(pathfn) { - return true, nil - } - - if len(args) != 2 { - return false, fmt.Errorf( - "validateGitHubActionWorkflow requires exactly 2 arguments: %w", errInvalidArgLength) - } - pdata := dataAsWorkflowResultPointer(args[1]) - dl := dataAsDetailLogger(args[0]) - - if !fileparser.CheckFileContainsCommands(content, "#") { - addWorkflowPinnedResult(pdata, true, true) - addWorkflowPinnedResult(pdata, true, true) - return true, nil - } - - workflow, errs := actionlint.Parse(content) - if len(errs) > 0 && workflow == nil { - // actionlint is a linter, so it will return errors when the yaml file does not meet its linting standards. - // Often we don't care about these errors. - return false, fileparser.FormatActionlintError(errs) - } - - hashRegex := regexp.MustCompile(`^.*@[a-f\d]{40,}`) - for jobName, job := range workflow.Jobs { - jobName := jobName - job := job - if len(fileparser.GetJobName(job)) > 0 { - jobName = fileparser.GetJobName(job) - } - for _, step := range job.Steps { - if !fileparser.IsStepExecKind(step, actionlint.ExecKindAction) { - continue - } - execAction, ok := step.Exec.(*actionlint.ExecAction) - if !ok { - stepName := fileparser.GetStepName(step) - return false, sce.WithMessage(sce.ErrScorecardInternal, - fmt.Sprintf("unable to parse step '%v' for job '%v'", jobName, stepName)) - } - - if execAction == nil || execAction.Uses == nil { - // Cannot check further, continue. - continue - } - - // nolint:lll - // Check whether this is an action defined in the same repo, - // https://docs.github.com/en/actions/learn-github-actions/finding-and-customizing-actions#referencing-an-action-in-the-same-repository-where-a-workflow-file-uses-the-action. - if strings.HasPrefix(execAction.Uses.Value, "./") { - continue - } - - // Check if we are dealing with a GitHub action or a third-party one. - gitHubOwned := fileparser.IsGitHubOwnedAction(execAction.Uses.Value) - owner := generateOwnerToDisplay(gitHubOwned) - - // Ensure a hash at least as large as SHA1 is used (40 hex characters). - // Example: action-name@hash - match := hashRegex.MatchString(execAction.Uses.Value) - if !match { - dl.Warn(&checker.LogMessage{ - Path: pathfn, Type: checker.FileTypeSource, - Offset: uint(execAction.Uses.Pos.Line), - EndOffset: uint(execAction.Uses.Pos.Line), // `Uses` always span a single line. - Snippet: execAction.Uses.Value, - Text: fmt.Sprintf("%s action not pinned by hash", owner), - Remediation: remediation.CreateWorkflowPinningRemediation(pathfn), - }) - } - - addWorkflowPinnedResult(pdata, match, gitHubOwned) - } - } - - return true, nil -} - -func addWorkflowPinnedResult(w *worklowPinningResult, to, isGitHub bool) { - if isGitHub { - addPinnedResult(&w.gitHubOwned, to) - } else { - addPinnedResult(&w.thirdParties, to) - } ->>>>>>> 465fc76a (updates) } diff --git a/checks/raw/permissions.go b/checks/raw/permissions.go index 552eedb7d966..5efcb9e2f3ea 100644 --- a/checks/raw/permissions.go +++ b/checks/raw/permissions.go @@ -23,7 +23,6 @@ import ( "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/checks/fileparser" sce "github.com/ossf/scorecard/v4/errors" - "github.com/ossf/scorecard/v4/remediation" ) type permission string @@ -54,10 +53,6 @@ func TokenPermissions(c *checker.CheckRequest) (checker.TokenPermissionsData, er // data is shared across all GitHub workflows. var data permissionCbData - if err := remediation.Setup(c); err != nil { - return data.results, err - } - err := fileparser.OnMatchingFileContentDo(c.RepoClient, fileparser.PathMatcher{ Pattern: ".github/workflows/*", CaseSensitive: false, @@ -140,7 +135,6 @@ func validatePermission(permissionKey permission, permissionValue *actionlint.Pe LocationType: &permLoc, Name: &key, Value: &val, - Remediation: remediation.CreateWorkflowPermissionRemediation(path), Type: checker.PermissionTypeWrite, // TODO: Job }) @@ -241,7 +235,6 @@ func validatePermissions(permissions *actionlint.Permissions, permLoc checker.Pe }, LocationType: &permLoc, Value: &val, - Remediation: remediation.CreateWorkflowPermissionRemediation(path), Type: checker.PermissionTypeWrite, // TODO: Job }) @@ -284,7 +277,6 @@ func validateTopLevelPermissions(workflow *actionlint.Workflow, path string, }, LocationType: &permLoc, Type: checker.PermissionTypeUndeclared, - Remediation: remediation.CreateWorkflowPermissionRemediation(path), // TODO: Job }) diff --git a/checks/raw/pinned_dependencies.go b/checks/raw/pinned_dependencies.go index 3465b1940a78..7cccc9e658f7 100644 --- a/checks/raw/pinned_dependencies.go +++ b/checks/raw/pinned_dependencies.go @@ -31,6 +31,7 @@ import ( // PinningDependencies checks for (un)pinned dependencies. func PinningDependencies(c *checker.CheckRequest) (checker.PinningDependenciesData, error) { var results checker.PinningDependenciesData + // GitHub actions. if err := collectGitHubActionsWorkflowPinning(c, &results); err != nil { return checker.PinningDependenciesData{}, err diff --git a/checks/raw/remediations.go b/checks/raw/remediations.go deleted file mode 100644 index 9ac12c62cddf..000000000000 --- a/checks/raw/remediations.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2022 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 ( - "errors" - "fmt" - "strings" - "sync" - - "github.com/ossf/scorecard/v4/checker" - "github.com/ossf/scorecard/v4/clients" -) - -var ( - remediationBranch string - remediationRepo string - remediationOnce *sync.Once - remediationSetupErr error -) - -var ( - workflowText = "update your workflow using https://app.stepsecurity.io/secureworkflow/%s/%s/%s?enable=%s" - //nolint - workflowMarkdown = "update your workflow using [https://app.stepsecurity.io](https://app.stepsecurity.io/secureworkflow/%s/%s/%s?enable=%s)" -) - -//nolint:gochecknoinits -func init() { - remediationOnce = new(sync.Once) -} - -func remdiationSetup(c *checker.CheckRequest) error { - remediationOnce.Do(func() { - // Get the branch for remediation. - b, err := c.RepoClient.GetDefaultBranch() - if err != nil && !errors.Is(err, clients.ErrUnsupportedFeature) { - remediationSetupErr = err - return - } - if b.Name != nil { - remediationBranch = *b.Name - uri := c.Repo.URI() - parts := strings.Split(uri, "/") - if len(parts) != 3 { - remediationSetupErr = fmt.Errorf("%w: %s", errInvalidArgLength, uri) - return - } - remediationRepo = fmt.Sprintf("%s/%s", parts[1], parts[2]) - } - }) - - return remediationSetupErr -} - -func createWorkflowPermissionRemediation(filepath string) *checker.Remediation { - return createWorkflowRemediation(filepath, "permissions") -} - -func createWorkflowPinningRemediation(filepath string) *checker.Remediation { - return createWorkflowRemediation(filepath, "pin") -} - -func createWorkflowRemediation(path, t string) *checker.Remediation { - p := strings.TrimPrefix(path, ".github/workflows/") - if remediationBranch == "" || remediationRepo == "" { - return nil - } - - text := fmt.Sprintf(workflowText, remediationRepo, p, remediationBranch, t) - markdown := fmt.Sprintf(workflowMarkdown, remediationRepo, p, remediationBranch, t) - - return &checker.Remediation{ - HelpText: text, - HelpMarkdown: markdown, - } -} diff --git a/checks/remediations.go b/checks/remediations.go deleted file mode 100644 index 5723a9e8b4af..000000000000 --- a/checks/remediations.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2022 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 checks - -import ( - "errors" - "fmt" - "strings" - "sync" - - "github.com/ossf/scorecard/v4/checker" - "github.com/ossf/scorecard/v4/clients" -) - -var ( - remediationBranch string - remediationRepo string - remediationOnce *sync.Once - remediationSetupErr error -) - -var ( - workflowText = "update your workflow using https://app.stepsecurity.io/secureworkflow/%s/%s/%s?enable=%s" - //nolint - workflowMarkdown = "update your workflow using [https://app.stepsecurity.io](https://app.stepsecurity.io/secureworkflow/%s/%s/%s?enable=%s)" -) - -//nolint:gochecknoinits -func init() { - remediationOnce = new(sync.Once) -} - -func remdiationSetup(c *checker.CheckRequest) error { - remediationOnce.Do(func() { - // Get the branch for remediation. - b, err := c.RepoClient.GetDefaultBranch() - if err != nil { - if !errors.Is(err, clients.ErrUnsupportedFeature) { - remediationSetupErr = err - } - return - } - - if b.Name != nil { - remediationBranch = *b.Name - uri := c.Repo.URI() - parts := strings.Split(uri, "/") - if len(parts) != 3 { - remediationSetupErr = fmt.Errorf("%w: %s", errInvalidArgLength, uri) - return - } - remediationRepo = fmt.Sprintf("%s/%s", parts[1], parts[2]) - } - }) - - return remediationSetupErr -} - -func createWorkflowPermissionRemediation(filepath string) *checker.Remediation { - return createWorkflowRemediation(filepath, "permissions") -} - -func createWorkflowRemediation(path, t string) *checker.Remediation { - p := strings.TrimPrefix(path, ".github/workflows/") - if remediationBranch == "" || remediationRepo == "" { - return nil - } - - text := fmt.Sprintf(workflowText, remediationRepo, p, remediationBranch, t) - markdown := fmt.Sprintf(workflowMarkdown, remediationRepo, p, remediationBranch, t) - - return &checker.Remediation{ - HelpText: text, - HelpMarkdown: markdown, - } -} diff --git a/pkg/json_raw_results.go b/pkg/json_raw_results.go index 33457444830e..fe211f5f5b7f 100644 --- a/pkg/json_raw_results.go +++ b/pkg/json_raw_results.go @@ -40,17 +40,10 @@ type jsonScorecardRawResult struct { // TODO: separate each check extraction into its own file. type jsonFile struct { -<<<<<<< HEAD Snippet *string `json:"snippet,omitempty"` Path string `json:"path"` Offset uint `json:"offset,omitempty"` EndOffset uint `json:"endOffset,omitempty"` -======= - Snippet *string `json:"snippet,omitempty"` - Path string `json:"path"` - // TODO: change to an uint. - Offset uint `json:"offset,omitempty"` ->>>>>>> 465fc76a (updates) } type jsonTool struct {