diff --git a/cmd/root.go b/cmd/root.go index 506cdb819ed..b66272c0bca 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -73,6 +73,9 @@ func New(o *options.Options) *cobra.Command { // rootCmd runs scorecard checks given a set of arguments. func rootCmd(o *options.Options) error { + var err error + var repoResult pkg.ScorecardResult + p := &pmc.PackageManagerClient{} // Set `repo` from package managers. pkgResp, err := fetchGitRepositoryFromPackageManagers(o.NPM, o.PyPI, o.RubyGems, o.Nuget, p) @@ -119,18 +122,22 @@ func rootCmd(o *options.Options) error { return fmt.Errorf("GetEnabled: %w", err) } + enabledProbes := o.Probes() if o.Format == options.FormatDefault { - for checkName := range enabledChecks { - fmt.Fprintf(os.Stderr, "Starting [%s]\n", checkName) + if len(enabledProbes) > 0 { + printProbeStart(enabledProbes) + } else { + printCheckStart(enabledChecks) } } - repoResult, err := pkg.RunScorecard( + repoResult, err = pkg.ExperimentalRunProbes( ctx, repoURI, o.Commit, o.CommitDepth, enabledChecks, + enabledProbes, repoClient, ossFuzzRepoClient, ciiClient, @@ -148,10 +155,11 @@ func rootCmd(o *options.Options) error { }) if o.Format == options.FormatDefault { - for checkName := range enabledChecks { - fmt.Fprintf(os.Stderr, "Finished [%s]\n", checkName) + if len(enabledProbes) > 0 { + printProbeResults(enabledProbes) + } else { + printCheckResults(enabledChecks) } - fmt.Fprintln(os.Stderr, "\nRESULTS\n-------") } resultsErr := pkg.FormatResults( @@ -172,3 +180,28 @@ func rootCmd(o *options.Options) error { } return nil } + +func printProbeStart(enabledProbes []string) { + for _, probeName := range enabledProbes { + fmt.Fprintf(os.Stderr, "Starting probe [%s]\n", probeName) + } +} + +func printCheckStart(enabledChecks checker.CheckNameToFnMap) { + for checkName := range enabledChecks { + fmt.Fprintf(os.Stderr, "Starting [%s]\n", checkName) + } +} + +func printProbeResults(enabledProbes []string) { + for _, probeName := range enabledProbes { + fmt.Fprintf(os.Stderr, "Finished probe %s\n", probeName) + } +} + +func printCheckResults(enabledChecks checker.CheckNameToFnMap) { + for checkName := range enabledChecks { + fmt.Fprintf(os.Stderr, "Finished [%s]\n", checkName) + } + fmt.Fprintln(os.Stderr, "\nRESULTS\n-------") +} diff --git a/options/flags.go b/options/flags.go index 2691c4a1978..cf512c033b6 100644 --- a/options/flags.go +++ b/options/flags.go @@ -70,6 +70,8 @@ const ( ShorthandFlagResultsFile = "o" FlagCommitDepth = "commit-depth" + + FlagProbes = "probes" ) // Command is an interface for handling options for command-line utilities. @@ -168,6 +170,13 @@ func (o *Options) AddFlags(cmd *cobra.Command) { fmt.Sprintf("Checks to run. Possible values are: %s", strings.Join(checkNames, ",")), ) + cmd.Flags().StringSliceVar( + &o.ProbesToRun, + FlagProbes, + o.ProbesToRun, + "Probes to run.", + ) + // TODO(options): Extract logic allowedFormats := []string{ FormatDefault, diff --git a/options/options.go b/options/options.go index 30acfe0efe3..2d328735051 100644 --- a/options/options.go +++ b/options/options.go @@ -42,6 +42,7 @@ type Options struct { PolicyFile string ResultsFile string ChecksToRun []string + ProbesToRun []string Metadata []string CommitDepth int ShowDetails bool @@ -240,6 +241,10 @@ func (o *Options) Checks() []string { return o.ChecksToRun } +func (o *Options) Probes() []string { + return o.ProbesToRun +} + // isExperimentalEnabled returns true if experimental features were enabled via // environment variable. func (o *Options) isExperimentalEnabled() bool { diff --git a/pkg/scorecard.go b/pkg/scorecard.go index b8c1a4e1691..321806c3ada 100644 --- a/pkg/scorecard.go +++ b/pkg/scorecard.go @@ -39,20 +39,11 @@ import ( var errEmptyRepository = errors.New("repository empty") func runEnabledChecks(ctx context.Context, - repo clients.Repo, raw *checker.RawResults, checksToRun checker.CheckNameToFnMap, - repoClient clients.RepoClient, ossFuzzRepoClient clients.RepoClient, ciiClient clients.CIIBestPracticesClient, - vulnsClient clients.VulnerabilitiesClient, + repo clients.Repo, + request *checker.CheckRequest, + checksToRun checker.CheckNameToFnMap, resultsCh chan checker.CheckResult, ) { - request := checker.CheckRequest{ - Ctx: ctx, - RepoClient: repoClient, - OssFuzzRepo: ossFuzzRepoClient, - CIIClient: ciiClient, - VulnerabilitiesClient: vulnsClient, - Repo: repo, - RawResults: raw, - } wg := sync.WaitGroup{} for checkName, checkFn := range checksToRun { checkName := checkName @@ -63,7 +54,7 @@ func runEnabledChecks(ctx context.Context, runner := checker.NewRunner( checkName, repo.URI(), - &request, + request, ) resultsCh <- runner.Run(ctx, checkFn) @@ -89,12 +80,12 @@ func getRepoCommitHash(r clients.RepoClient) (string, error) { return commits[0].SHA, nil } -// RunScorecard runs enabled Scorecard checks on a Repo. -func RunScorecard(ctx context.Context, +func runScorecard(ctx context.Context, repo clients.Repo, commitSHA string, commitDepth int, checksToRun checker.CheckNameToFnMap, + probesToRun []string, repoClient clients.RepoClient, ossFuzzRepoClient clients.RepoClient, ciiClient clients.CIIBestPracticesClient, @@ -150,9 +141,27 @@ func RunScorecard(ctx context.Context, "repository.defaultBranch": defaultBranch, } - go runEnabledChecks(ctx, repo, &ret.RawResults, checksToRun, - repoClient, ossFuzzRepoClient, - ciiClient, vulnsClient, resultsCh) + request := &checker.CheckRequest{ + Ctx: ctx, + RepoClient: repoClient, + OssFuzzRepo: ossFuzzRepoClient, + CIIClient: ciiClient, + VulnerabilitiesClient: vulnsClient, + Repo: repo, + RawResults: &ret.RawResults, + } + + // If the user runs probes + if len(probesToRun) > 0 { + err = runEnabledProbes(request, probesToRun, &ret) + if err != nil { + return ScorecardResult{}, err + } + return ret, nil + } + + // If the user runs checks + go runEnabledChecks(ctx, repo, request, checksToRun, resultsCh) for result := range resultsCh { ret.Checks = append(ret.Checks, result) @@ -176,3 +185,81 @@ func RunScorecard(ctx context.Context, } return ret, nil } + +func runEnabledProbes(request *checker.CheckRequest, + probesToRun []string, + ret *ScorecardResult, +) error { + // Add RawResults to request + err := populateRawResults(request, probesToRun, ret) + if err != nil { + return err + } + + probeFindings := make([]finding.Finding, 0) + for _, probeName := range probesToRun { + // Get the probe Run func + probeRunner, err := probes.GetProbeRunner(probeName) + if err != nil { + msg := fmt.Sprintf("could not find probe: %s", probeName) + return sce.WithMessage(sce.ErrScorecardInternal, msg) + } + // Run probe + findings, _, err := probeRunner(&ret.RawResults) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, "ending run") + } + probeFindings = append(probeFindings, findings...) + } + ret.Findings = probeFindings + return nil +} + +// RunScorecard runs enabled Scorecard checks on a Repo. +func RunScorecard(ctx context.Context, + repo clients.Repo, + commitSHA string, + commitDepth int, + checksToRun checker.CheckNameToFnMap, + repoClient clients.RepoClient, + ossFuzzRepoClient clients.RepoClient, + ciiClient clients.CIIBestPracticesClient, + vulnsClient clients.VulnerabilitiesClient, +) (ScorecardResult, error) { + return runScorecard(ctx, + repo, + commitSHA, + commitDepth, + checksToRun, + []string{}, + repoClient, + ossFuzzRepoClient, + ciiClient, + vulnsClient, + ) +} + +// ExperimentalRunProbes is experimental. Do not depend on it, it may be removed at any point. +func ExperimentalRunProbes(ctx context.Context, + repo clients.Repo, + commitSHA string, + commitDepth int, + checksToRun checker.CheckNameToFnMap, + probesToRun []string, + repoClient clients.RepoClient, + ossFuzzRepoClient clients.RepoClient, + ciiClient clients.CIIBestPracticesClient, + vulnsClient clients.VulnerabilitiesClient, +) (ScorecardResult, error) { + return runScorecard(ctx, + repo, + commitSHA, + commitDepth, + checksToRun, + probesToRun, + repoClient, + ossFuzzRepoClient, + ciiClient, + vulnsClient, + ) +} diff --git a/pkg/scorecard_result.go b/pkg/scorecard_result.go index ed06013b897..102f4e3ec0a 100644 --- a/pkg/scorecard_result.go +++ b/pkg/scorecard_result.go @@ -23,12 +23,19 @@ import ( "github.com/olekukonko/tablewriter" "github.com/ossf/scorecard/v4/checker" - "github.com/ossf/scorecard/v4/docs/checks" + "github.com/ossf/scorecard/v4/checks" + "github.com/ossf/scorecard/v4/checks/raw" + "github.com/ossf/scorecard/v4/checks/raw/github" + "github.com/ossf/scorecard/v4/checks/raw/gitlab" + "github.com/ossf/scorecard/v4/clients/githubrepo" + "github.com/ossf/scorecard/v4/clients/gitlabrepo" + docChecks "github.com/ossf/scorecard/v4/docs/checks" sce "github.com/ossf/scorecard/v4/errors" "github.com/ossf/scorecard/v4/finding" "github.com/ossf/scorecard/v4/log" "github.com/ossf/scorecard/v4/options" spol "github.com/ossf/scorecard/v4/policy" + "github.com/ossf/scorecard/v4/probes" ) // ScorecardInfo contains information about the scorecard code that was run. @@ -62,7 +69,7 @@ func scoreToString(s float64) string { } // GetAggregateScore returns the aggregate score. -func (r *ScorecardResult) GetAggregateScore(checkDocs checks.Doc) (float64, error) { +func (r *ScorecardResult) GetAggregateScore(checkDocs docChecks.Doc) (float64, error) { // TODO: calculate the score and make it a field // of ScorecardResult weights := map[string]float64{"Critical": 10, "High": 7.5, "Medium": 5, "Low": 2.5} @@ -105,7 +112,7 @@ func (r *ScorecardResult) GetAggregateScore(checkDocs checks.Doc) (float64, erro func FormatResults( opts *options.Options, results *ScorecardResult, - doc checks.Doc, + doc docChecks.Doc, policy *spol.ScorecardPolicy, ) error { var err error @@ -153,7 +160,7 @@ func FormatResults( // AsString returns ScorecardResult in string format. func (r *ScorecardResult) AsString(showDetails bool, logLevel log.Level, - checkDocs checks.Doc, writer io.Writer, + checkDocs docChecks.Doc, writer io.Writer, ) error { data := make([][]string, len(r.Checks)) @@ -225,3 +232,96 @@ func (r *ScorecardResult) AsString(showDetails bool, logLevel log.Level, return nil } + +func assignRawData(probeCheckName string, request *checker.CheckRequest, ret *ScorecardResult) error { + switch probeCheckName { + case checks.CheckSecurityPolicy: + rawData, err := raw.SecurityPolicy(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.SecurityPolicyResults = rawData + case checks.CheckDependencyUpdateTool: + rawData, err := raw.DependencyUpdateTool(request.RepoClient) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.DependencyUpdateToolResults = rawData + case checks.CheckFuzzing: + rawData, err := raw.Fuzzing(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.FuzzingResults = rawData + case checks.CheckPackaging: + switch request.RepoClient.(type) { + case *githubrepo.Client: + rawData, err := github.Packaging(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.PackagingResults = rawData + case *gitlabrepo.Client: + rawData, err := gitlab.Packaging(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.PackagingResults = rawData + default: + return sce.WithMessage(sce.ErrScorecardInternal, + "Only github and gitlab are supported") + } + case checks.CheckLicense: + rawData, err := raw.License(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.LicenseResults = rawData + case checks.CheckContributors: + rawData, err := raw.Contributors(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.ContributorsResults = rawData + case checks.CheckVulnerabilities: + rawData, err := raw.Vulnerabilities(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.VulnerabilitiesResults = rawData + case checks.CheckSAST: + rawData, err := raw.SAST(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.SASTResults = rawData + case checks.CheckDangerousWorkflow: + rawData, err := raw.DangerousWorkflow(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.DangerousWorkflowResults = rawData + case checks.CheckMaintained: + rawData, err := raw.Maintained(request) + if err != nil { + return sce.WithMessage(sce.ErrScorecardInternal, err.Error()) + } + ret.RawResults.MaintainedResults = rawData + } + return nil +} + +func populateRawResults(request *checker.CheckRequest, probesToRun []string, ret *ScorecardResult) error { + probeCheckNames := make([]string, 0) + for _, probeName := range probesToRun { + probeCheckName := probes.CheckMap[probeName] + if !contains(probeCheckNames, probeCheckName) { + probeCheckNames = append(probeCheckNames, probeCheckName) + err := assignRawData(probeCheckName, request, ret) + if err != nil { + return err + } + } + } + return nil +} diff --git a/pkg/scorecard_test.go b/pkg/scorecard_test.go index 76a4ced138b..32295b21275 100644 --- a/pkg/scorecard_test.go +++ b/pkg/scorecard_test.go @@ -21,9 +21,12 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/clients" "github.com/ossf/scorecard/v4/clients/localdir" mockrepo "github.com/ossf/scorecard/v4/clients/mockclients" + "github.com/ossf/scorecard/v4/finding" + "github.com/ossf/scorecard/v4/finding/probe" "github.com/ossf/scorecard/v4/log" ) @@ -187,3 +190,139 @@ func TestRunScorecard(t *testing.T) { }) } } + +func TestExperimentalRunProbes(t *testing.T) { + t.Parallel() + type args struct { + uri string + commitSHA string + probes []string + } + tests := []struct { + files []string + name string + args args + want ScorecardResult + wantErr bool + }{ + { + name: "empty commits repos should return repo details but no checks", + args: args{ + uri: "github.com/ossf/scorecard", + commitSHA: "1a17bb812fb2ac23e9d09e86e122f8b67563aed7", + probes: []string{"fuzzedWithOSSFuzz"}, + }, + want: ScorecardResult{ + Repo: RepoInfo{ + Name: "github.com/ossf/scorecard", + CommitSHA: "1a17bb812fb2ac23e9d09e86e122f8b67563aed7", + }, + RawResults: checker.RawResults{ + Metadata: checker.MetadataData{ + Metadata: map[string]string{ + "repository.defaultBranch": "main", + "repository.host": "github.com", + "repository.name": "ossf/scorecard", + "repository.sha1": "1a17bb812fb2ac23e9d09e86e122f8b67563aed7", + "repository.uri": "github.com/ossf/scorecard", + }, + }, + }, + Scorecard: ScorecardInfo{ + CommitSHA: "unknown", + }, + Findings: []finding.Finding{ + { + Probe: "fuzzedWithOSSFuzz", + Message: "no OSSFuzz integration found", + Remediation: &probe.Remediation{ + Effort: 3, + }, + }, + }, + }, + wantErr: false, + }, + { + name: "Wrong probe", + args: args{ + uri: "github.com/ossf/scorecard", + commitSHA: "1a17bb812fb2ac23e9d09e86e122f8b67563aed7", + probes: []string{"nonExistentProbe"}, + }, + want: ScorecardResult{}, + wantErr: true, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ctrl := gomock.NewController(t) + mockRepoClient := mockrepo.NewMockRepoClient(ctrl) + repo := mockrepo.NewMockRepo(ctrl) + + repo.EXPECT().URI().Return(tt.args.uri).AnyTimes() + repo.EXPECT().Host().Return("github.com").AnyTimes() + + mockRepoClient.EXPECT().InitRepo(repo, tt.args.commitSHA, 0).Return(nil) + + mockRepoClient.EXPECT().Close().DoAndReturn(func() error { + return nil + }) + + mockRepoClient.EXPECT().ListCommits().DoAndReturn(func() ([]clients.Commit, error) { + if tt.args.commitSHA == "" { + return []clients.Commit{}, nil + } + return []clients.Commit{ + { + SHA: tt.args.commitSHA, + }, + }, nil + }) + mockRepoClient.EXPECT().ListFiles(gomock.Any()).Return(tt.files, nil).AnyTimes() + progLanguages := []clients.Language{ + { + Name: clients.Go, + NumLines: 100, + }, + { + Name: clients.Java, + NumLines: 70, + }, + { + Name: clients.Cpp, + NumLines: 100, + }, + { + Name: clients.Ruby, + NumLines: 70, + }, + } + mockRepoClient.EXPECT().ListProgrammingLanguages().Return(progLanguages, nil).AnyTimes() + + mockRepoClient.EXPECT().GetDefaultBranchName().Return("main", nil).AnyTimes() + got, err := ExperimentalRunProbes(context.Background(), + repo, + tt.args.commitSHA, + 0, + nil, + tt.args.probes, + mockRepoClient, + nil, + nil, + nil) + if (err != nil) != tt.wantErr { + t.Errorf("RunScorecard() error = %v, wantErr %v", err, tt.wantErr) + return + } + ignoreRemediationText := cmpopts.IgnoreFields(probe.Remediation{}, "Text", "Markdown") + ignoreDate := cmpopts.IgnoreFields(ScorecardResult{}, "Date") + if !cmp.Equal(got, tt.want, ignoreDate, ignoreRemediationText) { + t.Errorf("expected %v, got %v", got, cmp.Diff(tt.want, got, ignoreDate, + ignoreRemediationText)) + } + }) + } +} diff --git a/probes/entries.go b/probes/entries.go index 9f4f8ede19a..6414d224e21 100644 --- a/probes/entries.go +++ b/probes/entries.go @@ -15,6 +15,8 @@ package probes import ( + "errors" + "github.com/ossf/scorecard/v4/checker" "github.com/ossf/scorecard/v4/finding" "github.com/ossf/scorecard/v4/probes/contributorsFromOrgOrCompany" @@ -133,6 +135,82 @@ var ( CITests = []ProbeImpl{ testsRunInCI.Run, } + + probeRunners = map[string]func(*checker.RawResults) ([]finding.Finding, string, error){ + securityPolicyPresent.Probe: securityPolicyPresent.Run, + securityPolicyContainsLinks.Probe: securityPolicyContainsLinks.Run, + securityPolicyContainsVulnerabilityDisclosure.Probe: securityPolicyContainsVulnerabilityDisclosure.Run, + securityPolicyContainsText.Probe: securityPolicyContainsText.Run, + toolRenovateInstalled.Probe: toolRenovateInstalled.Run, + toolDependabotInstalled.Probe: toolDependabotInstalled.Run, + toolPyUpInstalled.Probe: toolPyUpInstalled.Run, + fuzzedWithOSSFuzz.Probe: fuzzedWithOSSFuzz.Run, + fuzzedWithGoNative.Probe: fuzzedWithGoNative.Run, + fuzzedWithPythonAtheris.Probe: fuzzedWithPythonAtheris.Run, + fuzzedWithCLibFuzzer.Probe: fuzzedWithCLibFuzzer.Run, + fuzzedWithCppLibFuzzer.Probe: fuzzedWithCppLibFuzzer.Run, + fuzzedWithSwiftLibFuzzer.Probe: fuzzedWithSwiftLibFuzzer.Run, + fuzzedWithRustCargofuzz.Probe: fuzzedWithRustCargofuzz.Run, + fuzzedWithJavaJazzerFuzzer.Probe: fuzzedWithJavaJazzerFuzzer.Run, + fuzzedWithClusterFuzzLite.Probe: fuzzedWithClusterFuzzLite.Run, + fuzzedWithPropertyBasedHaskell.Probe: fuzzedWithPropertyBasedHaskell.Run, + fuzzedWithPropertyBasedTypescript.Probe: fuzzedWithPropertyBasedTypescript.Run, + fuzzedWithPropertyBasedJavascript.Probe: fuzzedWithPropertyBasedJavascript.Run, + packagedWithAutomatedWorkflow.Probe: packagedWithAutomatedWorkflow.Run, + hasLicenseFile.Probe: hasLicenseFile.Run, + hasFSFOrOSIApprovedLicense.Probe: hasFSFOrOSIApprovedLicense.Run, + hasLicenseFileAtTopDir.Probe: hasLicenseFileAtTopDir.Run, + contributorsFromOrgOrCompany.Probe: contributorsFromOrgOrCompany.Run, + hasOSVVulnerabilities.Probe: hasOSVVulnerabilities.Run, + sastToolCodeQLInstalled.Probe: sastToolCodeQLInstalled.Run, + sastToolRunsOnAllCommits.Probe: sastToolRunsOnAllCommits.Run, + sastToolSonarInstalled.Probe: sastToolSonarInstalled.Run, + hasDangerousWorkflowScriptInjection.Probe: hasDangerousWorkflowScriptInjection.Run, + hasDangerousWorkflowUntrustedCheckout.Probe: hasDangerousWorkflowUntrustedCheckout.Run, + notArchived.Probe: notArchived.Run, + hasRecentCommits.Probe: hasRecentCommits.Run, + issueActivityByProjectMember.Probe: issueActivityByProjectMember.Run, + notCreatedRecently.Probe: notCreatedRecently.Run, + } + + CheckMap = map[string]string{ + securityPolicyPresent.Probe: "Security-Policy", + securityPolicyContainsLinks.Probe: "Security-Policy", + securityPolicyContainsVulnerabilityDisclosure.Probe: "Security-Policy", + securityPolicyContainsText.Probe: "Security-Policy", + toolRenovateInstalled.Probe: "Dependency-Update-Tool", + toolDependabotInstalled.Probe: "Dependency-Update-Tool", + toolPyUpInstalled.Probe: "Dependency-Update-Tool", + fuzzedWithOSSFuzz.Probe: "Fuzzing", + fuzzedWithGoNative.Probe: "Fuzzing", + fuzzedWithPythonAtheris.Probe: "Fuzzing", + fuzzedWithCLibFuzzer.Probe: "Fuzzing", + fuzzedWithCppLibFuzzer.Probe: "Fuzzing", + fuzzedWithSwiftLibFuzzer.Probe: "Fuzzing", + fuzzedWithRustCargofuzz.Probe: "Fuzzing", + fuzzedWithJavaJazzerFuzzer.Probe: "Fuzzing", + fuzzedWithClusterFuzzLite.Probe: "Fuzzing", + fuzzedWithPropertyBasedHaskell.Probe: "Fuzzing", + fuzzedWithPropertyBasedTypescript.Probe: "Fuzzing", + fuzzedWithPropertyBasedJavascript.Probe: "Fuzzing", + packagedWithAutomatedWorkflow.Probe: "Packaging", + hasLicenseFile.Probe: "License", + hasFSFOrOSIApprovedLicense.Probe: "License", + hasLicenseFileAtTopDir.Probe: "License", + contributorsFromOrgOrCompany.Probe: "Contributors", + hasOSVVulnerabilities.Probe: "Vulnerabilities", + sastToolCodeQLInstalled.Probe: "SAST", + sastToolRunsOnAllCommits.Probe: "SAST", + sastToolSonarInstalled.Probe: "SAST", + hasDangerousWorkflowScriptInjection.Probe: "Dangerous-Workflow", + hasDangerousWorkflowUntrustedCheckout.Probe: "Dangerous-Workflow", + notArchived.Probe: "Maintained", + hasRecentCommits.Probe: "Maintained", + issueActivityByProjectMember.Probe: "Maintained", + notCreatedRecently.Probe: "Maintained", + } + + errProbeNotFound = errors.New("probe not found") ) //nolint:gochecknoinits @@ -146,6 +224,13 @@ func init() { }) } +func GetProbeRunner(probeName string) (func(*checker.RawResults) ([]finding.Finding, string, error), error) { + if runner, ok := probeRunners[probeName]; ok { + return runner, nil + } + return nil, errProbeNotFound +} + func concatMultipleProbes(slices [][]ProbeImpl) []ProbeImpl { var totalLen int for _, s := range slices {