mirror of
https://github.com/safedep/vet.git
synced 2025-12-10 12:07:30 -06:00
commit
b47355bc03
30
docs/why-vet.md
Normal file
30
docs/why-vet.md
Normal file
@ -0,0 +1,30 @@
|
||||
# Why vet?
|
||||
|
||||
> It has been estimated that Free and Open Source Software (FOSS) constitutes 70-90% of any given piece of modern software solutions.
|
||||
|
||||
<!-- Problem Space -->
|
||||
Product security practices target software developed and deployed internally.
|
||||
They do not cover software consumed from external sources in form of libraries
|
||||
from the Open Source ecosystem. The growing risk of vulnerable, unmaintained
|
||||
and malicious dependencies establishes the need for product security teams to
|
||||
vet 3rd party dependencies before consumption.
|
||||
|
||||
<!-- Current State -->
|
||||
Vetting open source packages is largely a manual and opinionated process
|
||||
involving engineering teams as the requester and security teams as the service
|
||||
provider. A typical OSS vetting process involves auditing dependencies to
|
||||
ensure security, popularity, license compliance, trusted publisher etc. The
|
||||
manual nature of this activity increases cycle time and slows down engineering
|
||||
velocity, especially for evolving products.
|
||||
|
||||
<!-- What vet aims to solve -->
|
||||
`vet` tool solves the problem of OSS dependency vetting by providing a policy
|
||||
driven automated analysis of libraries. It can be seamlessly integrated with
|
||||
any CI tool or used in developer / security engineer's local environment.
|
||||
|
||||
:link: [Get Started](https://github.com/safedep/vet)
|
||||
|
||||
## Reference
|
||||
|
||||
* https://slsa.dev/spec/v0.1/threats
|
||||
* https://www.linuxfoundation.org/blog/blog/a-summary-of-census-ii-open-source-software-application-libraries-the-world-depends-on
|
||||
@ -71,6 +71,14 @@ func (f *celFilterAnalyzer) Analyze(manifest *models.PackageManifest,
|
||||
|
||||
f.stat.IncMatchedPackage()
|
||||
f.packages[pkg.Id()] = pkg
|
||||
|
||||
handler(&AnalyzerEvent{
|
||||
Source: f.Name(),
|
||||
Type: ET_FilterExpressionMatched,
|
||||
Manifest: manifest,
|
||||
Package: pkg,
|
||||
Message: "cli-filter",
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -78,7 +78,7 @@ func (f *celFilterSuiteAnalyzer) Analyze(manifest *models.PackageManifest,
|
||||
}
|
||||
|
||||
if res.Matched() {
|
||||
f.queueMatchedPkg(pkg, res.GetMatchedFilter().Name())
|
||||
f.handleMatchedPkg(pkg, res.GetMatchedFilter().Name(), handler)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -123,8 +123,8 @@ func (f *celFilterSuiteAnalyzer) renderMatchTable() {
|
||||
tbl.Render()
|
||||
}
|
||||
|
||||
func (f *celFilterSuiteAnalyzer) queueMatchedPkg(pkg *models.Package,
|
||||
filterName string) {
|
||||
func (f *celFilterSuiteAnalyzer) handleMatchedPkg(pkg *models.Package,
|
||||
filterName string, handler AnalyzerEventHandler) {
|
||||
if _, ok := f.matchedPackages[pkg.Id()]; ok {
|
||||
return
|
||||
}
|
||||
@ -134,6 +134,14 @@ func (f *celFilterSuiteAnalyzer) queueMatchedPkg(pkg *models.Package,
|
||||
filterName: filterName,
|
||||
pkg: pkg,
|
||||
}
|
||||
|
||||
handler(&AnalyzerEvent{
|
||||
Source: f.Name(),
|
||||
Type: ET_FilterExpressionMatched,
|
||||
Manifest: pkg.Manifest,
|
||||
Package: pkg,
|
||||
Message: filterName,
|
||||
})
|
||||
}
|
||||
|
||||
// To correctly unmarshal a []byte into protobuf message, we must use
|
||||
|
||||
@ -3,3 +3,7 @@ package analyzer
|
||||
func (ev *AnalyzerEvent) IsFailOnError() bool {
|
||||
return ev.Type == ET_AnalyzerFailOnError
|
||||
}
|
||||
|
||||
func (ev *AnalyzerEvent) IsFilterMatch() bool {
|
||||
return ev.Type == ET_FilterExpressionMatched
|
||||
}
|
||||
|
||||
@ -21,6 +21,12 @@ type MarkdownReportingConfig struct {
|
||||
Path string
|
||||
}
|
||||
|
||||
type markdownTemplateInputViolation struct {
|
||||
Ecosystem string
|
||||
PkgName string
|
||||
Message string
|
||||
}
|
||||
|
||||
type markdownTemplateInputRemediation struct {
|
||||
Pkg *models.Package
|
||||
PkgRemediationName string
|
||||
@ -36,6 +42,7 @@ type markdownTemplateInputResultSummary struct {
|
||||
type markdownTemplateInput struct {
|
||||
Remediations map[string][]markdownTemplateInputRemediation
|
||||
Summary map[string]markdownTemplateInputResultSummary
|
||||
Violations []markdownTemplateInputViolation
|
||||
ManifestsCount int
|
||||
PackagesCount int
|
||||
}
|
||||
@ -47,6 +54,7 @@ type markdownReportGenerator struct {
|
||||
config MarkdownReportingConfig
|
||||
summaryReporter Reporter
|
||||
templateInput markdownTemplateInput
|
||||
violations map[string]*analyzer.AnalyzerEvent
|
||||
}
|
||||
|
||||
func NewMarkdownReportGenerator(config MarkdownReportingConfig) (Reporter, error) {
|
||||
@ -54,6 +62,7 @@ func NewMarkdownReportGenerator(config MarkdownReportingConfig) (Reporter, error
|
||||
return &markdownReportGenerator{
|
||||
config: config,
|
||||
summaryReporter: summaryReporter,
|
||||
violations: make(map[string]*analyzer.AnalyzerEvent),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -65,7 +74,26 @@ func (r *markdownReportGenerator) AddManifest(manifest *models.PackageManifest)
|
||||
r.summaryReporter.AddManifest(manifest)
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) AddAnalyzerEvent(event *analyzer.AnalyzerEvent) {}
|
||||
func (r *markdownReportGenerator) AddAnalyzerEvent(event *analyzer.AnalyzerEvent) {
|
||||
if !event.IsFilterMatch() {
|
||||
return
|
||||
}
|
||||
|
||||
if event.Package == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if event.Package.Manifest == nil {
|
||||
return
|
||||
}
|
||||
|
||||
pkgId := event.Package.Id()
|
||||
if _, ok := r.violations[pkgId]; ok {
|
||||
return
|
||||
}
|
||||
|
||||
r.violations[pkgId] = event
|
||||
}
|
||||
|
||||
func (r *markdownReportGenerator) AddPolicyEvent(event *policy.PolicyEvent) {}
|
||||
|
||||
@ -103,6 +131,20 @@ func (r *markdownReportGenerator) Finish() error {
|
||||
}
|
||||
}
|
||||
|
||||
violations := []markdownTemplateInputViolation{}
|
||||
for _, v := range r.violations {
|
||||
var msg string
|
||||
if msg, ok = v.Message.(string); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
violations = append(violations, markdownTemplateInputViolation{
|
||||
Ecosystem: v.Manifest.Ecosystem,
|
||||
PkgName: fmt.Sprintf("%s@%s", v.Package.Name, v.Package.Version),
|
||||
Message: msg,
|
||||
})
|
||||
}
|
||||
|
||||
tmpl, err := template.New("markdown").Parse(markdownTemplate)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -119,5 +161,6 @@ func (r *markdownReportGenerator) Finish() error {
|
||||
ManifestsCount: sr.summary.manifests,
|
||||
PackagesCount: sr.summary.packages,
|
||||
Summary: summaries,
|
||||
Violations: violations,
|
||||
})
|
||||
}
|
||||
|
||||
@ -15,6 +15,18 @@
|
||||
| {{ $key }} | {{ $value.Ecosystem }} | {{ $value.PackageCount }} | {{ $value.PackageWithIssuesCount }} |
|
||||
{{- end }}
|
||||
|
||||
## Policy Violation
|
||||
|
||||
{{ if .Violations }}
|
||||
| Ecosystem | Package | Reason |
|
||||
|-----------|---------|--------|
|
||||
{{- range $value := .Violations }}
|
||||
| {{ $value.Ecosystem }} | {{ $value.PkgName }} | {{ $value.Message }} |
|
||||
{{- end }}
|
||||
{{ else }}
|
||||
> No policy violation found or policy not configured during scan
|
||||
{{ end }}
|
||||
|
||||
## Remediation Advice
|
||||
|
||||
The table below lists advice for dependency upgrade to mitigate one or more
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user