@@ -40,14 +40,15 @@ func getResolver(sys resolve.System, cl resolve.Client) (resolve.Resolver, error
40
40
}
41
41
}
42
42
43
- func Resolve (ctx context.Context , cl resolve. Client , m manifest.Manifest ) (* ResolutionResult , error ) {
44
- c := client .NewOverrideClient (cl )
43
+ func Resolve (ctx context.Context , cl client. ResolutionClient , m manifest.Manifest ) (* ResolutionResult , error ) {
44
+ c := client .NewOverrideClient (cl . DependencyClient )
45
45
c .AddVersion (m .Root , m .Requirements )
46
46
for _ , loc := range m .LocalManifests {
47
47
c .AddVersion (loc .Root , loc .Requirements )
48
48
// TODO: may need to do this recursively
49
49
}
50
- r , err := getResolver (m .System (), c )
50
+ cl .DependencyClient = c
51
+ r , err := getResolver (m .System (), cl .DependencyClient )
51
52
if err != nil {
52
53
return nil , err
53
54
}
@@ -66,7 +67,7 @@ func Resolve(ctx context.Context, cl resolve.Client, m manifest.Manifest) (*Reso
66
67
Graph : graph ,
67
68
}
68
69
69
- if err := result .computeVulns (ctx , c ); err != nil {
70
+ if err := result .computeVulns (ctx , cl ); err != nil {
70
71
return nil , err
71
72
}
72
73
@@ -76,9 +77,56 @@ func Resolve(ctx context.Context, cl resolve.Client, m manifest.Manifest) (*Reso
76
77
return result , nil
77
78
}
78
79
79
- var OSVEcosystem = map [resolve.System ]models.Ecosystem {
80
- resolve .NPM : models .EcosystemNPM ,
81
- resolve .Maven : models .EcosystemMaven ,
80
+ // computeVulns scans for vulnerabilities in a resolved graph and populates res.Vulns
81
+ func (res * ResolutionResult ) computeVulns (ctx context.Context , cl client.ResolutionClient ) error {
82
+ nodeVulns , err := cl .FindVulns (res .Graph )
83
+ if err != nil {
84
+ return err
85
+ }
86
+ // Find all dependency paths to the vulnerable dependencies
87
+ var vulnerableNodes []resolve.NodeID
88
+ vulnInfo := make (map [string ]models.Vulnerability )
89
+ for i , vulns := range nodeVulns {
90
+ if len (vulns ) > 0 {
91
+ vulnerableNodes = append (vulnerableNodes , resolve .NodeID (i ))
92
+ }
93
+ for _ , vuln := range vulns {
94
+ vulnInfo [vuln .ID ] = vuln
95
+ }
96
+ }
97
+
98
+ nodeChains := computeChains (res .Graph , vulnerableNodes )
99
+ vulnChains := make (map [string ][]DependencyChain )
100
+ for i , idx := range vulnerableNodes {
101
+ for _ , vuln := range nodeVulns [idx ] {
102
+ vulnChains [vuln .ID ] = append (vulnChains [vuln .ID ], nodeChains [i ]... )
103
+ }
104
+ }
105
+
106
+ // construct the ResolutionVulns
107
+ // TODO: This constructs a single ResolutionVuln per vulnerability ID.
108
+ // The scan action treats vulns with the same ID but affecting different versions of a package as distinct.
109
+ // TODO: Combine aliased IDs
110
+ for id , vuln := range vulnInfo {
111
+ rv := ResolutionVuln {Vulnerability : vuln , DevOnly : true }
112
+ for _ , chain := range vulnChains [id ] {
113
+ if chainConstrains (ctx , cl , chain , & rv .Vulnerability ) {
114
+ rv .ProblemChains = append (rv .ProblemChains , chain )
115
+ } else {
116
+ rv .NonProblemChains = append (rv .NonProblemChains , chain )
117
+ }
118
+ rv .DevOnly = rv .DevOnly && ChainIsDev (chain , res .Manifest )
119
+ }
120
+ if len (rv .ProblemChains ) == 0 {
121
+ // There has to be at least one problem chain for the vulnerability to appear.
122
+ // If our heuristic couldn't determine any, treat them all as problematic.
123
+ rv .ProblemChains = rv .NonProblemChains
124
+ rv .NonProblemChains = nil
125
+ }
126
+ res .Vulns = append (res .Vulns , rv )
127
+ }
128
+
129
+ return nil
82
130
}
83
131
84
132
// FilterVulns populates Vulns with the UnfilteredVulns that satisfy matchFn
0 commit comments