@@ -63,6 +63,18 @@ public class SuppressionRule {
6363 * The list of cvssBelow scores.
6464 */
6565 private List <Double > cvssBelow = new ArrayList <>();
66+ /**
67+ * The list of cvssV2Below scores.
68+ */
69+ private List <Double > cvssV2Below = new ArrayList <>();
70+ /**
71+ * The list of cvssV3Below scores.
72+ */
73+ private List <Double > cvssV3Below = new ArrayList <>();
74+ /**
75+ * The list of cvssV4Below scores.
76+ */
77+ private List <Double > cvssV4Below = new ArrayList <>();
6678 /**
6779 * The list of CWE entries to suppress.
6880 */
@@ -261,6 +273,114 @@ public boolean hasCvssBelow() {
261273 return !cvssBelow .isEmpty ();
262274 }
263275
276+ /**
277+ * Get the value of cvssV2Below.
278+ *
279+ * @return the value of cvssV2Below
280+ */
281+ public List <Double > getCvssV2Below () {
282+ return cvssV2Below ;
283+ }
284+
285+ /**
286+ * Set the value of cvssV2Below.
287+ *
288+ * @param cvssV2Below new value of cvssV2Below
289+ */
290+ public void setCvssV2Below (List <Double > cvssV2Below ) {
291+ this .cvssV2Below = cvssV2Below ;
292+ }
293+
294+ /**
295+ * Adds the CVSS to the cvssV2Below list.
296+ *
297+ * @param cvss the CVSS to add
298+ */
299+ public void addCvssV2Below (Double cvss ) {
300+ this .cvssV2Below .add (cvss );
301+ }
302+
303+ /**
304+ * Returns whether or not this suppression rule has CVSS v2 suppression criteria.
305+ *
306+ * @return whether or not this suppression rule has CVSS v2 suppression criteria.
307+ */
308+ public boolean hasCvssV2Below () {
309+ return !cvssV2Below .isEmpty ();
310+ }
311+
312+ /**
313+ * Get the value of cvssV3Below.
314+ *
315+ * @return the value of cvssV3Below
316+ */
317+ public List <Double > getCvssV3Below () {
318+ return cvssV3Below ;
319+ }
320+
321+ /**
322+ * Set the value of cvssV3Below.
323+ *
324+ * @param cvssV3Below new value of cvssV3Below
325+ */
326+ public void setCvssV3Below (List <Double > cvssV3Below ) {
327+ this .cvssV3Below = cvssV3Below ;
328+ }
329+
330+ /**
331+ * Adds the CVSS to the cvssV3Below list.
332+ *
333+ * @param cvss the CVSS to add
334+ */
335+ public void addCvssV3Below (Double cvss ) {
336+ this .cvssV3Below .add (cvss );
337+ }
338+
339+ /**
340+ * Returns whether or not this suppression rule has CVSS v3 suppression criteria.
341+ *
342+ * @return whether or not this suppression rule has CVSS v3 suppression criteria.
343+ */
344+ public boolean hasCvssV3Below () {
345+ return !cvssV3Below .isEmpty ();
346+ }
347+
348+ /**
349+ * Get the value of cvssV4Below.
350+ *
351+ * @return the value of cvssV4Below
352+ */
353+ public List <Double > getCvssV4Below () {
354+ return cvssV4Below ;
355+ }
356+
357+ /**
358+ * Set the value of cvssV4Below.
359+ *
360+ * @param cvssV4Below new value of cvssV4Below
361+ */
362+ public void setCvssV4Below (List <Double > cvssV4Below ) {
363+ this .cvssV4Below = cvssV4Below ;
364+ }
365+
366+ /**
367+ * Adds the CVSS to the cvssV4Below list.
368+ *
369+ * @param cvss the CVSS to add
370+ */
371+ public void addCvssV4Below (Double cvss ) {
372+ this .cvssV4Below .add (cvss );
373+ }
374+
375+ /**
376+ * Returns whether or not this suppression rule has CVSS v4 suppression criteria.
377+ *
378+ * @return whether or not this suppression rule has CVSS v4 suppression criteria.
379+ */
380+ public boolean hasCvssV4Below () {
381+ return !cvssV4Below .isEmpty ();
382+ }
383+
264384 /**
265385 * Get the value of notes.
266386 *
@@ -494,7 +614,7 @@ public void process(Dependency dependency) {
494614 }
495615 removalList .forEach (dependency ::removeVulnerableSoftwareIdentifier );
496616 }
497- if (hasCve () || hasVulnerabilityName () || hasCwe () || hasCvssBelow ()) {
617+ if (hasCve () || hasVulnerabilityName () || hasCwe () || hasCvssBelow () || hasCvssV2Below () || hasCvssV3Below () || hasCvssV4Below () ) {
498618 final Set <Vulnerability > removeVulns = new HashSet <>();
499619 for (Vulnerability v : dependency .getVulnerabilities ()) {
500620 boolean remove = false ;
@@ -525,23 +645,9 @@ public void process(Dependency dependency) {
525645 }
526646 }
527647 if (!remove ) {
528- for (Double cvss : this .cvssBelow ) {
529- //TODO validate this comparison
530- if (v .getCvssV2 () != null && v .getCvssV2 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
531- remove = true ;
532- removeVulns .add (v );
533- break ;
534- }
535- if (v .getCvssV3 () != null && v .getCvssV3 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
536- remove = true ;
537- removeVulns .add (v );
538- break ;
539- }
540- if (v .getCvssV4 () != null && v .getCvssV4 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
541- remove = true ;
542- removeVulns .add (v );
543- break ;
544- }
648+ if (suppressedBasedOnScore (v )) {
649+ remove = true ;
650+ removeVulns .add (v );
545651 }
546652 }
547653 if (remove && !isBase ()) {
@@ -556,6 +662,44 @@ public void process(Dependency dependency) {
556662 }
557663 }
558664
665+ boolean suppressedBasedOnScore (Vulnerability v ) {
666+ if (!cvssBelow .isEmpty ()) {
667+ for (Double cvss : this .cvssBelow ) {
668+ //TODO validate this comparison
669+ if (v .getCvssV2 () != null && v .getCvssV2 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
670+ return true ;
671+ }
672+ if (v .getCvssV3 () != null && v .getCvssV3 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
673+ return true ;
674+ }
675+ if (v .getCvssV4 () != null && v .getCvssV4 ().getCvssData ().getBaseScore ().compareTo (cvss ) < 0 ) {
676+ return true ;
677+ }
678+ }
679+ return false ;
680+ }
681+
682+ if (hasCvssV2Below () || hasCvssV3Below () || hasCvssV4Below ()) {
683+ Double v2SuppressionThreshold = this .cvssV2Below .stream ().max (Double ::compare ).orElse (11.0 );
684+ Double v3SuppressionThreshold = this .cvssV3Below .stream ().max (Double ::compare ).orElse (11.0 );
685+ Double v4SuppressionThreshold = this .cvssV4Below .stream ().max (Double ::compare ).orElse (11.0 );
686+
687+ Double v2Score = v .getCvssV2 () != null ? v .getCvssV2 ().getCvssData ().getBaseScore () : null ;
688+ Double v3Score = v .getCvssV3 () != null ? v .getCvssV3 ().getCvssData ().getBaseScore () : null ;
689+ Double v4Score = v .getCvssV4 () != null ? v .getCvssV4 ().getCvssData ().getBaseScore () : null ;
690+
691+ // only if all version indicate suppression will the vulnerability be suppressed
692+ // so if we are missing data (score or threshold) for a specific version we assume suppression
693+ boolean cvssV2CheckSuppressing = v2Score == null || v2Score < v2SuppressionThreshold ;
694+ boolean cvssV3CheckSuppressing = v3Score == null || v3Score < v3SuppressionThreshold ;
695+ boolean cvssV4CheckSuppressing = v4Score == null || v4Score < v4SuppressionThreshold ;
696+
697+ return cvssV2CheckSuppressing && cvssV3CheckSuppressing && cvssV4CheckSuppressing ;
698+ }
699+
700+ return false ;
701+ }
702+
559703 /**
560704 * Identifies if the cpe specified by the cpe suppression rule does not
561705 * specify a version.
@@ -694,6 +838,21 @@ public String toString() {
694838 cvssBelow .forEach ((s ) -> sb .append (s ).append (',' ));
695839 sb .append ('}' );
696840 }
841+ if (cvssV2Below != null && !cvssV2Below .isEmpty ()) {
842+ sb .append ("cvssV2Below={" );
843+ cvssV2Below .forEach ((s ) -> sb .append (s ).append (',' ));
844+ sb .append ('}' );
845+ }
846+ if (cvssV3Below != null && !cvssV3Below .isEmpty ()) {
847+ sb .append ("cvssV3Below={" );
848+ cvssV3Below .forEach ((s ) -> sb .append (s ).append (',' ));
849+ sb .append ('}' );
850+ }
851+ if (cvssV4Below != null && !cvssV4Below .isEmpty ()) {
852+ sb .append ("cvssV4Below={" );
853+ cvssV4Below .forEach ((s ) -> sb .append (s ).append (',' ));
854+ sb .append ('}' );
855+ }
697856 sb .append ('}' );
698857 return sb .toString ();
699858 }
0 commit comments