@@ -36,8 +36,8 @@ type UserDeviceFinding struct {
3636 ProductName string
3737 CveID string
3838 CveSeverity string
39- MitigationAvailable bool
4039 TimestampFound string
40+ Mitigations []string
4141}
4242
4343func getUniqueDeviceID (hostInfo models.DomainAPIVulnerabilityHostInfoV2 ) (string , error ) {
@@ -118,6 +118,13 @@ func appendUnique(main, adder []string) []string {
118118 return main
119119}
120120
121+ func remove (a []string , i int ) []string {
122+ a [i ] = a [len (a )- 1 ] // Copy last element to index i.
123+ a [len (a )- 1 ] = "" // Erase last element (write zero value).
124+ a = a [:len (a )- 1 ] // Truncate slice.
125+ return a
126+ }
127+
121128func GetMessages (config * config.Config , ctx context.Context ) (results map [string ]FalconResult , err error ) {
122129 falconAPIMaxRecords := int64 (400 )
123130
@@ -174,6 +181,8 @@ func GetMessages(config *config.Config, ctx context.Context) (results map[string
174181 var hostTags []string
175182 devices := map [string ]UserDevice {}
176183
184+ var mitigationIDs []string
185+
177186 for _ , vuln := range getResult .GetPayload ().Resources {
178187
179188 if len (vuln .Remediation .Ids ) == 0 && config .Falcon .SkipNoMitigation {
@@ -200,6 +209,8 @@ func GetMessages(config *config.Config, ctx context.Context) (results map[string
200209 }
201210 }
202211
212+ mitigationIDs = appendUnique (mitigationIDs , vuln .Remediation .Ids )
213+
203214 uniqueDeviceID , err := getUniqueDeviceID (* vuln .HostInfo )
204215 if err != nil {
205216 logrus .WithError (err ).Error ("could not calculate unique device id" )
@@ -239,15 +250,8 @@ func GetMessages(config *config.Config, ctx context.Context) (results map[string
239250 ProductName : * vuln .App .ProductNameVersion ,
240251 CveID : * vuln .Cve .ID ,
241252 CveSeverity : * vuln .Cve .Severity ,
242- MitigationAvailable : len (vuln .Remediation .Ids ) > 0 ,
243253 TimestampFound : * vuln .CreatedTimestamp ,
244- }
245-
246- if ! deviceFinding .MitigationAvailable {
247- logrus .WithField ("cve" ,* vuln .Cve .ID ).WithField ("severity" , * vuln .Cve .Severity ).
248- WithField ("product" , * vuln .App .ProductNameVersion ).
249- Warn ("skipping finding without mitigation(s)" )
250- continue
254+ Mitigations : vuln .Remediation .Ids ,
251255 }
252256
253257 if _ , ok := devices [uniqueDeviceID ]; ! ok {
@@ -292,9 +296,64 @@ func GetMessages(config *config.Config, ctx context.Context) (results map[string
292296 return nil , errors .New ("no tags found on decices" )
293297 }
294298
299+ logrus .WithField ("remediations" , len (mitigationIDs )).Debug ("retrieving remediations" )
300+
301+ remResp , err := client .SpotlightVulnerabilities .GetRemediationsV2 (& spotlight_vulnerabilities.GetRemediationsV2Params {
302+ Ids : mitigationIDs ,
303+ Context : ctx ,
304+ })
305+
306+ if err != nil {
307+ return nil , errors .Wrap (err , "could not retrieve remediations" )
308+ }
309+
310+ remediations := make (map [string ]string )
311+
312+ for _ , remRes := range remResp .GetPayload ().Resources {
313+ logrus .Tracef ("%s -> %s" , * remRes .ID , * remRes .Action )
314+ remediations [* remRes .ID ] = * remRes .Action
315+ }
316+
317+ // remove useless mitigations that start with 'no fix available for'
318+ for a , device := range devices {
319+ for b , finding := range device .Findings {
320+ for c , rem := range finding .Mitigations {
321+ remText , remFound := remediations [rem ]
322+
323+ if ! remFound || strings .HasPrefix (strings .ToLower (remText ), "no fix available for" ) {
324+ logrus .WithField ("rem" , rem ).WithField ("rem_text" , remText ).WithField ("device" , device .MachineName ).
325+ Warn ("skipping mitigation" )
326+
327+ devices [a ].Findings [b ].Mitigations = remove (finding .Mitigations , c )
328+ continue
329+ }
330+
331+ finding .Mitigations [c ] = remText
332+ }
333+ }
334+ }
335+
295336 logrus .WithField ("devices" , len (devices )).Info ("found vulnerable devices" )
296337
297338 for _ , device := range devices {
339+ if len (device .Findings ) == 0 {
340+ continue
341+ }
342+
343+ hasMitigations := false
344+ for _ , f := range device .Findings {
345+ if len (f .Mitigations ) > 0 {
346+ hasMitigations = true
347+ break
348+ }
349+ }
350+
351+ if ! hasMitigations {
352+ logrus .WithField ("device" , device .MachineName ).
353+ Debug ("skipping device with vulnerabilities but no mitigations" )
354+ continue
355+ }
356+
298357 userEmail , err := findEmailTag (device .Tags , config .Email .Domains )
299358 if err != nil {
300359 logrus .
0 commit comments