All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.owasp.dependencycheck.dependency.Vulnerability Maven / Gradle / Ivy

/*
 * This file is part of dependency-check-core.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Copyright (c) 2012 Jeremy Long. All Rights Reserved.
 */
package org.owasp.dependencycheck.dependency;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.concurrent.NotThreadSafe;

import org.apache.commons.lang3.builder.CompareToBuilder;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.jetbrains.annotations.NotNull;
import org.owasp.dependencycheck.utils.SeverityUtil;

/**
 * Contains the information about a vulnerability.
 *
 * @author Jeremy Long
 */
@NotThreadSafe
public class Vulnerability implements Serializable, Comparable {

    /**
     * An enumeration for the source of vulnerability.
     */
    public enum Source {
        /**
         * National Vulnerability Database.
         */
        NVD,
        /**
         * NPM Public Advisory.
         */
        NPM,
        /**
         * RetireJS.
         */
        RETIREJS,
        /**
         * Sonatype OSS Index.
         */
        OSSINDEX,
        /**
         * Vulnerability from Bundle Audit.
         */
        BUNDLEAUDIT,
        /**
         * Vulnerability from Mix Audit.
         */
        MIXAUDIT
    }

    /**
     * The serial version uid.
     */
    private static final long serialVersionUID = 307319490326651053L;

    /**
     * The name of the vulnerability.
     */
    private String name;
    /**
     * the description of the vulnerability.
     */
    private String description;
    /**
     * Data if the vulnerability is a known exploited vulnerability.
     */
    private org.owasp.dependencycheck.data.knownexploited.json.Vulnerability knownExploitedVulnerability;
    /**
     * References for this vulnerability.
     */
    private final Set references = Collections.synchronizedSet(new HashSet<>());
    /**
     * A set of vulnerable software.
     */
    private final Set vulnerableSoftware = new HashSet<>();
    /**
     * The CWE(s) for the vulnerability.
     */
    private final CweSet cwes = new CweSet();
    /**
     * The severity a {@link Source} has assigned for which a CVSS score is not
     * available. Severity could be anything ranging from 'critical', 'high',
     * 'medium', and 'low', to non-traditional labels like 'major', 'minor', and
     * 'important'.
     */
    private String unscoredSeverity;
    /**
     * The CVSS V2 scoring information.
     */
    private CvssV2 cvssV2;

    /**
     * The CVSS V3 scoring information.
     */
    private CvssV3 cvssV3;

    /**
     * The Vulnerable Software that caused this vulnerability to be flagged.
     */
    private VulnerableSoftware matchedVulnerableSoftware;
    /**
     * Notes about the vulnerability. Generally used for suppression
     * information.
     */
    private String notes;

    /**
     * The source that identified the vulnerability.
     */
    private Source source = null;

    /**
     * Default constructor.
     */
    public Vulnerability() {
        //empty
    }

    /**
     * Constructs a new Vulnerability by its name.
     *
     * @param name the name of the vulnerability
     */
    public Vulnerability(String name) {
        this.name = name;
    }

    /**
     * Get the value of name.
     *
     * @return the value of name
     */
    public String getName() {
        return name;
    }

    /**
     * Set the value of name.
     *
     * @param name new value of name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * Get the value of description.
     *
     * @return the value of description
     */
    public String getDescription() {
        return description;
    }

    /**
     * Set the value of description.
     *
     * @param description new value of description
     */
    public void setDescription(String description) {
        this.description = description;
    }

    /**
     * Get the value of references.
     *
     * @return the value of references
     */
    public Set getReferences() {
        return references;
    }

    /**
     * Returns the list of references. This is primarily used within the
     * generated reports.
     *
     * @param sorted whether the returned list should be sorted
     * @return the list of references
     */
    public List getReferences(boolean sorted) {
        final List sortedRefs = new ArrayList<>(this.references);
        if (sorted) {
            Collections.sort(sortedRefs);
        }
        return sortedRefs;
    }

    /**
     * Adds the references to the collection.
     *
     * @param references a collection of references to add
     */
    public void addReferences(Set references) {
        this.references.addAll(references);
    }

    /**
     * Adds a reference to the references collection.
     *
     * @param ref a reference for the vulnerability
     */
    public void addReference(Reference ref) {
        this.references.add(ref);
    }

    /**
     * Adds a reference.
     *
     * @param referenceSource the source of the reference
     * @param referenceName the referenceName of the reference
     * @param referenceUrl the url of the reference
     */
    public void addReference(String referenceSource, String referenceName, String referenceUrl) {
        final Reference ref = new Reference();
        ref.setSource(referenceSource);
        ref.setName(referenceName);
        ref.setUrl(referenceUrl);
        this.references.add(ref);
    }

    /**
     * Adds information about known exploited vulnerabilities.
     *
     * @param kev the known exploited vulnerability information
     */
    public void setKnownExploitedVulnerability(org.owasp.dependencycheck.data.knownexploited.json.Vulnerability kev) {
        this.knownExploitedVulnerability = kev;
    }
    /**
     * Get the value of knownExploitedVulnerability.
     *
     * @return the value of knownExploitedVulnerability
     */
    public org.owasp.dependencycheck.data.knownexploited.json.Vulnerability getKnownExploitedVulnerability() {
        return knownExploitedVulnerability;
    }
    /**
     * Get the value of vulnerableSoftware.
     *
     * @return the value of vulnerableSoftware
     */
    public Set getVulnerableSoftware() {
        return vulnerableSoftware;
    }

    /**
     * Returns a sorted list of vulnerable software. This is primarily used for
     * display within reports.
     *
     * @param sorted whether or not the list should be sorted
     * @return the list of vulnerable software
     */
    @SuppressWarnings("unchecked")
    public List getVulnerableSoftware(boolean sorted) {
        synchronized (vulnerableSoftware) {
            final List sortedVulnerableSoftware = new ArrayList<>(this.vulnerableSoftware);
            if (sorted) {
                Collections.sort(sortedVulnerableSoftware);
            }
            return sortedVulnerableSoftware;
        }
    }

    /**
     * Adds the vulnerableSoftware to the collection.
     *
     * @param vulnerableSoftware a collection of vulnerable software
     */
    public void addVulnerableSoftware(Set vulnerableSoftware) {
        this.vulnerableSoftware.addAll(vulnerableSoftware);
    }

    /**
     * Adds an entry for vulnerable software.
     *
     * @param software the vulnerable software reference to add
     */
    public void addVulnerableSoftware(VulnerableSoftware software) {
        vulnerableSoftware.add(software);
    }

    /**
     * Get the CVSS V2 scoring information.
     *
     * @return the CVSS V2 scoring information
     */
    public CvssV2 getCvssV2() {
        return cvssV2;
    }

    /**
     * Sets the CVSS V2 scoring information.
     *
     * @param cvssV2 the CVSS V2 scoring information
     */
    public void setCvssV2(CvssV2 cvssV2) {
        this.cvssV2 = cvssV2;
    }

    /**
     * Get the CVSS V3 scoring information.
     *
     * @return the CVSS V3 scoring information
     */
    public CvssV3 getCvssV3() {
        return cvssV3;
    }

    /**
     * Sets the CVSS V3 scoring information.
     *
     * @param cvssV3 the CVSS V3 scoring information
     */
    public void setCvssV3(CvssV3 cvssV3) {
        this.cvssV3 = cvssV3;
    }

    /**
     * Get the set of CWEs.
     *
     * @return the set of CWEs
     */
    public CweSet getCwes() {
        return cwes;
    }

    /**
     * Adds a CWE to the set.
     *
     * @param cwe new CWE to add
     */
    public void addCwe(String cwe) {
        this.cwes.addCwe(cwe);
    }

    /**
     * Retrieves the severity a {@link Source} has assigned for which a CVSS
     * score is not available. Severity could be anything ranging from
     * 'critical', 'high', 'medium', and 'low', to non-traditional labels like
     * 'major', 'minor', and 'important'.
     *
     * @return the un-scored severity
     */
    public String getUnscoredSeverity() {
        return unscoredSeverity;
    }

    /**
     * Sets the severity a {@link Source} has assigned for which a CVSS score is
     * not available. Severity could be anything ranging from 'critical',
     * 'high', 'medium', and 'low', to non-traditional labels like 'major',
     * 'minor', and 'important'.
     *
     * @param unscoredSeverity the un-scored severity
     */
    public void setUnscoredSeverity(String unscoredSeverity) {
        this.unscoredSeverity = unscoredSeverity;
    }

    /**
     * Get the value of notes from suppression notes.
     *
     * @return the value of notes
     */
    public String getNotes() {
        return notes;
    }

    /**
     * Set the value of notes.
     *
     * @param notes new value of notes
     */
    public void setNotes(String notes) {
        this.notes = notes;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null || !(obj instanceof Vulnerability)) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        final Vulnerability other = (Vulnerability) obj;
        return new EqualsBuilder()
                .append(name, other.name)
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(3, 73)
                .append(name)
                .toHashCode();
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Vulnerability ");
        sb.append(this.name);
        sb.append("\nReferences:\n");
        for (Reference reference : getReferences(true)) {
            sb.append("=> ");
            sb.append(reference);
            sb.append("\n");
        }
        sb.append("\nSoftware:\n");

        for (VulnerableSoftware software : getVulnerableSoftware(true)) {
            sb.append("=> ");
            sb.append(software);
            sb.append("\n");
        }
        return sb.toString();
    }

    /**
     * Compares two vulnerabilities.
* Natural order of vulnerabilities is defined as decreasing in severity and * alphabetically by name for equal severity. This way the most severe * issues are listed first in a sorted list. *
* This uses a * {@link #bestEffortSeverityLevelForSorting() best-effort ordering} for * severity as the variety of sources do not guarantee a consistent * availability of standardized severity scores. The bestEffort severity * level estimation will use CVSSv3 baseScore for comparison when available * on both sides. If any of the vulnerabilities does not have a CVSSv3 score * the sort order may be off, but it will be consistent. *
* The ranking (high to low) of severity can be informally represented as * {@code <CVSSv3 critical> >> <Unscored recognized critical> >> * <Unscored unrecognized (assumed Critical)> >> <Score-based comparison for high-or-lower scoring severities with * recognized unscored severities taking the lower bound of the comparable CVSSv3 range> * } * * @param o a vulnerability to be compared * @return a negative integer, zero, or a positive integer as this object is * less than , equal to, or greater than the specified vulnerability * @see #bestEffortSeverityLevelForSorting() */ @Override public int compareTo(@NotNull Vulnerability o) { return new CompareToBuilder() .append(o.bestEffortSeverityLevelForSorting(), this.bestEffortSeverityLevelForSorting()) .append(this.name, o.name) .toComparison(); } /** * Compute a best-effort score for the severity of a vulnerability for the * purpose of sorting. *
* Note that CVSSv2 and CVSSv3 scores are essentially uncomparable. For the * purpose of sorting we nevertheless treat them comparable, with an * exception for the 9.0-10.0 range. For that entire range CVSSv3 is scoring * more severe than CVSSv2, so that the 'CRITICAL' severity is retained to * be reported as the highest severity after sorting on descending severity. *
* For vulnerabilities not scored with a CVSS score we estimate a score from * the severity text. For textual severities assumed or sementically * confirmed to be of a critical nature we assign a value in between the * highest CVSSv2 HIGH and the lowest CVSSv3 CRITICAL severity level. * * @see SeverityUtil#estimatedSortAdjustedCVSSv3(String) * @see SeverityUtil#sortAdjustedCVSSv3BaseScore(float) * @return A float value that allows for best-effort sorting on * vulnerability severity */ private float bestEffortSeverityLevelForSorting() { if (this.cvssV3 != null) { return SeverityUtil.sortAdjustedCVSSv3BaseScore(this.cvssV3.getBaseScore()); } if (this.cvssV2 != null) { return this.cvssV2.getScore(); } return SeverityUtil.estimatedSortAdjustedCVSSv3(this.unscoredSeverity); } /** * The report text to use for highest severity when this issue is ranked * highest. * * @return The string to display in the report, clarifying for unrecognized * unscored severities that critical is assumed. */ public String getHighestSeverityText() { if (this.cvssV3 != null) { return this.cvssV3.getBaseSeverity().toUpperCase(); } if (this.cvssV2 != null) { return this.cvssV2.getSeverity().toUpperCase(); } return SeverityUtil.unscoredToSeveritytext(this.unscoredSeverity).toUpperCase(); } /** * Sets the CPE that caused this vulnerability to be flagged. * * @param software a Vulnerable Software identifier */ public void setMatchedVulnerableSoftware(VulnerableSoftware software) { matchedVulnerableSoftware = software; } /** * Get the value of matchedVulnerableSoftware. * * @return the value of matchedVulnerableSoftware */ public VulnerableSoftware getMatchedVulnerableSoftware() { return matchedVulnerableSoftware; } /** * Returns the source that identified the vulnerability. * * @return the source */ public Source getSource() { return source; } /** * Sets the source that identified the vulnerability. * * @param source the source */ public void setSource(Source source) { this.source = source; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy