Skip to content

Commit

Permalink
Merge branch 'main' into registry
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixq authored Oct 21, 2024
2 parents 20310f0 + a5a1e29 commit b0295ef
Show file tree
Hide file tree
Showing 45 changed files with 2,805 additions and 22 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
go-version-file: go.mod
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
Expand All @@ -59,7 +59,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13

# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
Expand All @@ -73,4 +73,4 @@ jobs:
# make release

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
2 changes: 1 addition & 1 deletion .github/workflows/osv-scanner-reusable-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
if: ${{ !cancelled() && inputs.upload-sarif == true }}
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
sarif_file: ${{ inputs.results-file-name }}
2 changes: 1 addition & 1 deletion .github/workflows/osv-scanner-reusable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
if: "${{ !cancelled() && inputs.upload-sarif == true }}"
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
sarif_file: ${{ inputs.results-file-name }}
2 changes: 1 addition & 1 deletion .github/workflows/scorecards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,6 @@ jobs:

# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
sarif_file: results.sarif
2 changes: 1 addition & 1 deletion .github/workflows/semantic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
persist-credentials: false
- uses: ruby/setup-ruby@f26937343756480a8cb3ae1f623b9c8d89ed6984 # v1.196.0
- uses: ruby/setup-ruby@7bae1d00b5db9166f4f0fc47985a3a5702cb58f0 # v1.197.0
with:
ruby-version: "3.1"
- name: setup dependencies
Expand Down
2 changes: 1 addition & 1 deletion cmd/osv-scanner/fix/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import (
"strings"

"deps.dev/util/resolve"
"github.com/google/osv-scanner/internal/depsdev"
"github.com/google/osv-scanner/internal/remediation"
"github.com/google/osv-scanner/internal/remediation/upgrade"
"github.com/google/osv-scanner/internal/resolution"
"github.com/google/osv-scanner/internal/resolution/client"
"github.com/google/osv-scanner/internal/resolution/lockfile"
"github.com/google/osv-scanner/internal/resolution/manifest"
"github.com/google/osv-scanner/pkg/depsdev"
"github.com/google/osv-scanner/pkg/reporter"
"github.com/urfave/cli/v2"
"golang.org/x/term"
Expand Down
2 changes: 1 addition & 1 deletion cmd/osv-scanner/scan/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"slices"
"strings"

"github.com/google/osv-scanner/internal/spdx"
"github.com/google/osv-scanner/pkg/osvscanner"
"github.com/google/osv-scanner/pkg/reporter"
"github.com/google/osv-scanner/pkg/spdx"
"golang.org/x/term"

"github.com/urfave/cli/v2"
Expand Down
2 changes: 1 addition & 1 deletion cmd/osv-scanner/update/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import (
"io"
"os"

"github.com/google/osv-scanner/internal/depsdev"
"github.com/google/osv-scanner/internal/remediation/suggest"
"github.com/google/osv-scanner/internal/resolution/client"
"github.com/google/osv-scanner/internal/resolution/manifest"
"github.com/google/osv-scanner/pkg/depsdev"
"github.com/google/osv-scanner/pkg/lockfile"
"github.com/google/osv-scanner/pkg/reporter"
"github.com/urfave/cli/v2"
Expand Down
2 changes: 1 addition & 1 deletion docs/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.2.1)
activesupport (7.2.1.1)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.3.1)
Expand Down
2 changes: 1 addition & 1 deletion internal/ci/vulnerability_result_diff.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package ci

import (
"github.com/google/osv-scanner/internal/grouper"
"github.com/google/osv-scanner/internal/output"
"github.com/google/osv-scanner/pkg/grouper"
"github.com/google/osv-scanner/pkg/models"
)

Expand Down
251 changes: 251 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
package config

import (
"errors"
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"time"

"github.com/BurntSushi/toml"
"github.com/google/osv-scanner/pkg/models"
"github.com/google/osv-scanner/pkg/reporter"
)

const osvScannerConfigName = "osv-scanner.toml"

// Ignore stuttering as that would be a breaking change
// TODO: V2 rename?
//
//nolint:revive
type ConfigManager struct {
// Override to replace all other configs
OverrideConfig *Config
// Config to use if no config file is found alongside manifests
DefaultConfig Config
// Cache to store loaded configs
ConfigMap map[string]Config
}

type Config struct {
IgnoredVulns []IgnoreEntry `toml:"IgnoredVulns"`
PackageOverrides []PackageOverrideEntry `toml:"PackageOverrides"`
GoVersionOverride string `toml:"GoVersionOverride"`
// The path to config file that this config was loaded from,
// set by the scanner after having successfully parsed the file
LoadPath string `toml:"-"`
}

type IgnoreEntry struct {
ID string `toml:"id"`
IgnoreUntil time.Time `toml:"ignoreUntil"`
Reason string `toml:"reason"`
}

type PackageOverrideEntry struct {
Name string `toml:"name"`
// If the version is empty, the entry applies to all versions.
Version string `toml:"version"`
Ecosystem string `toml:"ecosystem"`
Group string `toml:"group"`
Ignore bool `toml:"ignore"`
Vulnerability Vulnerability `toml:"vulnerability"`
License License `toml:"license"`
EffectiveUntil time.Time `toml:"effectiveUntil"`
Reason string `toml:"reason"`
}

func (e PackageOverrideEntry) matches(pkg models.PackageVulns) bool {
if e.Name != "" && e.Name != pkg.Package.Name {
return false
}
if e.Version != "" && e.Version != pkg.Package.Version {
return false
}
if e.Ecosystem != "" && e.Ecosystem != pkg.Package.Ecosystem {
return false
}
if e.Group != "" && !slices.Contains(pkg.DepGroups, e.Group) {
return false
}

return true
}

type Vulnerability struct {
Ignore bool `toml:"ignore"`
}

type License struct {
Override []string `toml:"override"`
Ignore bool `toml:"ignore"`
}

func (c *Config) ShouldIgnore(vulnID string) (bool, IgnoreEntry) {
index := slices.IndexFunc(c.IgnoredVulns, func(e IgnoreEntry) bool { return e.ID == vulnID })
if index == -1 {
return false, IgnoreEntry{}
}
ignoredLine := c.IgnoredVulns[index]

return shouldIgnoreTimestamp(ignoredLine.IgnoreUntil), ignoredLine
}

func (c *Config) filterPackageVersionEntries(pkg models.PackageVulns, condition func(PackageOverrideEntry) bool) (bool, PackageOverrideEntry) {
index := slices.IndexFunc(c.PackageOverrides, func(e PackageOverrideEntry) bool {
return e.matches(pkg) && condition(e)
})
if index == -1 {
return false, PackageOverrideEntry{}
}
ignoredLine := c.PackageOverrides[index]

return shouldIgnoreTimestamp(ignoredLine.EffectiveUntil), ignoredLine
}

// ShouldIgnorePackage determines if the given package should be ignored based on override entries in the config
func (c *Config) ShouldIgnorePackage(pkg models.PackageVulns) (bool, PackageOverrideEntry) {
return c.filterPackageVersionEntries(pkg, func(e PackageOverrideEntry) bool {
return e.Ignore
})
}

// Deprecated: Use ShouldIgnorePackage instead
func (c *Config) ShouldIgnorePackageVersion(name, version, ecosystem string) (bool, PackageOverrideEntry) {
return c.ShouldIgnorePackage(models.PackageVulns{
Package: models.PackageInfo{
Name: name,
Version: version,
Ecosystem: ecosystem,
},
})
}

// ShouldIgnorePackageVulnerabilities determines if the given package should have its vulnerabilities ignored based on override entries in the config
func (c *Config) ShouldIgnorePackageVulnerabilities(pkg models.PackageVulns) bool {
overrides, _ := c.filterPackageVersionEntries(pkg, func(e PackageOverrideEntry) bool {
return e.Vulnerability.Ignore
})

return overrides
}

// ShouldOverridePackageLicense determines if the given package should have its license ignored or changed based on override entries in the config
func (c *Config) ShouldOverridePackageLicense(pkg models.PackageVulns) (bool, PackageOverrideEntry) {
return c.filterPackageVersionEntries(pkg, func(e PackageOverrideEntry) bool {
return e.License.Ignore || len(e.License.Override) > 0
})
}

// Deprecated: Use ShouldOverridePackageLicense instead
func (c *Config) ShouldOverridePackageVersionLicense(name, version, ecosystem string) (bool, PackageOverrideEntry) {
return c.ShouldOverridePackageLicense(models.PackageVulns{
Package: models.PackageInfo{
Name: name,
Version: version,
Ecosystem: ecosystem,
},
})
}

func shouldIgnoreTimestamp(ignoreUntil time.Time) bool {
if ignoreUntil.IsZero() {
// If IgnoreUntil is not set, should ignore.
return true
}
// Should ignore if IgnoreUntil is still after current time
// Takes timezone offsets into account if it is specified. otherwise it's using local time
return ignoreUntil.After(time.Now())
}

// Sets the override config by reading the config file at configPath.
// Will return an error if loading the config file fails
func (c *ConfigManager) UseOverride(configPath string) error {
config, configErr := tryLoadConfig(configPath)
if configErr != nil {
return configErr
}
c.OverrideConfig = &config

return nil
}

// Attempts to get the config
func (c *ConfigManager) Get(r reporter.Reporter, targetPath string) Config {
if c.OverrideConfig != nil {
return *c.OverrideConfig
}

configPath, err := normalizeConfigLoadPath(targetPath)
if err != nil {
// TODO: This can happen when target is not a file (e.g. Docker container, git hash...etc.)
// Figure out a more robust way to load config from non files
// r.PrintErrorf("Can't find config path: %s\n", err)
return Config{}
}

config, alreadyExists := c.ConfigMap[configPath]
if alreadyExists {
return config
}

config, configErr := tryLoadConfig(configPath)
if configErr == nil {
r.Infof("Loaded filter from: %s\n", config.LoadPath)
} else {
// anything other than the config file not existing is most likely due to an invalid config file
if !errors.Is(configErr, os.ErrNotExist) {
r.Errorf("Ignored invalid config file at: %s\n", configPath)
r.Verbosef("Config file %s is invalid because: %v\n", configPath, configErr)
}
// If config doesn't exist, use the default config
config = c.DefaultConfig
}
c.ConfigMap[configPath] = config

return config
}

// Finds the containing folder of `target`, then appends osvScannerConfigName
func normalizeConfigLoadPath(target string) (string, error) {
stat, err := os.Stat(target)
if err != nil {
return "", fmt.Errorf("failed to stat target: %w", err)
}

var containingFolder string
if !stat.IsDir() {
containingFolder = filepath.Dir(target)
} else {
containingFolder = target
}
configPath := filepath.Join(containingFolder, osvScannerConfigName)

return configPath, nil
}

// tryLoadConfig attempts to parse the config file at the given path as TOML,
// returning the Config object if successful or otherwise the error
func tryLoadConfig(configPath string) (Config, error) {
config := Config{}
m, err := toml.DecodeFile(configPath, &config)
if err == nil {
unknownKeys := m.Undecoded()

if len(unknownKeys) > 0 {
keys := make([]string, 0, len(unknownKeys))

for _, key := range unknownKeys {
keys = append(keys, key.String())
}

return Config{}, fmt.Errorf("unknown keys in config file: %s", strings.Join(keys, ", "))
}

config.LoadPath = configPath
}

return config, err
}
Loading

0 comments on commit b0295ef

Please sign in to comment.