scan

package
v0.38.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 3, 2025 License: Apache-2.0 Imports: 43 Imported by: 1

README

Vulnerability scanning

Wolfictl can scan APKs for known vulnerabilities. To do this, it relies on Grype to do 99% of the work. Wolfictl's own code is responsible for managing the handling of SBOM data provided to the scan, as well as vulnerability matching configuration settings, tuned to help account for vulnerabilities discovered downstream in image scans.

Testing

There are integration tests in wolfictl to guard against unexpected behaviors this Grype-based vulnerability scanning process. This section describes how to work with these tests.

How the tests work

The tests retrieve a selected set of Wolfi APK files to scan for vulnerabilities. APKs are saved to "git-ignored" locations in the repository so that they can be reused in subsequent test executions without needing to fetch them again.

Each test uses a "golden file" as the ground truth, and then compare the output of wolfictl's (*Scanner).ScanAPKs method to that golden file. If there is no diff, the test passes! If there is a diff, the test is failed, and the diff is reported to the user. JSON representations of the scan results are used to make diffing easier to reason about.

The Grype DB

Unlike SBOM generation, vulnerability scanning actually takes two inputs: the target artifact to scan, and a dataset of vulnerabilities, to which the target artifact's components will be matched. Wolfictl's vulnerability scanning uses the Grype DB as its vulnerability dataset. The Grype project updates this database every day, but we want our tests to return consistent results on every run, so we've pinned to a specific build of the Grype database. Similar to the APKs used in these tests, the Grype DB used by the tests is fetched only once and stored in the repo tree, as "git-ignored" data.

Running integration tests

Since these tests are long-running, they are not run by default by go test. Instead, you can include them in the executed test suite by using the build tag flag -tags=integration.

What to do when a test fails

When a test fails, a diff is rendered to explain how the ScanAPK method's output differed from what was expected (as codified in that test's golden file).

If a test is failing, it's failing for a notable reason. The ScanAPK method's output should never change (given unchanging APK content and an unchanging vulnerability database) under normal circumstances. So when the test fails, it means that something material changed in Grype, Syft, or in wolfictl's wrapping of these libraries. It's important to determine the root cause of the diff.

The diff either indicates a bug, or it shows an intended change (e.g. by the Syft/Grype maintainers) that wolfictl maintainers should have a heads-up about, since it may have a nontrivial impact on wolfictl's supported use cases.

If the new output coming from ScanAPK seems acceptable, then it's time to update the golden files to reflect the new ground truth.

Updating the golden files

Important! Only update the golden files after you've thoroughly examined the changes to wolfictl's vulnerability scanning behavior and determined they are acceptable.

When running these vulnerability scanning tests, you can pass the test flag -update-golden-files. Doing so will cause the tests not to check for diffs, instead saving the current output of the ScanAPK method to the golden files. It's important to check these changes into the git repository, so that everyone else starts using this data as the ground truth for their test executions.

Updating the list of APKs used for testing

The set of APK packages used during testing should be diverse, in order to give us a fair chance at identifying inbound impactful changes from Grype or Syft. One dimension that warrants diversity in particular is "language ecosystem".

The set of packages used in testing has been intentionally chosen to provide this diversity without being excessively large (costing more test execution time and storage).

But as time goes on, it's natural for the set to need to grow or change. Changing this list should be as simple as:

  1. Modifying the testTargets string slice as desired.
  2. Running the tests with -update-golden-files in order to generate golden files for any new APKs.
  3. Committing in the repo the changes to both of the above.

Documentation

Index

Constants

View Source
const (
	AdvisoriesSetResolved  = "resolved"
	AdvisoriesSetAll       = "all"
	AdvisoriesSetConcluded = "concluded"
)

Variables

View Source
var DefaultGrypeDBDir = path.Join(xdg.CacheHome, "wolfictl", "grype", "db")
View Source
var DefaultOptions = Options{

	MaxAllowedBuildAge: 120 * time.Hour,
}

DefaultOptions is the recommended default configuration for a new Scanner. These options are suitable for most use scanning cases.

Functions

func NewGrypeVulnerabilityMatcher added in v0.15.1

func NewGrypeVulnerabilityMatcher(vulnProvider vulnerability.Provider, useCPEs bool) *grype.VulnerabilityMatcher

Types

type DataSource added in v0.32.0

type DataSource struct {
	// Kind states the type of data source used during the scan (e.g. "grype-db").
	// This field can be used to better interpret the specific values populating the
	// other fields of this struct.
	Kind string

	// Schema describes the schema version of the underlying vulnerability data
	// source.
	Schema string

	// Integrity should provide some kind of machine-readable way for consumers of
	// scan data to validate the data integrity of the underlying data source. This
	// could be a checksum, signature, etc.
	Integrity string

	// Date indicates how fresh the dats source's data is.
	Date time.Time
}

DataSource describes the underlying data used during the vulnerability scan, in such a way that is intentionally abstracted from any specific scanner implementation, to avoid scanner-specific types and dependencies leaking into our scan results processing pipeline.

type Finding

type Finding struct {
	Package       Package
	Vulnerability Vulnerability
	CGAID         string `json:",omitempty"`

	// Deprecated: This field will be removed soon. Plan to use CGAID to lookup the
	// associated advisory out-of-band, instead of using this pointer.
	Advisory *v2.Advisory `json:",omitempty"`

	// Deprecated: This field will be removed soon.
	TriageAssessments []TriageAssessment `json:",omitempty"`
}

Finding represents a vulnerability finding for a single package.

func FilterWithAdvisories added in v0.1.0

func FilterWithAdvisories(ctx context.Context, result Result, advGetter advisory.Getter, advisoryFilterSet string) ([]Finding, error)

FilterWithAdvisories filters the findings in the result based on the advisories for the target APK.

type Findings added in v0.26.0

type Findings []Finding

func (Findings) Len added in v0.26.0

func (f Findings) Len() int

func (Findings) Less added in v0.26.0

func (f Findings) Less(i, j int) bool

func (Findings) Swap added in v0.26.0

func (f Findings) Swap(i, j int)

type Options added in v0.18.0

type Options struct {
	// PathOfDatabaseArchiveToImport, if set, is the path to a Grype vulnerability
	// database archive (.tar.gz file) from which a database will be loaded by
	// Grype.
	//
	// If empty, the default Grype database loading behavior will be used (e.g.
	// downloading the database from the Internet).
	PathOfDatabaseArchiveToImport string

	// PathOfDatabaseDestinationDirectory is the directory to which the Grype
	// database will be extracted, and where the database will be loaded from at
	// runtime. If empty, the value of DefaultGrypeDBDir will be used.
	PathOfDatabaseDestinationDirectory string

	// UseCPEs controls whether the scanner will use CPEs to match vulnerabilities
	// for matcher types that default to not using CPE matching. Most consumers will
	// probably want this set to false in order to avoid excessive noise from
	// matching.
	UseCPEs bool

	// DisableDatabaseAgeValidation controls whether the scanner will validate the
	// age of the vulnerability database before using it. If true, the scanner will
	// not validate the age of the database. This bool should always be set to false
	// except for testing purposes.
	DisableDatabaseAgeValidation bool

	// MaxAllowedBuildAge defines the maximum allowed age for the vulnerability database.
	// If the database is older than this duration, it will be considered invalid unless
	// DisableDatabaseAgeValidation is set to true. If not specified, the default value
	// of 48 hours will be used.
	MaxAllowedBuildAge time.Duration

	// DisableSBOMCache controls whether the scanner will cache SBOMs generated from
	// APKs. If true, the scanner will not cache SBOMs or use existing cached SBOMs.
	DisableSBOMCache bool
}

Options determine the configuration for a new Scanner. The zero-value of this struct is a valid configuration.

type Package

type Package struct {
	ID       string
	Name     string
	Version  string
	Type     string
	Location string
	PURL     string
}

type Result added in v0.1.0

type Result struct {
	TargetAPK  TargetAPK
	Findings   []Finding
	DataSource DataSource
}

type Scanner added in v0.11.0

type Scanner struct {
	// contains filtered or unexported fields
}

func NewScanner added in v0.11.0

func NewScanner(opts Options) (*Scanner, error)

NewScanner initializes the grype DB for reuse across multiple scans.

func (*Scanner) APKSBOM added in v0.11.0

func (s *Scanner) APKSBOM(ctx context.Context, ssbom *sbomSyft.SBOM) (*Result, error)

APKSBOM scans an SBOM of an APK for vulnerabilities.

func (*Scanner) Close added in v0.23.4

func (s *Scanner) Close()

Close closes the scanner's database connection.

func (*Scanner) DatabaseBuiltAt added in v0.38.16

func (s *Scanner) DatabaseBuiltAt() time.Time

DatabaseBuiltAt returns the time when the vulnerability database was built.

func (*Scanner) ScanAPK added in v0.15.0

func (s *Scanner) ScanAPK(ctx context.Context, apk fs.File, distroID string) (*Result, error)

ScanAPK scans an APK file for vulnerabilities.

type TargetAPK added in v0.1.0

type TargetAPK struct {
	// Name of the package in the APK (i.e., the value of pkgname in PKGINFO).
	// Example: "libcrypto3".
	Name string

	// Version of the package in the APK (i.e., the value of pkgver in PKGINFO).
	// Example: "3.0.11-r0".
	Version string

	// OriginPackageName is the name of the origin package for the package (i.e.,
	// the value of origin in PKGINFO), which, for non-subpackages, would be the
	// same as Name. Example: "openssl".
	OriginPackageName string

	// Arch is the architecture of the package (i.e., the value of arch in PKGINFO).
	// Should be "aarch64" or "x86_64".
	Arch string
}

func (TargetAPK) Origin added in v0.4.2

func (t TargetAPK) Origin() string

Origin returns the name of the origin package, if the package's metadata indicates an origin package. Otherwise, it returns the package name.

type TriageAssessment deprecated added in v0.8.0

type TriageAssessment struct {
	// Source is the name of the source of the triage assessment, e.g.
	// "govulncheck".
	Source string

	// TruePositive indicates whether the vulnerability is a true positive. A value
	// of false indicates that the vulnerability has been assessed to be a false
	// positive.
	TruePositive bool

	// Reason is the explanation of the triage assessment.
	Reason string
}

Deprecated: This type will be removed soon.

type Vulnerability

type Vulnerability struct {
	ID           string
	Severity     string
	Aliases      []string
	FixedVersion string
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL