scorecard/checker/raw_result.go
Raghav Kaul 77dce6fbef
⚠️ Add ProjectPackageVersions to raw data collection (#4104)
* add projectpackageversions to signed releases raw results

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* add mocks

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* update

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* fix tests

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* rename

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* Update runScorecard

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* pass depsdevclient to scdiff

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* error handling

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* make Host() return domain only

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* lint

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

* address cr comments

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>

---------

Signed-off-by: Raghav Kaul <raghavkaul+github@google.com>
2024-05-30 16:00:36 -04:00

494 lines
14 KiB
Go

// Copyright 2020 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 checker
import (
"fmt"
"time"
"github.com/ossf/scorecard/v5/clients"
"github.com/ossf/scorecard/v5/finding"
)
// RawResults contains results before a policy
// is applied.
//
//nolint:govet
type RawResults struct {
BinaryArtifactResults BinaryArtifactData
BranchProtectionResults BranchProtectionsData
CIIBestPracticesResults CIIBestPracticesData
CITestResults CITestData
CodeReviewResults CodeReviewData
ContributorsResults ContributorsData
DangerousWorkflowResults DangerousWorkflowData
DependencyUpdateToolResults DependencyUpdateToolData
FuzzingResults FuzzingData
LicenseResults LicenseData
SBOMResults SBOMData
MaintainedResults MaintainedData
Metadata MetadataData
PackagingResults PackagingData
PinningDependenciesResults PinningDependenciesData
SASTResults SASTData
SecurityPolicyResults SecurityPolicyData
SignedReleasesResults SignedReleasesData
TokenPermissionsResults TokenPermissionsData
VulnerabilitiesResults VulnerabilitiesData
WebhookResults WebhooksData
}
type MetadataData struct {
Metadata map[string]string
}
type RevisionCIInfo struct {
HeadSHA string
CheckRuns []clients.CheckRun
Statuses []clients.Status
PullRequestNumber int
}
type CITestData struct {
CIInfo []RevisionCIInfo
}
// FuzzingData represents different fuzzing done.
type FuzzingData struct {
Fuzzers []Tool
}
// TODO: Add Msg to all results.
// PackagingData contains results for the Packaging check.
type PackagingData struct {
Packages []Package
}
// Package represents a package.
type Package struct {
// TODO: not supported yet. This needs to be unique across
// ecosystems: purl, OSV, CPE, etc.
Name *string
Job *WorkflowJob
File *File
// Note: Msg is populated only for debug messages.
Msg *string
Runs []Run
}
type PackageProvenance struct {
Commit string
IsVerified bool
}
type ProjectPackage struct {
System string
Name string
Version string
Provenance PackageProvenance
}
// DependencyUseType represents a type of dependency use.
type DependencyUseType string
const (
// DependencyUseTypeGHAction is an action.
DependencyUseTypeGHAction DependencyUseType = "GitHubAction"
// DependencyUseTypeDockerfileContainerImage a container image used via FROM.
DependencyUseTypeDockerfileContainerImage DependencyUseType = "containerImage"
// DependencyUseTypeDownloadThenRun is a download followed by a run.
DependencyUseTypeDownloadThenRun DependencyUseType = "downloadThenRun"
// DependencyUseTypeGoCommand is a go command.
DependencyUseTypeGoCommand DependencyUseType = "goCommand"
// DependencyUseTypeChocoCommand is a choco command.
DependencyUseTypeChocoCommand DependencyUseType = "chocoCommand"
// DependencyUseTypeNpmCommand is an npm command.
DependencyUseTypeNpmCommand DependencyUseType = "npmCommand"
// DependencyUseTypePipCommand is a pip command.
DependencyUseTypePipCommand DependencyUseType = "pipCommand"
// DependencyUseTypeNugetCommand is a nuget command.
DependencyUseTypeNugetCommand DependencyUseType = "nugetCommand"
)
// PinningDependenciesData represents pinned dependency data.
type PinningDependenciesData struct {
Dependencies []Dependency
ProcessingErrors []ElementError // jobs or files with errors may have incomplete results
}
// Dependency represents a dependency.
type Dependency struct {
// TODO: unique dependency name.
// TODO: Job *WorkflowJob
Name *string
PinnedAt *string
Location *File
Msg *string // Only for debug messages.
Pinned *bool
Remediation *finding.Remediation
Type DependencyUseType
}
// MaintainedData contains the raw results
// for the Maintained check.
type MaintainedData struct {
CreatedAt time.Time
Issues []clients.Issue
DefaultBranchCommits []clients.Commit
ArchivedStatus ArchivedStatus
}
type LicenseAttributionType string
const (
// sources of license information used to assert repo's license.
LicenseAttributionTypeOther LicenseAttributionType = "other"
LicenseAttributionTypeAPI LicenseAttributionType = "repositoryAPI"
LicenseAttributionTypeHeuristics LicenseAttributionType = "builtinHeuristics"
)
// license details.
type License struct {
Name string // OSI standardized license name
SpdxID string // SPDX standardized identifier
Attribution LicenseAttributionType // source of licensing information
Approved bool // FSF or OSI Approved License
}
// one file contains one license.
type LicenseFile struct {
LicenseInformation License
File File
}
// LicenseData contains the raw results
// for the License check.
// Some repos may have more than one license.
type LicenseData struct {
LicenseFiles []LicenseFile
}
// SBOM details.
type SBOM struct {
Name string // SBOM Filename
File File // SBOM File Object
}
// SBOMData contains the raw results for the SBOM check.
// Some repos may have more than one SBOM.
type SBOMData struct {
SBOMFiles []SBOM
}
// CodeReviewData contains the raw results
// for the Code-Review check.
type CodeReviewData struct {
DefaultBranchChangesets []Changeset
}
type ReviewPlatform = string
const (
ReviewPlatformGitHub ReviewPlatform = "GitHub"
ReviewPlatformProw ReviewPlatform = "Prow"
ReviewPlatformGerrit ReviewPlatform = "Gerrit"
ReviewPlatformPhabricator ReviewPlatform = "Phabricator"
ReviewPlatformPiper ReviewPlatform = "Piper"
ReviewPlatformUnknown ReviewPlatform = "Unknown"
)
type Changeset struct {
ReviewPlatform string
RevisionID string
Commits []clients.Commit
Reviews []clients.Review
Author clients.User
}
// ContributorsData represents contributor information.
type ContributorsData struct {
Users []clients.User
}
// VulnerabilitiesData contains the raw results
// for the Vulnerabilities check.
type VulnerabilitiesData struct {
Vulnerabilities []clients.Vulnerability
}
type SecurityPolicyInformationType string
const (
// forms of security policy hints being evaluated.
SecurityPolicyInformationTypeEmail SecurityPolicyInformationType = "emailAddress"
SecurityPolicyInformationTypeLink SecurityPolicyInformationType = "httpLink"
SecurityPolicyInformationTypeText SecurityPolicyInformationType = "vulnDisclosureText"
)
type SecurityPolicyValueType struct {
Match string // Snippet of match
LineNumber uint // Line number in policy file of match
Offset uint // Offset in the line of the match
}
type SecurityPolicyInformation struct {
InformationType SecurityPolicyInformationType
InformationValue SecurityPolicyValueType
}
type SecurityPolicyFile struct {
// security policy information found in repo or org
Information []SecurityPolicyInformation
// file that contains the security policy information
File File
}
// SASTData contains the raw results
// for the SAST check.
type SASTData struct {
Workflows []SASTWorkflow
Commits []SASTCommit
NumWorkflows int
}
type SASTCommit struct {
CommittedDate time.Time
Message string
SHA string
CheckRuns []clients.CheckRun
AssociatedMergeRequest clients.PullRequest
Committer clients.User
Compliant bool
}
// SASTWorkflowType represents a type of SAST workflow.
type SASTWorkflowType string
const (
// CodeQLWorkflow represents a workflow that runs CodeQL.
CodeQLWorkflow SASTWorkflowType = "CodeQL"
// SonarWorkflow represents a workflow that runs Sonar.
SonarWorkflow SASTWorkflowType = "Sonar"
// SnykWorkflow represents a workflow that runs Snyk.
SnykWorkflow SASTWorkflowType = "Snyk"
// PysaWorkflow represents a workflow that runs Pysa.
PysaWorkflow SASTWorkflowType = "Pysa"
// QodanaWorkflow represents a workflow that runs Qodana.
QodanaWorkflow SASTWorkflowType = "Qodana"
)
// SASTWorkflow represents a SAST workflow.
type SASTWorkflow struct {
Type SASTWorkflowType
File File
}
// SecurityPolicyData contains the raw results
// for the Security-Policy check.
type SecurityPolicyData struct {
PolicyFiles []SecurityPolicyFile
}
// BinaryArtifactData contains the raw results
// for the Binary-Artifact check.
type BinaryArtifactData struct {
// Files contains a list of files.
Files []File
}
// SignedReleasesData contains the raw results
// for the Signed-Releases check.
type SignedReleasesData struct {
Releases []clients.Release
Packages []ProjectPackage
}
// DependencyUpdateToolData contains the raw results
// for the Dependency-Update-Tool check.
type DependencyUpdateToolData struct {
// Tools contains a list of tools.
Tools []Tool
}
// WebhooksData contains the raw results
// for the Webhook check.
type WebhooksData struct {
Webhooks []clients.Webhook
}
// BranchProtectionsData contains the raw results
// for the Branch-Protection check.
type BranchProtectionsData struct {
Branches []clients.BranchRef
CodeownersFiles []string
}
// Tool represents a tool.
type Tool struct {
URL *string
Desc *string
Files []File
Name string
// Runs of the tool.
Runs []Run
// Issues created by the tool.
Issues []clients.Issue
// Merge requests created by the tool.
MergeRequests []clients.PullRequest
// TODO: CodeCoverage, jsonWorkflowJob.
}
// Run represents a run.
type Run struct {
URL string
}
// ArchivedStatus defines the archived status.
type ArchivedStatus struct {
Status bool
// TODO: add fields, e.g., date of archival.
}
// File represents a file.
type File struct {
Path string
Snippet string // Snippet of code
Offset uint // Offset in the file of Path (line for source/text files).
EndOffset uint // End of offset in the file, e.g. if the command spans multiple lines.
FileSize uint // Total size of file.
Type finding.FileType // Type of file.
// TODO: add hash.
}
// CIIBestPracticesData contains data for CIIBestPractices check.
type CIIBestPracticesData struct {
Badge clients.BadgeLevel
}
// DangerousWorkflowType represents a type of dangerous workflow.
type DangerousWorkflowType string
const (
// DangerousWorkflowScriptInjection represents a script injection.
DangerousWorkflowScriptInjection DangerousWorkflowType = "scriptInjection"
// DangerousWorkflowUntrustedCheckout represents an untrusted checkout.
DangerousWorkflowUntrustedCheckout DangerousWorkflowType = "untrustedCheckout"
)
// DangerousWorkflowData contains raw results
// for dangerous workflow check.
type DangerousWorkflowData struct {
Workflows []DangerousWorkflow
NumWorkflows int
}
// DangerousWorkflow represents a dangerous workflow.
type DangerousWorkflow struct {
Job *WorkflowJob
Type DangerousWorkflowType
File File
}
// WorkflowJob represents a workflow job.
type WorkflowJob struct {
Name *string
ID *string
}
// TokenPermissionsData represents data about a permission failure.
type TokenPermissionsData struct {
TokenPermissions []TokenPermission
NumTokens int
}
// PermissionLocation represents a declaration type.
type PermissionLocation string
const (
// PermissionLocationTop is top-level workflow permission.
PermissionLocationTop PermissionLocation = "topLevel"
// PermissionLocationJob is job-level workflow permission.
PermissionLocationJob PermissionLocation = "jobLevel"
)
// PermissionLevel represents a permission type.
type PermissionLevel string
const (
// PermissionLevelUndeclared is an undeclared permission.
PermissionLevelUndeclared PermissionLevel = "undeclared"
// PermissionLevelWrite is a permission set to `write` for a permission we consider potentially dangerous.
PermissionLevelWrite PermissionLevel = "write"
// PermissionLevelRead is a permission set to `read`.
PermissionLevelRead PermissionLevel = "read"
// PermissionLevelNone is a permission set to `none`.
PermissionLevelNone PermissionLevel = "none"
// PermissionLevelUnknown is for other kinds of alerts, mostly to support debug messages.
// TODO: remove it once we have implemented severity (#1874).
PermissionLevelUnknown PermissionLevel = "unknown"
)
// TokenPermission defines a token permission result.
type TokenPermission struct {
Job *WorkflowJob
LocationType *PermissionLocation
Name *string
Value *string
File *File
Msg *string
Type PermissionLevel
}
// Location generates location from a file.
func (f *File) Location() *finding.Location {
// TODO(2626): merge location and path.
if f == nil {
return nil
}
loc := &finding.Location{
Type: f.Type,
Path: f.Path,
LineStart: &f.Offset,
}
if f.EndOffset != 0 {
loc.LineEnd = &f.EndOffset
}
if f.Snippet != "" {
loc.Snippet = &f.Snippet
}
return loc
}
// ElementError allows us to identify the "element" that led to the given error.
// The "element" is the specific "code under analysis" that caused the error. It should
// describe what caused the error as precisely as possible.
//
// For example, if a shell parsing error occurs while parsing a Dockerfile `RUN` block
// or a GitHub workflow's `run:` step, the "element" should point to the Dockerfile
// lines or workflow job step that caused the failure, not just the file path.
type ElementError struct {
Err error
Location finding.Location
}
func (e *ElementError) Error() string {
return fmt.Sprintf("%s: %v", e.Err, e.Location)
}
func (e *ElementError) Unwrap() error {
return e.Err
}