mirror of
https://github.com/ossf/scorecard.git
synced 2024-09-11 08:55:27 +03:00
✨ [experimental] Probe support for fuzzing check (#3230)
* update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * update Signed-off-by: laurentsimon <laurentsimon@google.com> * comments Signed-off-by: laurentsimon <laurentsimon@google.com> * unit tests and linter Signed-off-by: laurentsimon <laurentsimon@google.com> * remove raw from check request in e2e tests Signed-off-by: laurentsimon <laurentsimon@google.com> * remove redundant finding check Signed-off-by: laurentsimon <laurentsimon@google.com> * typo Signed-off-by: laurentsimon <laurentsimon@google.com> * adress comments Signed-off-by: laurentsimon <laurentsimon@google.com> --------- Signed-off-by: laurentsimon <laurentsimon@google.com>
This commit is contained in:
parent
7f64da758a
commit
d177169ec2
@ -123,6 +123,10 @@ func TestDependencyUpdateTool(t *testing.T) {
|
|||||||
Probe: "toolSonatypeLiftInstalled",
|
Probe: "toolSonatypeLiftInstalled",
|
||||||
Outcome: finding.OutcomePositive,
|
Outcome: finding.OutcomePositive,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolRenovateInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
want: checker.CheckResult{
|
want: checker.CheckResult{
|
||||||
Score: 10,
|
Score: 10,
|
||||||
@ -153,7 +157,50 @@ func TestDependencyUpdateTool(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "empty tool list",
|
name: "missing probes renovate",
|
||||||
|
findings: []finding.Finding{
|
||||||
|
{
|
||||||
|
Probe: "toolDependabotInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolPyUpInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolSonatypeInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: true,
|
||||||
|
want: checker.CheckResult{
|
||||||
|
Score: -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invalid probe name",
|
||||||
|
findings: []finding.Finding{
|
||||||
|
{
|
||||||
|
Probe: "toolDependabotInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolRenovateInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolPyUpInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolSonatypeInstalled",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "toolInvalidProbeName",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
want: checker.CheckResult{
|
want: checker.CheckResult{
|
||||||
Score: -1,
|
Score: -1,
|
||||||
},
|
},
|
||||||
|
@ -15,40 +15,44 @@
|
|||||||
package evaluation
|
package evaluation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/ossf/scorecard/v4/checker"
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
sce "github.com/ossf/scorecard/v4/errors"
|
sce "github.com/ossf/scorecard/v4/errors"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithClusterFuzzLite"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithGoNative"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithOSSFuzz"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithOneFuzz"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedHaskell"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedJavascript"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedTypescript"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fuzzing applies the score policy for the Fuzzing check.
|
// Fuzzing applies the score policy for the Fuzzing check.
|
||||||
func Fuzzing(name string, dl checker.DetailLogger,
|
func Fuzzing(name string,
|
||||||
r *checker.FuzzingData,
|
findings []finding.Finding,
|
||||||
) checker.CheckResult {
|
) checker.CheckResult {
|
||||||
if r == nil {
|
// We have 7 unique probes, each should have a finding.
|
||||||
e := sce.WithMessage(sce.ErrScorecardInternal, "empty raw data")
|
expectedProbes := []string{
|
||||||
|
fuzzedWithClusterFuzzLite.Probe,
|
||||||
|
fuzzedWithGoNative.Probe,
|
||||||
|
fuzzedWithOneFuzz.Probe,
|
||||||
|
fuzzedWithOSSFuzz.Probe,
|
||||||
|
fuzzedWithPropertyBasedHaskell.Probe,
|
||||||
|
fuzzedWithPropertyBasedJavascript.Probe,
|
||||||
|
fuzzedWithPropertyBasedTypescript.Probe,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !finding.UniqueProbesEqual(findings, expectedProbes) {
|
||||||
|
e := sce.WithMessage(sce.ErrScorecardInternal, "invalid probe results")
|
||||||
return checker.CreateRuntimeErrorResult(name, e)
|
return checker.CreateRuntimeErrorResult(name, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(r.Fuzzers) == 0 {
|
// Compute the score.
|
||||||
return checker.CreateMinScoreResult(name, "project is not fuzzed")
|
for i := range findings {
|
||||||
}
|
f := &findings[i]
|
||||||
fuzzers := []string{}
|
if f.Outcome == finding.OutcomePositive {
|
||||||
for i := range r.Fuzzers {
|
return checker.CreateMaxScoreResult(name, "project is fuzzed")
|
||||||
fuzzer := r.Fuzzers[i]
|
|
||||||
for _, f := range fuzzer.Files {
|
|
||||||
msg := checker.LogMessage{
|
|
||||||
Path: f.Path,
|
|
||||||
Type: f.Type,
|
|
||||||
Offset: f.Offset,
|
|
||||||
}
|
|
||||||
if f.Snippet != "" {
|
|
||||||
msg.Text = f.Snippet
|
|
||||||
}
|
|
||||||
dl.Info(&msg)
|
|
||||||
}
|
}
|
||||||
fuzzers = append(fuzzers, fuzzer.Name)
|
|
||||||
}
|
}
|
||||||
return checker.CreateMaxScoreResult(name,
|
return checker.CreateMinScoreResult(name, "project is not fuzzed")
|
||||||
fmt.Sprintf("project is fuzzed with %v", fuzzers))
|
|
||||||
}
|
}
|
||||||
|
@ -20,15 +20,14 @@ import (
|
|||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
"github.com/ossf/scorecard/v4/checker"
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
scut "github.com/ossf/scorecard/v4/utests"
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFuzzing(t *testing.T) {
|
func TestFuzzing(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
type args struct { //nolint
|
type args struct { //nolint
|
||||||
name string
|
name string
|
||||||
dl checker.DetailLogger
|
findings []finding.Finding
|
||||||
r *checker.FuzzingData
|
|
||||||
}
|
}
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@ -39,8 +38,36 @@ func TestFuzzing(t *testing.T) {
|
|||||||
name: "Fuzzing - no fuzzing",
|
name: "Fuzzing - no fuzzing",
|
||||||
args: args{
|
args: args{
|
||||||
name: "Fuzzing",
|
name: "Fuzzing",
|
||||||
dl: &scut.TestDetailLogger{},
|
findings: []finding.Finding{
|
||||||
r: &checker.FuzzingData{},
|
{
|
||||||
|
Probe: "fuzzedWithClusterFuzzLite",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithGoNative",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOneFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOSSFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedHaskell",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedJavascript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedTypescript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
want: checker.CheckResult{
|
want: checker.CheckResult{
|
||||||
Score: 0,
|
Score: 0,
|
||||||
@ -50,23 +77,37 @@ func TestFuzzing(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Fuzzing - fuzzing",
|
name: "Fuzzing - fuzzing GoNative",
|
||||||
args: args{
|
args: args{
|
||||||
name: "Fuzzing",
|
name: "Fuzzing",
|
||||||
dl: &scut.TestDetailLogger{},
|
findings: []finding.Finding{
|
||||||
r: &checker.FuzzingData{
|
{
|
||||||
Fuzzers: []checker.Tool{
|
Probe: "fuzzedWithClusterFuzzLite",
|
||||||
{
|
Outcome: finding.OutcomeNegative,
|
||||||
Name: "Fuzzing",
|
},
|
||||||
Files: []checker.File{
|
{
|
||||||
{
|
Probe: "fuzzedWithGoNative",
|
||||||
Path: "Fuzzing",
|
Outcome: finding.OutcomePositive,
|
||||||
Type: 0,
|
},
|
||||||
Offset: 1,
|
{
|
||||||
Snippet: "Fuzzing",
|
Probe: "fuzzedWithOneFuzz",
|
||||||
},
|
Outcome: finding.OutcomeNegative,
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
|
Probe: "fuzzedWithOSSFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedHaskell",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedJavascript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedTypescript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -74,21 +115,91 @@ func TestFuzzing(t *testing.T) {
|
|||||||
Score: 10,
|
Score: 10,
|
||||||
Name: "Fuzzing",
|
Name: "Fuzzing",
|
||||||
Version: 2,
|
Version: 2,
|
||||||
Reason: "project is fuzzed with [Fuzzing]",
|
Reason: "project is fuzzed",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Fuzzing - fuzzing data nil",
|
name: "Fuzzing - fuzzing missing GoNative finding",
|
||||||
args: args{
|
args: args{
|
||||||
name: "Fuzzing",
|
name: "Fuzzing",
|
||||||
dl: &scut.TestDetailLogger{},
|
findings: []finding.Finding{
|
||||||
r: nil,
|
{
|
||||||
|
Probe: "fuzzedWithClusterFuzzLite",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOneFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOSSFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedHaskell",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedJavascript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedTypescript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
want: checker.CheckResult{
|
want: checker.CheckResult{
|
||||||
Score: -1,
|
Score: -1,
|
||||||
Name: "Fuzzing",
|
Name: "Fuzzing",
|
||||||
Version: 2,
|
Version: 2,
|
||||||
Reason: "internal error: empty raw data",
|
Reason: "internal error: invalid probe results",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Fuzzing - fuzzing invalid probe name",
|
||||||
|
args: args{
|
||||||
|
name: "Fuzzing",
|
||||||
|
findings: []finding.Finding{
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithClusterFuzzLite",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithGoNative",
|
||||||
|
Outcome: finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOneFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithOSSFuzz",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedHaskell",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedJavascript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithPropertyBasedTypescript",
|
||||||
|
Outcome: finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Probe: "fuzzedWithInvalidProbeName",
|
||||||
|
Outcome: finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: checker.CheckResult{
|
||||||
|
Score: -1,
|
||||||
|
Name: "Fuzzing",
|
||||||
|
Version: 2,
|
||||||
|
Reason: "internal error: invalid probe results",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -96,7 +207,7 @@ func TestFuzzing(t *testing.T) {
|
|||||||
tt := tt
|
tt := tt
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
if got := Fuzzing(tt.args.name, tt.args.dl, tt.args.r); !cmp.Equal(got, tt.want, cmpopts.IgnoreFields(checker.CheckResult{}, "Error")) { //nolint:lll
|
if got := Fuzzing(tt.args.name, tt.args.findings); !cmp.Equal(got, tt.want, cmpopts.IgnoreFields(checker.CheckResult{}, "Error")) { //nolint:lll
|
||||||
t.Errorf("Fuzzing() = %v, want %v", got, cmp.Diff(got, tt.want, cmpopts.IgnoreFields(checker.CheckResult{}, "Error"))) //nolint:lll
|
t.Errorf("Fuzzing() = %v, want %v", got, cmp.Diff(got, tt.want, cmpopts.IgnoreFields(checker.CheckResult{}, "Error"))) //nolint:lll
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/ossf/scorecard/v4/checks/evaluation"
|
"github.com/ossf/scorecard/v4/checks/evaluation"
|
||||||
"github.com/ossf/scorecard/v4/checks/raw"
|
"github.com/ossf/scorecard/v4/checks/raw"
|
||||||
sce "github.com/ossf/scorecard/v4/errors"
|
sce "github.com/ossf/scorecard/v4/errors"
|
||||||
|
"github.com/ossf/scorecard/v4/probes"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckFuzzing is the registered name for Fuzzing.
|
// CheckFuzzing is the registered name for Fuzzing.
|
||||||
@ -41,9 +42,16 @@ func Fuzzing(c *checker.CheckRequest) checker.CheckResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the raw results.
|
// Set the raw results.
|
||||||
if c.RawResults != nil {
|
pRawResults := getRawResults(c)
|
||||||
c.RawResults.FuzzingResults = rawData
|
pRawResults.FuzzingResults = rawData
|
||||||
|
|
||||||
|
// Evaluate the probes.
|
||||||
|
findings, err := evaluateProbes(c, pRawResults, probes.Fuzzing)
|
||||||
|
if err != nil {
|
||||||
|
e := sce.WithMessage(sce.ErrScorecardInternal, err.Error())
|
||||||
|
return checker.CreateRuntimeErrorResult(CheckFuzzing, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
return evaluation.Fuzzing(CheckFuzzing, c.Dlogger, &rawData)
|
// Return the score evaluation.
|
||||||
|
return evaluation.Fuzzing(CheckFuzzing, findings)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ func TestFuzzing(t *testing.T) {
|
|||||||
//nolint
|
//nolint
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
want checker.CheckResult
|
|
||||||
langs []clients.Language
|
langs []clients.Language
|
||||||
response clients.SearchResponse
|
response clients.SearchResponse
|
||||||
wantErr bool
|
wantErr bool
|
||||||
@ -52,6 +51,13 @@ func TestFuzzing(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
|
expected: scut.TestReturn{
|
||||||
|
Error: nil,
|
||||||
|
NumberOfWarn: 7,
|
||||||
|
NumberOfDebug: 0,
|
||||||
|
NumberOfInfo: 0,
|
||||||
|
Score: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "hits 1",
|
name: "hits 1",
|
||||||
@ -69,11 +75,10 @@ func TestFuzzing(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
want: checker.CheckResult{Score: 10},
|
|
||||||
expected: scut.TestReturn{
|
expected: scut.TestReturn{
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 6,
|
||||||
NumberOfDebug: 0,
|
NumberOfDebug: 0,
|
||||||
NumberOfInfo: 0,
|
NumberOfInfo: 1,
|
||||||
Score: 10,
|
Score: 10,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -86,7 +91,6 @@ func TestFuzzing(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
want: checker.CheckResult{Score: -1},
|
|
||||||
expected: scut.TestReturn{
|
expected: scut.TestReturn{
|
||||||
Error: sce.ErrScorecardInternal,
|
Error: sce.ErrScorecardInternal,
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 0,
|
||||||
@ -104,12 +108,24 @@ func TestFuzzing(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantFuzzErr: false,
|
wantFuzzErr: false,
|
||||||
want: checker.CheckResult{Score: 0},
|
expected: scut.TestReturn{
|
||||||
|
Error: nil,
|
||||||
|
NumberOfWarn: 7,
|
||||||
|
NumberOfDebug: 0,
|
||||||
|
NumberOfInfo: 0,
|
||||||
|
Score: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "error",
|
name: "error",
|
||||||
wantFuzzErr: true,
|
wantFuzzErr: true,
|
||||||
want: checker.CheckResult{},
|
expected: scut.TestReturn{
|
||||||
|
Error: nil,
|
||||||
|
NumberOfWarn: 7,
|
||||||
|
NumberOfDebug: 0,
|
||||||
|
NumberOfInfo: 0,
|
||||||
|
Score: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -138,11 +154,14 @@ func TestFuzzing(t *testing.T) {
|
|||||||
return tt.fileContent, nil
|
return tt.fileContent, nil
|
||||||
}).AnyTimes()
|
}).AnyTimes()
|
||||||
dl := scut.TestDetailLogger{}
|
dl := scut.TestDetailLogger{}
|
||||||
|
raw := checker.RawResults{}
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
RepoClient: mockFuzz,
|
RepoClient: mockFuzz,
|
||||||
OssFuzzRepo: mockFuzz,
|
OssFuzzRepo: mockFuzz,
|
||||||
Dlogger: &dl,
|
Dlogger: &dl,
|
||||||
|
RawResults: &raw,
|
||||||
}
|
}
|
||||||
|
|
||||||
if tt.wantFuzzErr {
|
if tt.wantFuzzErr {
|
||||||
req.OssFuzzRepo = nil
|
req.OssFuzzRepo = nil
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
Ctx: context.Background(),
|
Ctx: context.Background(),
|
||||||
RepoClient: repoClient,
|
RepoClient: repoClient,
|
||||||
@ -50,8 +51,8 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
expected := scut.TestReturn{
|
expected := scut.TestReturn{
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Score: checker.MaxResultScore,
|
Score: checker.MaxResultScore,
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 6,
|
||||||
NumberOfInfo: 0,
|
NumberOfInfo: 1,
|
||||||
NumberOfDebug: 0,
|
NumberOfDebug: 0,
|
||||||
}
|
}
|
||||||
result := checks.Fuzzing(&req)
|
result := checks.Fuzzing(&req)
|
||||||
@ -68,6 +69,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
Ctx: context.Background(),
|
Ctx: context.Background(),
|
||||||
RepoClient: repoClient,
|
RepoClient: repoClient,
|
||||||
@ -78,8 +80,8 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
expected := scut.TestReturn{
|
expected := scut.TestReturn{
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Score: checker.MaxResultScore,
|
Score: checker.MaxResultScore,
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 6,
|
||||||
NumberOfInfo: 0,
|
NumberOfInfo: 1,
|
||||||
NumberOfDebug: 0,
|
NumberOfDebug: 0,
|
||||||
}
|
}
|
||||||
result := checks.Fuzzing(&req)
|
result := checks.Fuzzing(&req)
|
||||||
@ -96,6 +98,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
Ctx: context.Background(),
|
Ctx: context.Background(),
|
||||||
RepoClient: repoClient,
|
RepoClient: repoClient,
|
||||||
@ -106,7 +109,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
expected := scut.TestReturn{
|
expected := scut.TestReturn{
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Score: checker.MaxResultScore,
|
Score: checker.MaxResultScore,
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 6,
|
||||||
NumberOfInfo: 2,
|
NumberOfInfo: 2,
|
||||||
NumberOfDebug: 0,
|
NumberOfDebug: 0,
|
||||||
}
|
}
|
||||||
@ -124,6 +127,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
Ctx: context.Background(),
|
Ctx: context.Background(),
|
||||||
RepoClient: repoClient,
|
RepoClient: repoClient,
|
||||||
@ -144,6 +148,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
ossFuzzRepoClient, err := ossfuzz.CreateOSSFuzzClientEager(ossfuzz.StatusURL)
|
||||||
Expect(err).Should(BeNil())
|
Expect(err).Should(BeNil())
|
||||||
|
|
||||||
req := checker.CheckRequest{
|
req := checker.CheckRequest{
|
||||||
Ctx: context.Background(),
|
Ctx: context.Background(),
|
||||||
RepoClient: repoClient,
|
RepoClient: repoClient,
|
||||||
@ -154,7 +159,7 @@ var _ = Describe("E2E TEST:"+checks.CheckFuzzing, func() {
|
|||||||
expected := scut.TestReturn{
|
expected := scut.TestReturn{
|
||||||
Error: nil,
|
Error: nil,
|
||||||
Score: checker.MinResultScore,
|
Score: checker.MinResultScore,
|
||||||
NumberOfWarn: 0,
|
NumberOfWarn: 7,
|
||||||
NumberOfInfo: 0,
|
NumberOfInfo: 0,
|
||||||
NumberOfDebug: 0,
|
NumberOfDebug: 0,
|
||||||
}
|
}
|
||||||
|
@ -149,19 +149,19 @@ func NewWith(efs embed.FS, probeID, text string, loc *Location,
|
|||||||
return f, nil
|
return f, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWith create a negative finding with the desried location.
|
// NewWith create a negative finding with the desired location.
|
||||||
func NewNegative(efs embed.FS, probeID, text string, loc *Location,
|
func NewNegative(efs embed.FS, probeID, text string, loc *Location,
|
||||||
) (*Finding, error) {
|
) (*Finding, error) {
|
||||||
return NewWith(efs, probeID, text, loc, OutcomeNegative)
|
return NewWith(efs, probeID, text, loc, OutcomeNegative)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNotAvailable create a finding with a NotAvailable outcome and the desried location.
|
// NewNotAvailable create a finding with a NotAvailable outcome and the desired location.
|
||||||
func NewNotAvailable(efs embed.FS, probeID, text string, loc *Location,
|
func NewNotAvailable(efs embed.FS, probeID, text string, loc *Location,
|
||||||
) (*Finding, error) {
|
) (*Finding, error) {
|
||||||
return NewWith(efs, probeID, text, loc, OutcomeNotAvailable)
|
return NewWith(efs, probeID, text, loc, OutcomeNotAvailable)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPositive create a positive finding with the desried location.
|
// NewPositive create a positive finding with the desired location.
|
||||||
func NewPositive(efs embed.FS, probeID, text string, loc *Location,
|
func NewPositive(efs embed.FS, probeID, text string, loc *Location,
|
||||||
) (*Finding, error) {
|
) (*Finding, error) {
|
||||||
return NewWith(efs, probeID, text, loc, OutcomePositive)
|
return NewWith(efs, probeID, text, loc, OutcomePositive)
|
||||||
|
@ -17,6 +17,13 @@ package probes
|
|||||||
import (
|
import (
|
||||||
"github.com/ossf/scorecard/v4/checker"
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
"github.com/ossf/scorecard/v4/finding"
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithClusterFuzzLite"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithGoNative"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithOSSFuzz"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithOneFuzz"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedHaskell"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedJavascript"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/fuzzedWithPropertyBasedTypescript"
|
||||||
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsLinks"
|
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsLinks"
|
||||||
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsText"
|
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsText"
|
||||||
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsVulnerabilityDisclosure"
|
"github.com/ossf/scorecard/v4/probes/securityPolicyContainsVulnerabilityDisclosure"
|
||||||
@ -49,6 +56,15 @@ var (
|
|||||||
toolPyUpInstalled.Run,
|
toolPyUpInstalled.Run,
|
||||||
toolSonatypeLiftInstalled.Run,
|
toolSonatypeLiftInstalled.Run,
|
||||||
}
|
}
|
||||||
|
Fuzzing = []ProbeImpl{
|
||||||
|
fuzzedWithOSSFuzz.Run,
|
||||||
|
fuzzedWithOneFuzz.Run,
|
||||||
|
fuzzedWithGoNative.Run,
|
||||||
|
fuzzedWithClusterFuzzLite.Run,
|
||||||
|
fuzzedWithPropertyBasedHaskell.Run,
|
||||||
|
fuzzedWithPropertyBasedTypescript.Run,
|
||||||
|
fuzzedWithPropertyBasedJavascript.Run,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
//nolint:gochecknoinits
|
//nolint:gochecknoinits
|
||||||
@ -56,6 +72,7 @@ func init() {
|
|||||||
All = concatMultipleProbes([][]ProbeImpl{
|
All = concatMultipleProbes([][]ProbeImpl{
|
||||||
DependencyToolUpdates,
|
DependencyToolUpdates,
|
||||||
SecurityPolicy,
|
SecurityPolicy,
|
||||||
|
Fuzzing,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
probes/fuzzedWithClusterFuzzLite/def.yml
Normal file
32
probes/fuzzedWithClusterFuzzLite/def.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithClusterFuzzLite
|
||||||
|
short: Check that the project is fuzzed using ClusterFuzzLite
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementation looks for a file called ".clusterfuzzlite/Dockerfile".
|
||||||
|
outcome:
|
||||||
|
- If the file is found, one finding with OutcomePositive (1) is returned.
|
||||||
|
- If the file is not found, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- Follow the steps in https://github.com/google/clusterfuzzlite to integrate fuzzing as part of CI.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
||||||
|
markdown:
|
||||||
|
- Follow the steps in [https://github.com/google/clusterfuzzlite](https://github.com/google/clusterfuzzlite) to integrate fuzzing as part of CI.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
38
probes/fuzzedWithClusterFuzzLite/impl.go
Normal file
38
probes/fuzzedWithClusterFuzzLite/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithClusterFuzzLite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithClusterFuzzLite"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "ClusterFuzzLite")
|
||||||
|
}
|
144
probes/fuzzedWithClusterFuzzLite/impl_test.go
Normal file
144
probes/fuzzedWithClusterFuzzLite/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithClusterFuzzLite
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-ClusterFuzzLite",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
32
probes/fuzzedWithGoNative/def.yml
Normal file
32
probes/fuzzedWithGoNative/def.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithGoNative
|
||||||
|
short: Check that the project is fuzzed using Go native fuzzing framework
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementation checks whether fo the presence of functions with the signature 'func FuzzSomeName(*testing.F)' in .go files.
|
||||||
|
outcome:
|
||||||
|
- If fuzzing functions are found, each finding is returned with OutcomePositive (1).
|
||||||
|
- If no fuzzing is detected, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: Medium
|
||||||
|
text:
|
||||||
|
- Follow the steps in https://go.dev/doc/fuzz/ to enable fuzzing on your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
||||||
|
markdown:
|
||||||
|
- Follow the steps in [https://go.dev/doc/fuzz/](https://go.dev/doc/fuzz/) to enable fuzzing on your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
38
probes/fuzzedWithGoNative/impl.go
Normal file
38
probes/fuzzedWithGoNative/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithGoNative
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithGoNative"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "GoBuiltInFuzzer")
|
||||||
|
}
|
144
probes/fuzzedWithGoNative/impl_test.go
Normal file
144
probes/fuzzedWithGoNative/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithGoNative
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-GoBuiltInFuzzer",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
32
probes/fuzzedWithOSSFuzz/def.yml
Normal file
32
probes/fuzzedWithOSSFuzz/def.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithOSSFuzz
|
||||||
|
short: Check that the project is fuzzed using OSS-Fuzz
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementation lists the projects integrated with OSS-Fuzz in https://github.com/google/oss-fuzz/tree/master/projects, and checks whether the project is in the list.
|
||||||
|
outcome:
|
||||||
|
- If an integration with OSS-Fuzz is found, one finding with OutcomePositive (1) is returned.
|
||||||
|
- If no integration with OSS-Fuzz is found, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- Follow the steps in https://github.com/google/oss-fuzz to integrate fuzzing for your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
||||||
|
markdown:
|
||||||
|
- Follow the steps in [https://github.com/google/oss-fuzz](https://github.com/google/oss-fuzz) to integrate fuzzing for your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
38
probes/fuzzedWithOSSFuzz/impl.go
Normal file
38
probes/fuzzedWithOSSFuzz/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithOSSFuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithOSSFuzz"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "OSSFuzz")
|
||||||
|
}
|
144
probes/fuzzedWithOSSFuzz/impl_test.go
Normal file
144
probes/fuzzedWithOSSFuzz/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithOSSFuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OSSFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OSSFuzz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "OSSFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OSSFuzz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-OSSFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-OSSFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
32
probes/fuzzedWithOneFuzz/def.yml
Normal file
32
probes/fuzzedWithOneFuzz/def.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithOneFuzz
|
||||||
|
short: Check that the project is fuzzed using OneFuzz
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementation checks if the file '.onefuzz' is present in the source code files.
|
||||||
|
outcome:
|
||||||
|
- If the file is found, one finding is returned with OutcomePositive (1).
|
||||||
|
- If the file is not found, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- Follow the steps in https://github.com/microsoft/onefuzz to start fuzzing for your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
||||||
|
markdown:
|
||||||
|
- Follow the steps in [https://github.com/microsoft/onefuzz](https://github.com/microsoft/onefuzz) to start fuzzing for your project.
|
||||||
|
- Over time, try to add fuzzing for more functionalities of your project.
|
38
probes/fuzzedWithOneFuzz/impl.go
Normal file
38
probes/fuzzedWithOneFuzz/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithOneFuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
var Probe = "fuzzedWithOneFuzz"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "OneFuzz")
|
||||||
|
}
|
144
probes/fuzzedWithOneFuzz/impl_test.go
Normal file
144
probes/fuzzedWithOneFuzz/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithOneFuzz
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OneFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OneFuzz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "OneFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "OneFuzz",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-OneFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-OneFuzz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
42
probes/fuzzedWithPropertyBasedHaskell/def.yml
Normal file
42
probes/fuzzedWithPropertyBasedHaskell/def.yml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithPropertyBasedHaskell
|
||||||
|
short: Check that the project is fuzzed using a property-based testing framework.
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementation looks for direct imports of QuickCheck, Hedgehog, validity and SmallCheck or their indirect imports through the higher-level Hspec or Tasty testing frameworks.
|
||||||
|
outcome:
|
||||||
|
- If imports are found, each finding is returned with OutcomePositive (1).
|
||||||
|
- If no import is detected, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- 'Use one of the following frameworks to fuzz your project:'
|
||||||
|
- 'QuickCheck: https://hackage.haskell.org/package/QuickCheck'
|
||||||
|
- 'hedgehog: https://hedgehog.qa/'
|
||||||
|
- 'validity: https://github.com/NorfairKing/validity'
|
||||||
|
- 'smallcheck: https://hackage.haskell.org/package/smallcheck'
|
||||||
|
- 'hspec: https://hspec.github.io/'
|
||||||
|
- 'tasty: https://hackage.haskell.org/package/tasty'
|
||||||
|
markdown:
|
||||||
|
- 'Use one of the following frameworks to fuzz your project:'
|
||||||
|
- '[QuickCheck](https://hackage.haskell.org/package/QuickCheck)'
|
||||||
|
- '[hedgehog]( https://hedgehog.qa/)'
|
||||||
|
- '[validity](https://github.com/NorfairKing/validity)'
|
||||||
|
- '[smallcheck](https://hackage.haskell.org/package/smallcheck)'
|
||||||
|
- '[hspec](https://hspec.github.io/)'
|
||||||
|
- '[tasty](https://hackage.haskell.org/package/tasty)'
|
38
probes/fuzzedWithPropertyBasedHaskell/impl.go
Normal file
38
probes/fuzzedWithPropertyBasedHaskell/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedHaskell
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithPropertyBasedHaskell"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "HaskellPropertyBasedTesting")
|
||||||
|
}
|
144
probes/fuzzedWithPropertyBasedHaskell/impl_test.go
Normal file
144
probes/fuzzedWithPropertyBasedHaskell/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedHaskell
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-HaskellPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
30
probes/fuzzedWithPropertyBasedJavascript/def.yml
Normal file
30
probes/fuzzedWithPropertyBasedJavascript/def.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithPropertyBasedJavascript
|
||||||
|
short: Check that the javascript project is fuzzed using a property-based testing framework.
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementations looks for direct imports of fast-check https://github.com/dubzzz/fast-check in .js files.
|
||||||
|
outcome:
|
||||||
|
- If imports are found, each finding is returned with OutcomePositive (1).
|
||||||
|
- If no import is detected, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- 'Use fast-check: https://github.com/dubzzz/fast-check'
|
||||||
|
markdown:
|
||||||
|
- 'Use [fast-check](https://github.com/dubzzz/fast-check)'
|
38
probes/fuzzedWithPropertyBasedJavascript/impl.go
Normal file
38
probes/fuzzedWithPropertyBasedJavascript/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedJavascript
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithPropertyBasedJavascript"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "JavaScriptPropertyBasedTesting")
|
||||||
|
}
|
144
probes/fuzzedWithPropertyBasedJavascript/impl_test.go
Normal file
144
probes/fuzzedWithPropertyBasedJavascript/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedJavascript
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-JavaScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
30
probes/fuzzedWithPropertyBasedTypescript/def.yml
Normal file
30
probes/fuzzedWithPropertyBasedTypescript/def.yml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Copyright 2023 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.
|
||||||
|
|
||||||
|
id: fuzzedWithPropertyBasedTypescript
|
||||||
|
short: Check that the typescript project is fuzzed using a property-based testing framework.
|
||||||
|
motivation: >
|
||||||
|
Fuzzing, or fuzz testing, is the practice of feeding unexpected or random data into a program to expose bugs.
|
||||||
|
Regular fuzzing is important to detect vulnerabilities that may be exploited by others, especially since attackers can also use fuzzing to find the same flaws.
|
||||||
|
implementation: >
|
||||||
|
The implementations looks for direct imports of fast-check https://github.com/dubzzz/fast-check in .ts files.
|
||||||
|
outcome:
|
||||||
|
- If imports are found, each finding is returned with OutcomePositive (1).
|
||||||
|
- If no import is detected, one finding with OutcomeNegative (0) is returned.
|
||||||
|
remediation:
|
||||||
|
effort: High
|
||||||
|
text:
|
||||||
|
- 'Use fast-check: https://github.com/dubzzz/fast-check'
|
||||||
|
markdown:
|
||||||
|
- 'Use [fast-check](https://github.com/dubzzz/fast-check)'
|
38
probes/fuzzedWithPropertyBasedTypescript/impl.go
Normal file
38
probes/fuzzedWithPropertyBasedTypescript/impl.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedTypescript
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed *.yml
|
||||||
|
var fs embed.FS
|
||||||
|
|
||||||
|
const Probe = "fuzzedWithPropertyBasedTypescript"
|
||||||
|
|
||||||
|
func Run(raw *checker.RawResults) ([]finding.Finding, string, error) {
|
||||||
|
if raw == nil {
|
||||||
|
return nil, "", fmt.Errorf("%w: raw", utils.ErrNil)
|
||||||
|
}
|
||||||
|
//nolint:wrapcheck
|
||||||
|
return utils.FuzzerRun(raw, fs, Probe, "TypeScriptPropertyBasedTesting")
|
||||||
|
}
|
144
probes/fuzzedWithPropertyBasedTypescript/impl_test.go
Normal file
144
probes/fuzzedWithPropertyBasedTypescript/impl_test.go
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright 2023 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.
|
||||||
|
|
||||||
|
// nolint:stylecheck
|
||||||
|
package fuzzedWithPropertyBasedTypescript
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
"github.com/ossf/scorecard/v4/probes/internal/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_Run(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
// nolint:govet
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
raw *checker.RawResults
|
||||||
|
outcomes []finding.Outcome
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "fuzzer present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present twice",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer present and other present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "not-TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomePositive,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fuzzer not present",
|
||||||
|
raw: &checker.RawResults{
|
||||||
|
FuzzingResults: checker.FuzzingData{
|
||||||
|
Fuzzers: []checker.Tool{
|
||||||
|
{
|
||||||
|
Name: "not-TypeScriptPropertyBasedTesting",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no fuzzer",
|
||||||
|
raw: &checker.RawResults{},
|
||||||
|
outcomes: []finding.Outcome{
|
||||||
|
finding.OutcomeNegative,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil raw",
|
||||||
|
err: utils.ErrNil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt // Re-initializing variable so it is not changed while executing the closure below
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
findings, s, err := Run(tt.raw)
|
||||||
|
if !cmp.Equal(tt.err, err, cmpopts.EquateErrors()) {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", cmp.Diff(tt.err, err, cmpopts.EquateErrors()))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(Probe, s); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(len(tt.outcomes), len(findings)); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
for i := range tt.outcomes {
|
||||||
|
outcome := &tt.outcomes[i]
|
||||||
|
f := &findings[i]
|
||||||
|
if diff := cmp.Diff(*outcome, f.Outcome); diff != "" {
|
||||||
|
t.Errorf("mismatch (-want +got):\n%s", diff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
71
probes/internal/utils/fuzzing.go
Normal file
71
probes/internal/utils/fuzzing.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// Copyright 2023 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 utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ossf/scorecard/v4/checker"
|
||||||
|
"github.com/ossf/scorecard/v4/finding"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FuzzerRun(raw *checker.RawResults, fs embed.FS, probeID, fuzzerName string) ([]finding.Finding, string, error) {
|
||||||
|
var findings []finding.Finding
|
||||||
|
fuzzers := raw.FuzzingResults.Fuzzers
|
||||||
|
|
||||||
|
for i := range fuzzers {
|
||||||
|
fuzzer := &fuzzers[i]
|
||||||
|
if fuzzer.Name != fuzzerName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// The current implementation does not provide file location
|
||||||
|
// for all fuzzers. Check this first.
|
||||||
|
if len(fuzzer.Files) == 0 {
|
||||||
|
f, err := finding.NewWith(fs, probeID,
|
||||||
|
fmt.Sprintf("%s integration found", fuzzerName), nil,
|
||||||
|
finding.OutcomePositive)
|
||||||
|
if err != nil {
|
||||||
|
return nil, probeID, fmt.Errorf("create finding: %w", err)
|
||||||
|
}
|
||||||
|
findings = append(findings, *f)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Files are present. Create one results for each file location.
|
||||||
|
for j := range fuzzer.Files {
|
||||||
|
file := fuzzer.Files[j]
|
||||||
|
f, err := finding.NewWith(fs, probeID,
|
||||||
|
fmt.Sprintf("%s integration found", fuzzerName), file.Location(),
|
||||||
|
finding.OutcomePositive)
|
||||||
|
if err != nil {
|
||||||
|
return nil, probeID, fmt.Errorf("create finding: %w", err)
|
||||||
|
}
|
||||||
|
findings = append(findings, *f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(findings) == 0 {
|
||||||
|
f, err := finding.NewNegative(fs, probeID,
|
||||||
|
fmt.Sprintf("no %s integration found", fuzzerName), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, probeID, fmt.Errorf("create finding: %w", err)
|
||||||
|
}
|
||||||
|
findings = append(findings, *f)
|
||||||
|
}
|
||||||
|
|
||||||
|
return findings, probeID, nil
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user