Skip to content

Commit

Permalink
🌱 Convert pinned dependencies to probe
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Korczynski <[email protected]>
  • Loading branch information
AdamKorcz committed Jan 30, 2024
1 parent 3b94825 commit b42e010
Show file tree
Hide file tree
Showing 7 changed files with 977 additions and 784 deletions.
183 changes: 22 additions & 161 deletions checks/evaluation/pinned_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ 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/probes/pinsDependencies"
"github.com/ossf/scorecard/v4/rule"
)

Expand Down Expand Up @@ -54,36 +55,15 @@ const (
depTypeKey = "dependencyType"
)

var (
dependencyTypes = map[checker.DependencyUseType]int{
checker.DependencyUseTypeGHAction: 0,
checker.DependencyUseTypeDockerfileContainerImage: 1,
checker.DependencyUseTypeDownloadThenRun: 2,
checker.DependencyUseTypeGoCommand: 3,
checker.DependencyUseTypeChocoCommand: 4,
checker.DependencyUseTypeNpmCommand: 5,
checker.DependencyUseTypePipCommand: 6,
checker.DependencyUseTypeNugetCommand: 7,
}
intToDepType = map[int]checker.DependencyUseType{
0: checker.DependencyUseTypeGHAction,
1: checker.DependencyUseTypeDockerfileContainerImage,
2: checker.DependencyUseTypeDownloadThenRun,
3: checker.DependencyUseTypeGoCommand,
4: checker.DependencyUseTypeChocoCommand,
5: checker.DependencyUseTypeNpmCommand,
6: checker.DependencyUseTypePipCommand,
7: checker.DependencyUseTypeNugetCommand,
}
)

func ruleRemToProbeRem(rem *rule.Remediation) *probe.Remediation {
return &probe.Remediation{
Patch: rem.Patch,
Text: rem.Text,
Markdown: rem.Markdown,
Effort: probe.RemediationEffort(rem.Effort),
}
var intToDepType = map[int]checker.DependencyUseType{
0: checker.DependencyUseTypeGHAction,
1: checker.DependencyUseTypeDockerfileContainerImage,
2: checker.DependencyUseTypeDownloadThenRun,
3: checker.DependencyUseTypeGoCommand,
4: checker.DependencyUseTypeChocoCommand,
5: checker.DependencyUseTypeNpmCommand,
6: checker.DependencyUseTypePipCommand,
7: checker.DependencyUseTypeNugetCommand,
}

func probeRemToRuleRem(rem *probe.Remediation) *rule.Remediation {
Expand All @@ -95,132 +75,28 @@ func probeRemToRuleRem(rem *probe.Remediation) *rule.Remediation {
}
}

func dependenciesToFindings(r *checker.PinningDependenciesData) ([]finding.Finding, error) {
findings := make([]finding.Finding, 0)

for i := range r.ProcessingErrors {
e := r.ProcessingErrors[i]
f := finding.Finding{
Message: generateTextIncompleteResults(e),
Location: &e.Location,
Outcome: finding.OutcomeNotAvailable,
}
findings = append(findings, f)
}

for i := range r.Dependencies {
rr := r.Dependencies[i]
if rr.Location == nil {
if rr.Msg == nil {
e := sce.WithMessage(sce.ErrScorecardInternal, "empty File field")
return findings, e
}
f := &finding.Finding{
Probe: "",
Outcome: finding.OutcomeNotApplicable,
Message: *rr.Msg,
}
findings = append(findings, *f)
continue
}
if rr.Msg != nil {
loc := &finding.Location{
Type: rr.Location.Type,
Path: rr.Location.Path,
LineStart: &rr.Location.Offset,
LineEnd: &rr.Location.EndOffset,
Snippet: &rr.Location.Snippet,
}
f := &finding.Finding{
Probe: "",
Outcome: finding.OutcomeNotApplicable,
Message: *rr.Msg,
Location: loc,
}
findings = append(findings, *f)
continue
}
if rr.Pinned == nil {
loc := &finding.Location{
Type: rr.Location.Type,
Path: rr.Location.Path,
LineStart: &rr.Location.Offset,
LineEnd: &rr.Location.EndOffset,
Snippet: &rr.Location.Snippet,
}
f := &finding.Finding{
Probe: "",
Outcome: finding.OutcomeNotApplicable,
Message: fmt.Sprintf("%s has empty Pinned field", rr.Type),
Location: loc,
}
findings = append(findings, *f)
continue
}
if !*rr.Pinned {
loc := &finding.Location{
Type: rr.Location.Type,
Path: rr.Location.Path,
LineStart: &rr.Location.Offset,
LineEnd: &rr.Location.EndOffset,
Snippet: &rr.Location.Snippet,
}
f := &finding.Finding{
Probe: "",
Outcome: finding.OutcomeNegative,
Message: generateTextUnpinned(&rr),
Location: loc,
}
if rr.Remediation != nil {
f.Remediation = ruleRemToProbeRem(rr.Remediation)
}
f = f.WithValues(map[string]int{
depTypeKey: dependencyTypes[rr.Type],
})
findings = append(findings, *f)
} else {
loc := &finding.Location{
Type: rr.Location.Type,
Path: rr.Location.Path,
LineStart: &rr.Location.Offset,
LineEnd: &rr.Location.EndOffset,
Snippet: &rr.Location.Snippet,
}
f := &finding.Finding{
Probe: "",
Outcome: finding.OutcomePositive,
Location: loc,
}
f = f.WithValues(map[string]int{
depTypeKey: dependencyTypes[rr.Type],
})
findings = append(findings, *f)
}
}
return findings, nil
}

// PinningDependencies applies the score policy for the Pinned-Dependencies check.
func PinningDependencies(name string, c *checker.CheckRequest,
r *checker.PinningDependenciesData,
func PinningDependencies(name string,
findings []finding.Finding,
dl checker.DetailLogger,
) checker.CheckResult {
if r == nil {
e := sce.WithMessage(sce.ErrScorecardInternal, "empty raw data")
expectedProbes := []string{
pinsDependencies.Probe,
}

if !finding.UniqueProbesEqual(findings, expectedProbes) {
e := sce.WithMessage(sce.ErrScorecardInternal, "invalid probe results")

Check warning on line 88 in checks/evaluation/pinned_dependencies.go

View check run for this annotation

Codecov / codecov/patch

checks/evaluation/pinned_dependencies.go#L88

Added line #L88 was not covered by tests
return checker.CreateRuntimeErrorResult(name, e)
}

var wp workflowPinningResult
pr := make(map[checker.DependencyUseType]pinnedResult)
dl := c.Dlogger

findings, err := dependenciesToFindings(r)
if err != nil {
return checker.CreateRuntimeErrorResult(name, err)
}

for i := range findings {
f := findings[i]
switch f.Outcome {
case finding.OutcomeNotAvailable:
return checker.CreateInconclusiveResult(name, "no dependencies found")

Check warning on line 99 in checks/evaluation/pinned_dependencies.go

View check run for this annotation

Codecov / codecov/patch

checks/evaluation/pinned_dependencies.go#L98-L99

Added lines #L98 - L99 were not covered by tests
case finding.OutcomeNotApplicable:
if f.Location != nil {
dl.Debug(&checker.LogMessage{
Expand Down Expand Up @@ -251,7 +127,7 @@ func PinningDependencies(name string, c *checker.CheckRequest,
lm.Remediation = probeRemToRuleRem(f.Remediation)
}
dl.Warn(lm)
case finding.OutcomeNotAvailable:
case finding.OutcomeError:

Check warning on line 130 in checks/evaluation/pinned_dependencies.go

View check run for this annotation

Codecov / codecov/patch

checks/evaluation/pinned_dependencies.go#L130

Added line #L130 was not covered by tests
dl.Info(&checker.LogMessage{
Finding: &f,
})
Expand Down Expand Up @@ -316,21 +192,6 @@ func updatePinningResults(dependencyType checker.DependencyUseType,
pr[dependencyType] = p
}

func generateTextUnpinned(rr *checker.Dependency) string {
if rr.Type == checker.DependencyUseTypeGHAction {
// Check if we are dealing with a GitHub action or a third-party one.
gitHubOwned := fileparser.IsGitHubOwnedAction(rr.Location.Snippet)
owner := generateOwnerToDisplay(gitHubOwned)
return fmt.Sprintf("%s not pinned by hash", owner)
}

return fmt.Sprintf("%s not pinned by hash", rr.Type)
}

func generateTextIncompleteResults(e checker.ElementError) string {
return fmt.Sprintf("Possibly incomplete results: %s", e.Err)
}

func generateOwnerToDisplay(gitHubOwned bool) string {
if gitHubOwned {
return fmt.Sprintf("GitHub-owned %s", checker.DependencyUseTypeGHAction)
Expand Down
Loading

0 comments on commit b42e010

Please sign in to comment.