This commit is contained in:
2026-01-02 18:05:03 +00:00
parent 14c1e044f4
commit 0f7c29c3ef
21 changed files with 1706 additions and 161 deletions
+18 -22
View File
@@ -163,15 +163,11 @@ func (s *Scanner) queryAdvisories(ctx context.Context, ecosystem, packageName st
// filterAffectedAdvisories filters advisories that affect the given version
func (s *Scanner) filterAffectedAdvisories(advisories []GHSAAdvisory, version string) []GHSAAdvisory {
affected := make([]GHSAAdvisory, 0)
for _, advisory := range advisories {
// Check if this version is affected
// GitHub API already filters by package, but we need to check version ranges
// For now, we'll include all advisories that match the package
// A more sophisticated implementation would parse version ranges
affected = append(affected, advisory)
}
// Check if this version is affected
// GitHub API already filters by package, but we need to check version ranges
// For now, we'll include all advisories that match the package
// A more sophisticated implementation would parse version ranges
affected := append([]GHSAAdvisory(nil), advisories...)
return affected
}
@@ -255,16 +251,16 @@ func (s *Scanner) convertResult(advisories []GHSAAdvisory, registry, packageName
// GHSAAdvisory represents a GitHub Security Advisory
type GHSAAdvisory struct {
GHSAID string `json:"ghsa_id"`
CVEID string `json:"cve_id"`
Summary string `json:"summary"`
Description string `json:"description"`
Severity string `json:"severity"`
HTMLURL string `json:"html_url"`
References []GHSAReference `json:"references"`
Vulnerabilities []GHSAVulnerability `json:"vulnerabilities"`
PublishedAt string `json:"published_at"`
UpdatedAt string `json:"updated_at"`
GHSAID string `json:"ghsa_id"`
CVEID string `json:"cve_id"`
Summary string `json:"summary"`
Description string `json:"description"`
Severity string `json:"severity"`
HTMLURL string `json:"html_url"`
References []GHSAReference `json:"references"`
Vulnerabilities []GHSAVulnerability `json:"vulnerabilities"`
PublishedAt string `json:"published_at"`
UpdatedAt string `json:"updated_at"`
}
type GHSAReference struct {
@@ -272,9 +268,9 @@ type GHSAReference struct {
}
type GHSAVulnerability struct {
Package GHSAPackage `json:"package"`
VulnerableVersions string `json:"vulnerable_version_range"`
FirstPatchedVersion *GHSAPatchVersion `json:"first_patched_version"`
Package GHSAPackage `json:"package"`
VulnerableVersions string `json:"vulnerable_version_range"`
FirstPatchedVersion *GHSAPatchVersion `json:"first_patched_version"`
}
type GHSAPackage struct {
+2 -2
View File
@@ -75,7 +75,7 @@ func (s *Scanner) Scan(ctx context.Context, registry, packageName, version strin
// Run govulncheck
cmd := exec.CommandContext(ctx, "govulncheck", "-json", "-mode=binary", tmpDir)
output, err := cmd.CombinedOutput()
output, _ := cmd.CombinedOutput()
// govulncheck returns non-zero when vulnerabilities are found
// Parse output regardless of error
@@ -94,7 +94,7 @@ func (s *Scanner) Scan(ctx context.Context, registry, packageName, version strin
}
if entry.Finding != nil && entry.Finding.OSV != "" {
vulns = append(vulns, GovulncheckVuln{
OSV: entry.Finding.OSV,
OSV: entry.Finding.OSV,
FixedVersion: entry.Finding.FixedVersion,
})
}
+8 -8
View File
@@ -153,9 +153,9 @@ func (s *Scanner) convertGrypeResult(grypeResult *GrypeResult, registry, package
// GrypeResult represents Grype JSON output structure
type GrypeResult struct {
Matches []GrypeMatch `json:"matches"`
Descriptor GrypeDescriptor `json:"descriptor"`
Source GrypeSource `json:"source"`
Matches []GrypeMatch `json:"matches"`
Descriptor GrypeDescriptor `json:"descriptor"`
Source GrypeSource `json:"source"`
}
type GrypeDescriptor struct {
@@ -174,11 +174,11 @@ type GrypeMatch struct {
}
type GrypeVulnerability struct {
ID string `json:"id"`
Severity string `json:"severity"`
Description string `json:"description"`
URLs []string `json:"urls"`
Fix GrypeFix `json:"fix"`
ID string `json:"id"`
Severity string `json:"severity"`
Description string `json:"description"`
URLs []string `json:"urls"`
Fix GrypeFix `json:"fix"`
}
type GrypeFix struct {
+17 -17
View File
@@ -199,20 +199,20 @@ func (s *Scanner) convertResult(auditResult *NpmAuditResult, registry, packageNa
// NpmAuditResult represents npm audit JSON output
type NpmAuditResult struct {
AuditReportVersion int `json:"auditReportVersion"`
Vulnerabilities map[string]NpmVulnerability `json:"vulnerabilities"`
Metadata NpmAuditMetadata `json:"metadata"`
AuditReportVersion int `json:"auditReportVersion"`
Vulnerabilities map[string]NpmVulnerability `json:"vulnerabilities"`
Metadata NpmAuditMetadata `json:"metadata"`
}
type NpmVulnerability struct {
Name string `json:"name"`
Severity string `json:"severity"`
Via string `json:"via"`
Effects []string `json:"effects"`
Range string `json:"range"`
FixAvailable interface{} `json:"fixAvailable"`
URL string `json:"url"`
References []NpmReference `json:"references"`
Name string `json:"name"`
Severity string `json:"severity"`
Via string `json:"via"`
Effects []string `json:"effects"`
Range string `json:"range"`
FixAvailable interface{} `json:"fixAvailable"`
URL string `json:"url"`
References []NpmReference `json:"references"`
}
type NpmReference struct {
@@ -225,10 +225,10 @@ type NpmAuditMetadata struct {
}
type NpmVulnCounts struct {
Info int `json:"info"`
Low int `json:"low"`
Moderate int `json:"moderate"`
High int `json:"high"`
Critical int `json:"critical"`
Total int `json:"total"`
Info int `json:"info"`
Low int `json:"low"`
Moderate int `json:"moderate"`
High int `json:"high"`
Critical int `json:"critical"`
Total int `json:"total"`
}
+13 -13
View File
@@ -48,12 +48,12 @@ type OSVResponse struct {
// OSVVulnerability represents a vulnerability in OSV format
type OSVVulnerability struct {
ID string `json:"id"`
Summary string `json:"summary"`
Details string `json:"details"`
Severity []OSVSeverity `json:"severity,omitempty"`
References []OSVReference `json:"references,omitempty"`
Affected []OSVAffected `json:"affected"`
ID string `json:"id"`
Summary string `json:"summary"`
Details string `json:"details"`
Severity []OSVSeverity `json:"severity,omitempty"`
References []OSVReference `json:"references,omitempty"`
Affected []OSVAffected `json:"affected"`
DatabaseSpecific map[string]interface{} `json:"database_specific,omitempty"`
}
@@ -71,23 +71,23 @@ type OSVReference struct {
// OSVAffected represents affected package versions
type OSVAffected struct {
Package PackageInfo `json:"package"`
Ranges []OSVRange `json:"ranges,omitempty"`
Versions []string `json:"versions,omitempty"`
Package PackageInfo `json:"package"`
Ranges []OSVRange `json:"ranges,omitempty"`
Versions []string `json:"versions,omitempty"`
DatabaseSpecific map[string]interface{} `json:"database_specific,omitempty"`
EcosystemSpecific map[string]interface{} `json:"ecosystem_specific,omitempty"`
}
// OSVRange represents version ranges
type OSVRange struct {
Type string `json:"type"` // SEMVER, GIT, etc.
Events []OSVEvent `json:"events"`
Type string `json:"type"` // SEMVER, GIT, etc.
Events []OSVEvent `json:"events"`
}
// OSVEvent represents version range events
type OSVEvent struct {
Introduced string `json:"introduced,omitempty"`
Fixed string `json:"fixed,omitempty"`
Introduced string `json:"introduced,omitempty"`
Fixed string `json:"fixed,omitempty"`
LastAffected string `json:"last_affected,omitempty"`
}
+3 -3
View File
@@ -196,9 +196,9 @@ type PipAuditResult struct {
}
type PipDependency struct {
Name string `json:"name"`
Version string `json:"version"`
Vulns []PipVuln `json:"vulns"`
Name string `json:"name"`
Version string `json:"version"`
Vulns []PipVuln `json:"vulns"`
}
type PipVuln struct {
+16 -16
View File
@@ -36,10 +36,10 @@ type DatabaseUpdater interface {
// Manager manages multiple security scanners
type Manager struct {
scanners []Scanner
enabled bool
config config.SecurityConfig
metadataStore metadata.MetadataStore
scanners []Scanner
enabled bool
config config.SecurityConfig
metadataStore metadata.MetadataStore
}
// New creates a new scanner manager with configured scanners
@@ -217,15 +217,15 @@ func (m *Manager) mergeResults(results []*metadata.ScanResult, scannerNames []st
// Use first result as base
merged := &metadata.ScanResult{
ID: results[0].ID,
Registry: results[0].Registry,
PackageName: results[0].PackageName,
PackageVersion: results[0].PackageVersion,
Scanner: strings.Join(scannerNames, "+"), // Combined scanner name
ScannedAt: results[0].ScannedAt,
Status: metadata.ScanStatusClean,
ID: results[0].ID,
Registry: results[0].Registry,
PackageName: results[0].PackageName,
PackageVersion: results[0].PackageVersion,
Scanner: strings.Join(scannerNames, "+"), // Combined scanner name
ScannedAt: results[0].ScannedAt,
Status: metadata.ScanStatusClean,
Vulnerabilities: make([]metadata.Vulnerability, 0),
Details: make(map[string]interface{}),
Details: make(map[string]interface{}),
}
// Use map for deduplication - key is CVE ID in uppercase
@@ -431,20 +431,20 @@ func (m *Manager) CheckVulnerabilities(ctx context.Context, registry, packageNam
switch severity {
case "CRITICAL":
if severityCounts["CRITICAL"] > 0 {
return true, fmt.Sprintf("Package has CRITICAL vulnerabilities"), nil
return true, "Package has CRITICAL vulnerabilities", nil
}
case "HIGH":
if severityCounts["CRITICAL"] > 0 || severityCounts["HIGH"] > 0 {
return true, fmt.Sprintf("Package has HIGH or CRITICAL vulnerabilities"), nil
return true, "Package has HIGH or CRITICAL vulnerabilities", nil
}
case "MODERATE", "MEDIUM":
moderateCount := severityCounts["MODERATE"] + severityCounts["MEDIUM"]
if severityCounts["CRITICAL"] > 0 || severityCounts["HIGH"] > 0 || moderateCount > 0 {
return true, fmt.Sprintf("Package has MODERATE, HIGH, or CRITICAL vulnerabilities"), nil
return true, "Package has MODERATE, HIGH, or CRITICAL vulnerabilities", nil
}
case "LOW":
if len(result.Vulnerabilities) > 0 {
return true, fmt.Sprintf("Package has vulnerabilities"), nil
return true, "Package has vulnerabilities", nil
}
}
}
+18 -18
View File
@@ -25,18 +25,18 @@ type Scanner struct {
// TrivyResult represents Trivy JSON output structure
type TrivyResult struct {
SchemaVersion int `json:"SchemaVersion"`
ArtifactName string `json:"ArtifactName"`
ArtifactType string `json:"ArtifactType"`
Metadata TrivyMetadata `json:"Metadata"`
Results []TrivyVulnResult `json:"Results"`
SchemaVersion int `json:"SchemaVersion"`
ArtifactName string `json:"ArtifactName"`
ArtifactType string `json:"ArtifactType"`
Metadata TrivyMetadata `json:"Metadata"`
Results []TrivyVulnResult `json:"Results"`
}
type TrivyMetadata struct {
OS *TrivyOS `json:"OS,omitempty"`
RepoTags []string `json:"RepoTags,omitempty"`
RepoDigests []string `json:"RepoDigests,omitempty"`
ImageConfig *TrivyImageConfig `json:"ImageConfig,omitempty"`
OS *TrivyOS `json:"OS,omitempty"`
RepoTags []string `json:"RepoTags,omitempty"`
RepoDigests []string `json:"RepoDigests,omitempty"`
ImageConfig *TrivyImageConfig `json:"ImageConfig,omitempty"`
}
type TrivyOS struct {
@@ -131,13 +131,13 @@ func (s *Scanner) Scan(ctx context.Context, registry, packageName, version strin
// Check if it's a timeout
if ctx.Err() == context.DeadlineExceeded {
return &metadata.ScanResult{
ID: uuid.New().String(),
Registry: registry,
PackageName: packageName,
PackageVersion: version,
Scanner: s.Name(),
ScannedAt: time.Now(),
Status: metadata.ScanStatusError,
ID: uuid.New().String(),
Registry: registry,
PackageName: packageName,
PackageVersion: version,
Scanner: s.Name(),
ScannedAt: time.Now(),
Status: metadata.ScanStatusError,
Details: map[string]interface{}{
"error": "scan timeout",
},
@@ -222,8 +222,8 @@ func (s *Scanner) convertTrivyResult(trivyResult *TrivyResult, registry, package
VulnerabilityCount: len(vulnerabilities),
Vulnerabilities: vulnerabilities,
Details: map[string]interface{}{
"artifact_name": trivyResult.ArtifactName,
"artifact_type": trivyResult.ArtifactType,
"artifact_name": trivyResult.ArtifactName,
"artifact_type": trivyResult.ArtifactType,
"severity_counts": severityCounts,
},
}