@@ -97,7 +97,7 @@ func preferMarkdown(text common.Text) string {
9797
9898func (s * service ) HandleFirstPartyVulnResult (org models.Org , project models.Project , asset models.Asset , assetVersion * models.AssetVersion , sarifScan common.SarifResult , scannerID string , userID string ) (int , int , []models.FirstPartyVuln , error ) {
9999
100- firstPartyVulnerabilities := [ ]models.FirstPartyVuln {}
100+ firstPartyVulnerabilitiesMap := make ( map [ string ]models.FirstPartyVuln )
101101
102102 ruleMap := make (map [string ]common.Rule )
103103 for _ , run := range sarifScan .Runs {
@@ -135,22 +135,58 @@ func (s *service) HandleFirstPartyVulnResult(org models.Org, project models.Proj
135135 firstPartyVulnerability .Date = result .PartialFingerprints .Date
136136 }
137137
138+ var hash string
139+ if result .Fingerprints != nil {
140+ if result .Fingerprints .CalculatedFingerprint != "" {
141+ firstPartyVulnerability .Fingerprint = result .Fingerprints .CalculatedFingerprint
142+ }
143+ }
144+
138145 if len (result .Locations ) > 0 {
139146 firstPartyVulnerability .URI = result .Locations [0 ].PhysicalLocation .ArtifactLocation .URI
140- firstPartyVulnerability .StartLine = result .Locations [0 ].PhysicalLocation .Region .StartLine
141- firstPartyVulnerability .StartColumn = result .Locations [0 ].PhysicalLocation .Region .StartColumn
142- firstPartyVulnerability .EndLine = result .Locations [0 ].PhysicalLocation .Region .EndLine
143- firstPartyVulnerability .EndColumn = result .Locations [0 ].PhysicalLocation .Region .EndColumn
144- firstPartyVulnerability .Snippet = result .Locations [0 ].PhysicalLocation .Region .Snippet .Text
147+
148+ snippetContent := models.SnippetContent {
149+ StartLine : result .Locations [0 ].PhysicalLocation .Region .StartLine ,
150+ EndLine : result .Locations [0 ].PhysicalLocation .Region .EndLine ,
151+ StartColumn : result .Locations [0 ].PhysicalLocation .Region .StartColumn ,
152+ EndColumn : result .Locations [0 ].PhysicalLocation .Region .EndColumn ,
153+ Snippet : result .Locations [0 ].PhysicalLocation .Region .Snippet .Text ,
154+ }
155+
156+ hash = firstPartyVulnerability .CalculateHash ()
157+ if existingVuln , ok := firstPartyVulnerabilitiesMap [hash ]; ok {
158+ snippetContents , err := existingVuln .FromJSONSnippetContents ()
159+ if err != nil {
160+ return 0 , 0 , []models.FirstPartyVuln {}, errors .Wrap (err , "could not parse existing snippet contents" )
161+ }
162+ snippetContents .Snippets = append (snippetContents .Snippets , snippetContent )
163+ firstPartyVulnerability .SnippetContents , err = snippetContents .ToJSON ()
164+ if err != nil {
165+ return 0 , 0 , []models.FirstPartyVuln {}, errors .Wrap (err , "could not convert snippet contents to JSON" )
166+ }
167+
168+ } else {
169+
170+ snippetContents := models.SnippetContents {
171+ Snippets : []models.SnippetContent {snippetContent },
172+ }
173+ var err error
174+ firstPartyVulnerability .SnippetContents , err = snippetContents .ToJSON ()
175+ if err != nil {
176+ return 0 , 0 , []models.FirstPartyVuln {}, errors .Wrap (err , "could not convert snippet contents to JSON" )
177+ }
178+
179+ }
180+ firstPartyVulnerabilitiesMap [hash ] = firstPartyVulnerability
181+
145182 }
146183
147- firstPartyVulnerabilities = append (firstPartyVulnerabilities , firstPartyVulnerability )
148184 }
149185 }
150-
151- firstPartyVulnerabilities = utils . UniqBy ( firstPartyVulnerabilities , func ( f models. FirstPartyVuln ) string {
152- return f . CalculateHash ( )
153- })
186+ var firstPartyVulnerabilities []models. FirstPartyVuln
187+ for _ , vuln := range firstPartyVulnerabilitiesMap {
188+ firstPartyVulnerabilities = append ( firstPartyVulnerabilities , vuln )
189+ }
154190
155191 amountOpened , amountClosed , amountExisting , err := s .handleFirstPartyVulnResult (userID , scannerID , assetVersion , firstPartyVulnerabilities , asset , org , project )
156192 if err != nil {
@@ -186,18 +222,42 @@ func (s *service) handleFirstPartyVulnResult(userID string, scannerID string, as
186222 fixedVulns := comparison .OnlyInA
187223 newVulns := comparison .OnlyInB
188224
225+ inBoth := comparison .InBoth // these are the vulns that are already in the database, but we need to update them
226+
227+ updatedFirstPartyVulns := make ([]models.FirstPartyVuln , 0 )
228+
229+ for i := range inBoth {
230+ for n := range vulns {
231+ if inBoth [i ].ID == vulns [n ].ID {
232+ // we found a new vuln that is already in the database, we need to update it
233+ inBoth [i ].SnippetContents = vulns [n ].SnippetContents
234+ updatedFirstPartyVulns = append (updatedFirstPartyVulns , inBoth [i ])
235+ }
236+ }
237+ }
238+
189239 // get a transaction
190240 if err := s .firstPartyVulnRepository .Transaction (func (tx core.DB ) error {
191241 if err := s .firstPartyVulnService .UserDetectedFirstPartyVulns (tx , userID , scannerID , newVulns ); err != nil {
192242 // this will cancel the transaction
193243 return err
194244 }
195- return s .firstPartyVulnService .UserFixedFirstPartyVulns (tx , userID , fixedVulns )
245+ if err := s .firstPartyVulnService .UserFixedFirstPartyVulns (tx , userID , fixedVulns ); err != nil {
246+ return err
247+ }
248+
249+ // update existing first party vulns within the transaction
250+ for _ , v := range updatedFirstPartyVulns {
251+ if err := s .firstPartyVulnRepository .Save (tx , & v ); err != nil {
252+ slog .Error ("could not update existing first party vulns" , "err" , err )
253+ return err
254+ }
255+ }
256+ return nil
196257 }); err != nil {
197258 slog .Error ("could not save vulns" , "err" , err )
198259 return 0 , 0 , []models.FirstPartyVuln {}, err
199260 }
200-
201261 // the amount we actually fixed, is the amount that was open before
202262 fixedVulns = utils .Filter (fixedVulns , func (vuln models.FirstPartyVuln ) bool {
203263 return vuln .State == models .VulnStateOpen
@@ -217,7 +277,7 @@ func (s *service) handleFirstPartyVulnResult(userID string, scannerID string, as
217277 }()
218278 }
219279
220- return len (newVulns ), len (fixedVulns ), append (newVulns , comparison . InBoth ... ), nil
280+ return len (newVulns ), len (fixedVulns ), append (newVulns , inBoth ... ), nil
221281}
222282
223283func (s * service ) HandleScanResult (org models.Org , project models.Project , asset models.Asset , assetVersion * models.AssetVersion , vulns []models.VulnInPackage , scannerID string , userID string ) (opened []models.DependencyVuln , closed []models.DependencyVuln , newState []models.DependencyVuln , err error ) {
0 commit comments