🌱 Add probe registration mechanism (#3876)

* add basic probe registration function

Signed-off-by: Spencer Schrock <sschrock@google.com>

* ignore probes which call init to register the probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* redefine probeimpl to avoid circular imports

Signed-off-by: Spencer Schrock <sschrock@google.com>

* register all probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* experiment with a probe struct

Signed-off-by: Spencer Schrock <sschrock@google.com>

* make check name constants

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert branch protection probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert binary artifact probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert cii probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert ci test probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert code review probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert contributor probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert dangerous workflow probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert dep update tool probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert fuzzing probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert license probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert maintained probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert packaging probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert sast probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert security policy probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert signed releases probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert vuln probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* try using probe registration data

Signed-off-by: Spencer Schrock <sschrock@google.com>

* blank import unused probe

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add uncategorized group

Signed-off-by: Spencer Schrock <sschrock@google.com>

* ensure All list is up-to-date

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add reason behind uncategorized group

Signed-off-by: Spencer Schrock <sschrock@google.com>

* fix linter yaml parse error

Signed-off-by: Spencer Schrock <sschrock@google.com>

* fix linter

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add webhook data

Signed-off-by: Spencer Schrock <sschrock@google.com>

* convert probe registration to Must pattern

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add registration for new probes

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add missing license header

Signed-off-by: Spencer Schrock <sschrock@google.com>

* revert changing wrapcheck linter config

Signed-off-by: Spencer Schrock <sschrock@google.com>

* use error func which doesnt need wrapped

Signed-off-by: Spencer Schrock <sschrock@google.com>

* add test for probe registration

Signed-off-by: Spencer Schrock <sschrock@google.com>

* restore trailing newline

Signed-off-by: Spencer Schrock <sschrock@google.com>

* order probe category list

Signed-off-by: Spencer Schrock <sschrock@google.com>

---------

Signed-off-by: Spencer Schrock <sschrock@google.com>
This commit is contained in:
Spencer Schrock 2024-03-19 13:10:11 -07:00 committed by GitHub
parent 2c02d4b816
commit b3ad602a59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 578 additions and 103 deletions

View File

@ -21,6 +21,10 @@ issues:
- goerr113
- lll
- wrapcheck
# probes must register via init
- path: 'probes/.+/impl.go'
linters:
- gochecknoinits
skip-files:
- cron/data/request.pb.go # autogenerated
linters:

93
internal/probes/probes.go Normal file
View File

@ -0,0 +1,93 @@
// Copyright 2024 OpenSSF 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 probes
import (
"fmt"
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/errors"
"github.com/ossf/scorecard/v4/finding"
)
type CheckName string
// Redefining check names here to avoid circular imports.
const (
BinaryArtifacts CheckName = "Binary-Artifacts"
BranchProtection CheckName = "Branch-Protection"
CIIBestPractices CheckName = "CII-Best-Practices"
CITests CheckName = "CI-Tests"
CodeReview CheckName = "Code-Review"
Contributors CheckName = "Contributors"
DangerousWorkflow CheckName = "Dangerous-Workflow"
DependencyUpdateTool CheckName = "Dependency-Update-Tool"
Fuzzing CheckName = "Fuzzing"
License CheckName = "License"
Maintained CheckName = "Maintained"
Packaging CheckName = "Packaging"
PinnedDependencies CheckName = "Pinned-Dependencies"
SAST CheckName = "SAST"
SecurityPolicy CheckName = "Security-Policy"
SignedReleases CheckName = "Signed-Releases"
TokenPermissions CheckName = "Token-Permissions"
Vulnerabilities CheckName = "Vulnerabilities"
Webhooks CheckName = "Webhooks"
)
type Probe struct {
Name string
Implementation ProbeImpl
RequiredRawData []CheckName
}
type ProbeImpl func(*checker.RawResults) ([]finding.Finding, string, error)
// registered is the mapping of all registered probes.
var registered = map[string]Probe{}
func MustRegister(name string, impl ProbeImpl, requiredRawData []CheckName) {
err := register(Probe{
Name: name,
Implementation: impl,
RequiredRawData: requiredRawData,
})
if err != nil {
panic(err)
}
}
func register(p Probe) error {
if p.Name == "" {
return errors.WithMessage(errors.ErrScorecardInternal, "name cannot be empty")
}
if p.Implementation == nil {
return errors.WithMessage(errors.ErrScorecardInternal, "implementation cannot be nil")
}
if len(p.RequiredRawData) == 0 {
return errors.WithMessage(errors.ErrScorecardInternal, "probes need some raw data")
}
registered[p.Name] = p
return nil
}
func Get(name string) (Probe, error) {
p, ok := registered[name]
if !ok {
msg := fmt.Sprintf("probe %q not found", name)
return Probe{}, errors.WithMessage(errors.ErrScorecardInternal, msg)
}
return p, nil
}

View File

@ -0,0 +1,144 @@
// Copyright 2024 OpenSSF 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 probes
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
)
func emptyImpl(r *checker.RawResults) ([]finding.Finding, string, error) {
return nil, "", nil
}
var (
p1 = Probe{
Name: "someProbe1",
Implementation: emptyImpl,
RequiredRawData: []CheckName{BinaryArtifacts},
}
p2 = Probe{
Name: "someProbe2",
Implementation: emptyImpl,
RequiredRawData: []CheckName{BranchProtection},
}
)
//nolint:paralleltest // registration isn't safe for concurrent use
func Test_register(t *testing.T) {
tests := []struct {
name string
probe Probe
wantErr bool
}{
{
name: "name is required",
probe: Probe{
Name: "",
Implementation: emptyImpl,
RequiredRawData: []CheckName{BinaryArtifacts},
},
wantErr: true,
},
{
name: "implementation is required",
probe: Probe{
Name: "foo",
Implementation: nil,
RequiredRawData: []CheckName{BinaryArtifacts},
},
wantErr: true,
},
{
name: "raw check data is required",
probe: Probe{
Name: "foo",
Implementation: emptyImpl,
RequiredRawData: []CheckName{},
},
wantErr: true,
},
{
name: "valid registration",
probe: Probe{
Name: "foo",
Implementation: emptyImpl,
RequiredRawData: []CheckName{BinaryArtifacts},
},
wantErr: false,
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
err := register(tt.probe)
if err != nil != tt.wantErr {
t.Fatalf("got err: %v, wanted err: %t", err, tt.wantErr)
}
})
}
}
func setupControlledProbes(t *testing.T) {
t.Helper()
err := register(p1)
if err != nil {
t.Fatalf("unable to register someProbe1")
}
err = register(p2)
if err != nil {
t.Fatalf("unable to register someProbe2")
}
}
//nolint:paralleltest // registration isn't safe for concurrent use
func TestGet(t *testing.T) {
tests := []struct {
name string
probeName string
expected Probe
wantErr bool
}{
{
name: "probe is found",
probeName: p1.Name,
expected: p1,
wantErr: false,
},
{
name: "probe not found",
probeName: "noProbeCalledThis",
wantErr: true,
},
}
setupControlledProbes(t)
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
p, err := Get(tt.probeName)
if err != nil != tt.wantErr {
t.Fatalf("got err: %v, wanted err: %t", err, tt.wantErr)
}
if diff := cmp.Diff(p.Name, tt.expected.Name); diff != "" {
t.Error("probes didn't match: " + diff)
}
})
}
}

View File

@ -30,6 +30,7 @@ import (
"github.com/ossf/scorecard/v4/clients"
sce "github.com/ossf/scorecard/v4/errors"
"github.com/ossf/scorecard/v4/finding"
proberegistration "github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/options"
"github.com/ossf/scorecard/v4/probes"
"github.com/ossf/scorecard/v4/probes/zrunner"
@ -198,14 +199,12 @@ func runEnabledProbes(request *checker.CheckRequest,
probeFindings := make([]finding.Finding, 0)
for _, probeName := range probesToRun {
// Get the probe Run func
probeRunner, err := probes.GetProbeRunner(probeName)
probe, err := proberegistration.Get(probeName)
if err != nil {
msg := fmt.Sprintf("could not find probe: %s", probeName)
return sce.WithMessage(sce.ErrScorecardInternal, msg)
return fmt.Errorf("getting probe %q: %w", probeName, err)
}
// Run probe
findings, _, err := probeRunner(&ret.RawResults)
findings, _, err := probe.Implementation(&ret.RawResults)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, "ending run")
}

View File

@ -32,10 +32,10 @@ import (
docChecks "github.com/ossf/scorecard/v4/docs/checks"
sce "github.com/ossf/scorecard/v4/errors"
"github.com/ossf/scorecard/v4/finding"
proberegistration "github.com/ossf/scorecard/v4/internal/probes"
"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.
@ -234,14 +234,51 @@ func (r *ScorecardResult) AsString(showDetails bool, logLevel log.Level,
return nil
}
//nolint:gocognit,gocyclo // nothing better to do right now
func assignRawData(probeCheckName string, request *checker.CheckRequest, ret *ScorecardResult) error {
switch probeCheckName {
case checks.CheckSecurityPolicy:
rawData, err := raw.SecurityPolicy(request)
case checks.CheckBinaryArtifacts:
rawData, err := raw.BinaryArtifacts(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.SecurityPolicyResults = rawData
ret.RawResults.BinaryArtifactResults = rawData
case checks.CheckBranchProtection:
rawData, err := raw.BranchProtection(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.BranchProtectionResults = rawData
case checks.CheckCIIBestPractices:
rawData, err := raw.CIIBestPractices(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.CIIBestPracticesResults = rawData
case checks.CheckCITests:
rawData, err := raw.CITests(request.RepoClient)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.CITestResults = rawData
case checks.CheckCodeReview:
rawData, err := raw.CodeReview(request.RepoClient)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.CodeReviewResults = 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.CheckDangerousWorkflow:
rawData, err := raw.DangerousWorkflow(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.DangerousWorkflowResults = rawData
case checks.CheckDependencyUpdateTool:
rawData, err := raw.DependencyUpdateTool(request.RepoClient)
if err != nil {
@ -254,6 +291,18 @@ func assignRawData(probeCheckName string, request *checker.CheckRequest, ret *Sc
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.FuzzingResults = rawData
case checks.CheckLicense:
rawData, err := raw.License(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.LicenseResults = rawData
case checks.CheckMaintained:
rawData, err := raw.Maintained(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.MaintainedResults = rawData
case checks.CheckPackaging:
switch request.RepoClient.(type) {
case *githubrepo.Client:
@ -269,58 +318,71 @@ func assignRawData(probeCheckName string, request *checker.CheckRequest, ret *Sc
}
ret.RawResults.PackagingResults = rawData
default:
return sce.WithMessage(sce.ErrScorecardInternal,
"Only github and gitlab are supported")
return sce.WithMessage(sce.ErrScorecardInternal, "Only github and gitlab are supported")
}
case checks.CheckLicense:
rawData, err := raw.License(request)
case checks.CheckPinnedDependencies:
rawData, err := raw.PinningDependencies(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
ret.RawResults.PinningDependenciesResults = 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)
case checks.CheckSecurityPolicy:
rawData, err := raw.SecurityPolicy(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.DangerousWorkflowResults = rawData
case checks.CheckMaintained:
rawData, err := raw.Maintained(request)
ret.RawResults.SecurityPolicyResults = rawData
case checks.CheckSignedReleases:
rawData, err := raw.SignedReleases(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.MaintainedResults = rawData
ret.RawResults.SignedReleasesResults = rawData
case checks.CheckTokenPermissions:
rawData, err := raw.TokenPermissions(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.TokenPermissionsResults = 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.CheckWebHooks:
rawData, err := raw.WebHook(request)
if err != nil {
return sce.WithMessage(sce.ErrScorecardInternal, err.Error())
}
ret.RawResults.WebhookResults = rawData
default:
return sce.WithMessage(sce.ErrScorecardInternal, "unknown check")
}
return nil
}
func populateRawResults(request *checker.CheckRequest, probesToRun []string, ret *ScorecardResult) error {
probeCheckNames := make([]string, 0)
seen := map[string]bool{}
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
p, err := proberegistration.Get(probeName)
if err != nil {
return fmt.Errorf("getting probe %q: %w", probeName, err)
}
for _, checkName := range p.RequiredRawData {
checkName := string(checkName)
if !seen[checkName] {
err := assignRawData(checkName, request, ret)
if err != nil {
return err
}
seen[checkName] = true
}
}
}

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/branchprotection"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -23,9 +23,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.CodeReview})
}
var (
//go:embed *.yml
fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/utils"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.CodeReview})
}
var (
//go:embed *.yml
fs embed.FS
@ -32,13 +37,13 @@ var (
)
const (
probe = "codeReviewOneReviewers"
Probe = "codeReviewOneReviewers"
minimumReviewers = 1
)
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
rawReviewData := &raw.CodeReviewResults
return codeReviewRun(rawReviewData, fs, probe, finding.OutcomePositive, finding.OutcomeNegative)
return codeReviewRun(rawReviewData, fs, Probe, finding.OutcomePositive, finding.OutcomeNegative)
}
// Looks through the data and validates author and reviewers of a changeset

View File

@ -324,7 +324,7 @@ func TestProbeCodeReviewOneReviewers(t *testing.T) {
t.Errorf("Expected error %v, got nil", tt.err)
case res == nil && err == nil:
t.Errorf("Probe(s) returned nil for both finding and error")
case probeID != probe:
case probeID != Probe:
t.Errorf("Probe returned the wrong probe ID")
default:
for i := range tt.expectedFindings {

View File

@ -21,6 +21,7 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
@ -28,6 +29,10 @@ const (
minContributionsPerUser = 5
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Contributors})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/branchprotection"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -15,8 +15,6 @@
package probes
import (
"errors"
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/probes/blocksDeleteOnBranches"
@ -27,6 +25,7 @@ import (
"github.com/ossf/scorecard/v4/probes/codeReviewOneReviewers"
"github.com/ossf/scorecard/v4/probes/contributorsFromOrgOrCompany"
"github.com/ossf/scorecard/v4/probes/dismissesStaleReviews"
"github.com/ossf/scorecard/v4/probes/freeOfAnyBinaryArtifacts"
"github.com/ossf/scorecard/v4/probes/freeOfUnverifiedBinaryArtifacts"
"github.com/ossf/scorecard/v4/probes/fuzzed"
"github.com/ossf/scorecard/v4/probes/hasDangerousWorkflowScriptInjection"
@ -113,7 +112,6 @@ var (
hasDangerousWorkflowScriptInjection.Run,
hasDangerousWorkflowUntrustedCheckout.Run,
}
Maintained = []ProbeImpl{
notArchived.Run,
hasRecentCommits.Run,
@ -153,76 +151,36 @@ var (
pinsDependencies.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,
fuzzed.Probe: fuzzed.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,
sastToolRunsOnAllCommits.Probe: sastToolRunsOnAllCommits.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,
// Probes which aren't included by any checks.
// These still need to be listed so they can be called with --probes.
Uncategorized = []ProbeImpl{
freeOfAnyBinaryArtifacts.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",
fuzzed.Probe: "Fuzzing",
packagedWithAutomatedWorkflow.Probe: "Packaging",
hasLicenseFile.Probe: "License",
hasFSFOrOSIApprovedLicense.Probe: "License",
hasLicenseFileAtTopDir.Probe: "License",
contributorsFromOrgOrCompany.Probe: "Contributors",
hasOSVVulnerabilities.Probe: "Vulnerabilities",
sastToolRunsOnAllCommits.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
func init() {
All = concatMultipleProbes([][]ProbeImpl{
DependencyToolUpdates,
BinaryArtifacts,
CIIBestPractices,
CITests,
CodeReview,
SecurityPolicy,
Contributors,
DangerousWorkflows,
DependencyToolUpdates,
Fuzzing,
License,
Contributors,
Maintained,
Packaging,
SAST,
SecurityPolicy,
SignedReleases,
Uncategorized,
Vulnerabilities,
Webhook,
})
}
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 {

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BinaryArtifacts})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BinaryArtifacts})
}
//go:embed *.yml
var fs embed.FS

View File

@ -20,9 +20,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Fuzzing})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.DangerousWorkflow})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.DangerousWorkflow})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.License})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.License})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.License})
}
//go:embed *.yml
var fs embed.FS

View File

@ -25,9 +25,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Vulnerabilities})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.CIIBestPractices})
}
//go:embed *.yml
var fs embed.FS

View File

@ -23,9 +23,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Maintained})
}
//go:embed *.yml
var fs embed.FS

View File

@ -24,9 +24,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/clients"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Maintained})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Maintained})
}
//go:embed *.yml
var fs embed.FS

View File

@ -23,9 +23,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Maintained})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Packaging})
}
//go:embed *.yml
var fs embed.FS

View File

@ -24,10 +24,15 @@ import (
sce "github.com/ossf/scorecard/v4/errors"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/finding/probe"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
"github.com/ossf/scorecard/v4/rule"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.PinnedDependencies})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SignedReleases})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SignedReleases})
}
//go:embed *.yml
var fs embed.FS

View File

@ -23,9 +23,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/branchprotection"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/branchprotection"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.BranchProtection})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SAST})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SAST})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/secpolicy"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SecurityPolicy})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/secpolicy"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SecurityPolicy})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/secpolicy"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SecurityPolicy})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.SecurityPolicy})
}
//go:embed *.yml
var fs embed.FS

View File

@ -22,9 +22,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.CITests})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
tls "github.com/ossf/scorecard/v4/probes/internal/utils/tools"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.DependencyUpdateTool})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
tls "github.com/ossf/scorecard/v4/probes/internal/utils/tools"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.DependencyUpdateTool})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,10 +21,15 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
tls "github.com/ossf/scorecard/v4/probes/internal/utils/tools"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.DependencyUpdateTool})
}
//go:embed *.yml
var fs embed.FS

View File

@ -21,9 +21,14 @@ import (
"github.com/ossf/scorecard/v4/checker"
"github.com/ossf/scorecard/v4/finding"
"github.com/ossf/scorecard/v4/internal/probes"
"github.com/ossf/scorecard/v4/probes/internal/utils/uerror"
)
func init() {
probes.MustRegister(Probe, Run, []probes.CheckName{probes.Webhooks})
}
//go:embed *.yml
var fs embed.FS