Coverage Report - org.owasp.dependencycheck.suppression.SuppressionRule
 
Classes in this File Line Coverage Branch Coverage Complexity
SuppressionRule
73%
108/146
67%
74/110
2.897
 
 1  
 /*
 2  
  * This file is part of dependency-check-core.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  *
 16  
  * Copyright (c) 2013 Jeremy Long. All Rights Reserved.
 17  
  */
 18  
 package org.owasp.dependencycheck.suppression;
 19  
 
 20  
 import java.util.ArrayList;
 21  
 import java.util.Iterator;
 22  
 import java.util.List;
 23  
 import org.apache.commons.lang3.StringUtils;
 24  
 import org.owasp.dependencycheck.dependency.Dependency;
 25  
 import org.owasp.dependencycheck.dependency.Identifier;
 26  
 import org.owasp.dependencycheck.dependency.Vulnerability;
 27  
 
 28  
 /**
 29  
  *
 30  
  * @author Jeremy Long
 31  
  */
 32  155
 public class SuppressionRule {
 33  
 
 34  
     /**
 35  
      * The file path for the suppression.
 36  
      */
 37  
     private PropertyType filePath;
 38  
 
 39  
     /**
 40  
      * Get the value of filePath.
 41  
      *
 42  
      * @return the value of filePath
 43  
      */
 44  
     public PropertyType getFilePath() {
 45  1
         return filePath;
 46  
     }
 47  
 
 48  
     /**
 49  
      * Set the value of filePath.
 50  
      *
 51  
      * @param filePath new value of filePath
 52  
      */
 53  
     public void setFilePath(PropertyType filePath) {
 54  34
         this.filePath = filePath;
 55  34
     }
 56  
     /**
 57  
      * The sha1 hash.
 58  
      */
 59  
     private String sha1;
 60  
 
 61  
     /**
 62  
      * Get the value of sha1.
 63  
      *
 64  
      * @return the value of sha1
 65  
      */
 66  
     public String getSha1() {
 67  1
         return sha1;
 68  
     }
 69  
 
 70  
     /**
 71  
      * Set the value of sha1.
 72  
      *
 73  
      * @param sha1 new value of sha1
 74  
      */
 75  
     public void setSha1(String sha1) {
 76  6
         this.sha1 = sha1;
 77  6
     }
 78  
     /**
 79  
      * A list of CPEs to suppression
 80  
      */
 81  155
     private List<PropertyType> cpe = new ArrayList<PropertyType>();
 82  
 
 83  
     /**
 84  
      * Get the value of cpe.
 85  
      *
 86  
      * @return the value of cpe
 87  
      */
 88  
     public List<PropertyType> getCpe() {
 89  1
         return cpe;
 90  
     }
 91  
 
 92  
     /**
 93  
      * Set the value of cpe.
 94  
      *
 95  
      * @param cpe new value of cpe
 96  
      */
 97  
     public void setCpe(List<PropertyType> cpe) {
 98  1
         this.cpe = cpe;
 99  1
     }
 100  
 
 101  
     /**
 102  
      * Adds the cpe to the cpe list.
 103  
      *
 104  
      * @param cpe the cpe to add
 105  
      */
 106  
     public void addCpe(PropertyType cpe) {
 107  235
         this.cpe.add(cpe);
 108  235
     }
 109  
 
 110  
     /**
 111  
      * Returns whether or not this suppression rule as CPE entries.
 112  
      *
 113  
      * @return whether or not this suppression rule as CPE entries
 114  
      */
 115  
     public boolean hasCpe() {
 116  19
         return !cpe.isEmpty();
 117  
     }
 118  
     /**
 119  
      * The list of cvssBelow scores.
 120  
      */
 121  155
     private List<Float> cvssBelow = new ArrayList<Float>();
 122  
 
 123  
     /**
 124  
      * Get the value of cvssBelow.
 125  
      *
 126  
      * @return the value of cvssBelow
 127  
      */
 128  
     public List<Float> getCvssBelow() {
 129  1
         return cvssBelow;
 130  
     }
 131  
 
 132  
     /**
 133  
      * Set the value of cvssBelow.
 134  
      *
 135  
      * @param cvssBelow new value of cvssBelow
 136  
      */
 137  
     public void setCvssBelow(List<Float> cvssBelow) {
 138  1
         this.cvssBelow = cvssBelow;
 139  1
     }
 140  
 
 141  
     /**
 142  
      * Adds the cvss to the cvssBelow list.
 143  
      *
 144  
      * @param cvss the cvss to add
 145  
      */
 146  
     public void addCvssBelow(Float cvss) {
 147  7
         this.cvssBelow.add(cvss);
 148  7
     }
 149  
 
 150  
     /**
 151  
      * Returns whether or not this suppression rule has cvss suppressions.
 152  
      *
 153  
      * @return whether or not this suppression rule has cvss suppressions
 154  
      */
 155  
     public boolean hasCvssBelow() {
 156  16
         return !cvssBelow.isEmpty();
 157  
     }
 158  
     /**
 159  
      * The list of cwe entries to suppress.
 160  
      */
 161  155
     private List<String> cwe = new ArrayList<String>();
 162  
 
 163  
     /**
 164  
      * Get the value of cwe.
 165  
      *
 166  
      * @return the value of cwe
 167  
      */
 168  
     public List<String> getCwe() {
 169  1
         return cwe;
 170  
     }
 171  
 
 172  
     /**
 173  
      * Set the value of cwe.
 174  
      *
 175  
      * @param cwe new value of cwe
 176  
      */
 177  
     public void setCwe(List<String> cwe) {
 178  1
         this.cwe = cwe;
 179  1
     }
 180  
 
 181  
     /**
 182  
      * Adds the cwe to the cwe list.
 183  
      *
 184  
      * @param cwe the cwe to add
 185  
      */
 186  
     public void addCwe(String cwe) {
 187  2
         this.cwe.add(cwe);
 188  2
     }
 189  
 
 190  
     /**
 191  
      * Returns whether this suppression rule has CWE entries.
 192  
      *
 193  
      * @return whether this suppression rule has CWE entries
 194  
      */
 195  
     public boolean hasCwe() {
 196  17
         return !cwe.isEmpty();
 197  
     }
 198  
     /**
 199  
      * The list of cve entries to suppress.
 200  
      */
 201  155
     private List<String> cve = new ArrayList<String>();
 202  
 
 203  
     /**
 204  
      * Get the value of cve.
 205  
      *
 206  
      * @return the value of cve
 207  
      */
 208  
     public List<String> getCve() {
 209  1
         return cve;
 210  
     }
 211  
 
 212  
     /**
 213  
      * Set the value of cve.
 214  
      *
 215  
      * @param cve new value of cve
 216  
      */
 217  
     public void setCve(List<String> cve) {
 218  1
         this.cve = cve;
 219  1
     }
 220  
 
 221  
     /**
 222  
      * Adds the cve to the cve list.
 223  
      *
 224  
      * @param cve the cve to add
 225  
      */
 226  
     public void addCve(String cve) {
 227  11
         this.cve.add(cve);
 228  11
     }
 229  
 
 230  
     /**
 231  
      * Returns whether this suppression rule has CVE entries.
 232  
      *
 233  
      * @return whether this suppression rule has CVE entries
 234  
      */
 235  
     public boolean hasCve() {
 236  19
         return !cve.isEmpty();
 237  
     }
 238  
     /**
 239  
      * A Maven GAV to suppression.
 240  
      */
 241  155
     private PropertyType gav = null;
 242  
 
 243  
     /**
 244  
      * Get the value of Maven GAV.
 245  
      *
 246  
      * @return the value of gav
 247  
      */
 248  
     public PropertyType getGav() {
 249  0
         return gav;
 250  
     }
 251  
 
 252  
     /**
 253  
      * Set the value of Maven GAV.
 254  
      *
 255  
      * @param gav new value of Maven gav
 256  
      */
 257  
     public void setGav(PropertyType gav) {
 258  101
         this.gav = gav;
 259  101
     }
 260  
 
 261  
     /**
 262  
      * Returns whether or not this suppression rule as GAV entries.
 263  
      *
 264  
      * @return whether or not this suppression rule as GAV entries
 265  
      */
 266  
     public boolean hasGav() {
 267  0
         return gav != null;
 268  
     }
 269  
 
 270  
     /**
 271  
      * A flag indicating whether or not the suppression rule is a core/base rule that should not be included in the
 272  
      * resulting report in the "suppressed" section.
 273  
      */
 274  
     private boolean base;
 275  
 
 276  
     /**
 277  
      * Get the value of base.
 278  
      *
 279  
      * @return the value of base
 280  
      */
 281  
     public boolean isBase() {
 282  17
         return base;
 283  
     }
 284  
 
 285  
     /**
 286  
      * Set the value of base.
 287  
      *
 288  
      * @param base new value of base
 289  
      */
 290  
     public void setBase(boolean base) {
 291  142
         this.base = base;
 292  142
     }
 293  
 
 294  
     /**
 295  
      * Processes a given dependency to determine if any CPE, CVE, CWE, or CVSS scores should be suppressed. If any
 296  
      * should be, they are removed from the dependency.
 297  
      *
 298  
      * @param dependency a project dependency to analyze
 299  
      */
 300  
     public void process(Dependency dependency) {
 301  106
         if (filePath != null && !filePath.matches(dependency.getFilePath())) {
 302  8
             return;
 303  
         }
 304  98
         if (sha1 != null && !sha1.equalsIgnoreCase(dependency.getSha1sum())) {
 305  1
             return;
 306  
         }
 307  97
         if (gav != null) {
 308  81
             final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
 309  81
             boolean gavFound = false;
 310  165
             while (itr.hasNext()) {
 311  85
                 final Identifier i = itr.next();
 312  85
                 if (identifierMatches("maven", this.gav, i)) {
 313  1
                     gavFound = true;
 314  1
                     break;
 315  
                 }
 316  84
             }
 317  81
             if (!gavFound) {
 318  80
                 return;
 319  
             }
 320  
         }
 321  
 
 322  17
         if (this.hasCpe()) {
 323  12
             final Iterator<Identifier> itr = dependency.getIdentifiers().iterator();
 324  30
             while (itr.hasNext()) {
 325  18
                 final Identifier i = itr.next();
 326  18
                 for (PropertyType c : this.cpe) {
 327  26
                     if (identifierMatches("cpe", c, i)) {
 328  7
                         if (!isBase()) {
 329  4
                             dependency.addSuppressedIdentifier(i);
 330  
                         }
 331  7
                         itr.remove();
 332  7
                         break;
 333  
                     }
 334  19
                 }
 335  18
             }
 336  
         }
 337  17
         if (hasCve() || hasCwe() || hasCvssBelow()) {
 338  5
             final Iterator<Vulnerability> itr = dependency.getVulnerabilities().iterator();
 339  10
             while (itr.hasNext()) {
 340  5
                 boolean remove = false;
 341  5
                 final Vulnerability v = itr.next();
 342  5
                 for (String entry : this.cve) {
 343  3
                     if (entry.equalsIgnoreCase(v.getName())) {
 344  1
                         remove = true;
 345  1
                         break;
 346  
                     }
 347  2
                 }
 348  5
                 if (!remove) {
 349  4
                     for (String entry : this.cwe) {
 350  1
                         if (v.getCwe() != null) {
 351  1
                             final String toMatch = String.format("CWE-%s ", entry);
 352  1
                             final String toTest = v.getCwe().substring(0, toMatch.length()).toUpperCase();
 353  1
                             if (toTest.equals(toMatch)) {
 354  1
                                 remove = true;
 355  1
                                 break;
 356  
                             }
 357  
                         }
 358  0
                     }
 359  
                 }
 360  5
                 if (!remove) {
 361  3
                     for (float cvss : this.cvssBelow) {
 362  3
                         if (v.getCvssScore() < cvss) {
 363  1
                             remove = true;
 364  1
                             break;
 365  
                         }
 366  2
                     }
 367  
                 }
 368  5
                 if (remove) {
 369  3
                     if (!isBase()) {
 370  3
                         dependency.addSuppressedVulnerability(v);
 371  
                     }
 372  3
                     itr.remove();
 373  
                 }
 374  5
             }
 375  
         }
 376  17
     }
 377  
 
 378  
     /**
 379  
      * Identifies if the cpe specified by the cpe suppression rule does not specify a version.
 380  
      *
 381  
      * @param c a suppression rule identifier
 382  
      * @return true if the property type does not specify a version; otherwise false
 383  
      */
 384  
     boolean cpeHasNoVersion(PropertyType c) {
 385  30
         return !c.isRegex() && StringUtils.countMatches(c.getValue(), ':') == 3;
 386  
     }
 387  
 
 388  
     /**
 389  
      * Determines if the cpeEntry specified as a PropertyType matches the given Identifier.
 390  
      *
 391  
      * @param identifierType the type of identifier ("cpe", "maven", etc.)
 392  
      * @param suppressionEntry a suppression rule entry
 393  
      * @param identifier a CPE identifier to check
 394  
      * @return true if the entry matches; otherwise false
 395  
      */
 396  
     boolean identifierMatches(String identifierType, PropertyType suppressionEntry, Identifier identifier) {
 397  120
         if (identifierType.equals(identifier.getType())) {
 398  33
             if (suppressionEntry.matches(identifier.getValue())) {
 399  5
                 return true;
 400  28
             } else if ("cpe".equals(identifierType) && cpeHasNoVersion(suppressionEntry)) {
 401  21
                 if (suppressionEntry.isCaseSensitive()) {
 402  0
                     return identifier.getValue().startsWith(suppressionEntry.getValue());
 403  
                 } else {
 404  21
                     final String id = identifier.getValue().toLowerCase();
 405  21
                     final String check = suppressionEntry.getValue().toLowerCase();
 406  21
                     return id.startsWith(check);
 407  
                 }
 408  
             }
 409  
         }
 410  94
         return false;
 411  
     }
 412  
 
 413  
     /**
 414  
      * Standard toString implementation.
 415  
      *
 416  
      * @return a string representation of this object
 417  
      */
 418  
     @Override
 419  
     public String toString() {
 420  0
         final StringBuilder sb = new StringBuilder();
 421  0
         sb.append("SuppressionRule{");
 422  0
         if (filePath != null) {
 423  0
             sb.append("filePath=").append(filePath).append(',');
 424  
         }
 425  0
         if (sha1 != null) {
 426  0
             sb.append("sha1=").append(sha1).append(',');
 427  
         }
 428  0
         if (gav != null) {
 429  0
             sb.append("gav=").append(gav).append(',');
 430  
         }
 431  0
         if (cpe != null && !cpe.isEmpty()) {
 432  0
             sb.append("cpe={");
 433  0
             for (PropertyType pt : cpe) {
 434  0
                 sb.append(pt).append(',');
 435  0
             }
 436  0
             sb.append('}');
 437  
         }
 438  0
         if (cwe != null && !cwe.isEmpty()) {
 439  0
             sb.append("cwe={");
 440  0
             for (String s : cwe) {
 441  0
                 sb.append(s).append(',');
 442  0
             }
 443  0
             sb.append('}');
 444  
         }
 445  0
         if (cve != null && !cve.isEmpty()) {
 446  0
             sb.append("cve={");
 447  0
             for (String s : cve) {
 448  0
                 sb.append(s).append(',');
 449  0
             }
 450  0
             sb.append('}');
 451  
         }
 452  0
         if (cvssBelow != null && !cvssBelow.isEmpty()) {
 453  0
             sb.append("cvssBelow={");
 454  0
             for (Float s : cvssBelow) {
 455  0
                 sb.append(s).append(',');
 456  0
             }
 457  0
             sb.append('}');
 458  
         }
 459  0
         sb.append('}');
 460  0
         return sb.toString();
 461  
     }
 462  
 }