CVSS

 view release on metacpan or  search on metacpan

lib/CVSS/v4.pm  view on Meta::CPAN

        $severity_distance_VC
            = $VC_levels->{$self->M("VC")} - $VC_levels->{$self->extract_value_metric("VC", $max_vector)};
        $severity_distance_VI
            = $VI_levels->{$self->M("VI")} - $VI_levels->{$self->extract_value_metric("VI", $max_vector)};
        $severity_distance_VA
            = $VA_levels->{$self->M("VA")} - $VA_levels->{$self->extract_value_metric("VA", $max_vector)};

        $severity_distance_SC
            = $SC_levels->{$self->M("SC")} - $SC_levels->{$self->extract_value_metric("SC", $max_vector)};
        $severity_distance_SI
            = $SI_levels->{$self->M("SI")} - $SI_levels->{$self->extract_value_metric("SI", $max_vector)};
        $severity_distance_SA
            = $SA_levels->{$self->M("SA")} - $SA_levels->{$self->extract_value_metric("SA", $max_vector)};

        $severity_distance_CR
            = $CR_levels->{$self->M("CR")} - $CR_levels->{$self->extract_value_metric("CR", $max_vector)};
        $severity_distance_IR
            = $IR_levels->{$self->M("IR")} - $IR_levels->{$self->extract_value_metric("IR", $max_vector)};
        $severity_distance_AR
            = $AR_levels->{$self->M("AR")} - $AR_levels->{$self->extract_value_metric("AR", $max_vector)};


        my @check = (
            $severity_distance_AV, $severity_distance_PR, $severity_distance_UI, $severity_distance_AC,
            $severity_distance_AT, $severity_distance_VC, $severity_distance_VI, $severity_distance_VA,
            $severity_distance_SC, $severity_distance_SI, $severity_distance_SA, $severity_distance_CR,
            $severity_distance_IR, $severity_distance_AR
        );

        # if any is less than zero this is not the right max
        foreach (@check) {
            next DISTANCE if ($_ < 0);
        }

        # if multiple maxes exist to reach it it is enough the first one
        last;
    }

    my $step = 0.1;

    my $current_severity_distance_eq1 = ($severity_distance_AV + $severity_distance_PR + $severity_distance_UI);
    my $current_severity_distance_eq2 = ($severity_distance_AC + $severity_distance_AT);
    my $current_severity_distance_eq3eq6
        = (   $severity_distance_VC
            + $severity_distance_VI
            + $severity_distance_VA
            + $severity_distance_CR
            + $severity_distance_IR
            + $severity_distance_AR);
    my $current_severity_distance_eq4 = ($severity_distance_SC + $severity_distance_SI + $severity_distance_SA);
    my $current_severity_distance_eq5 = 0;

    # if the next lower macro score do not exist the result is Nan
    # Rename to maximal scoring difference (aka MSD)
    my $available_distance_eq1    = $value - $score_eq1_next_lower_macro;
    my $available_distance_eq2    = $value - $score_eq2_next_lower_macro;
    my $available_distance_eq3eq6 = $value - $score_eq3eq6_next_lower_macro;
    my $available_distance_eq4    = $value - $score_eq4_next_lower_macro;
    my $available_distance_eq5    = $value - $score_eq5_next_lower_macro;

    my $percent_to_next_eq1_severity    = 0;
    my $percent_to_next_eq2_severity    = 0;
    my $percent_to_next_eq3eq6_severity = 0;
    my $percent_to_next_eq4_severity    = 0;
    my $percent_to_next_eq5_severity    = 0;

    my $normalized_severity_eq1    = 0;
    my $normalized_severity_eq2    = 0;
    my $normalized_severity_eq3eq6 = 0;
    my $normalized_severity_eq4    = 0;
    my $normalized_severity_eq5    = 0;

    # multiply by step because distance is pure
    my $max_severity_eq1    = $MAX_SEVERITY->{eq1}->{$eq1} * $step;
    my $max_severity_eq2    = $MAX_SEVERITY->{eq2}->{$eq2} * $step;
    my $max_severity_eq3eq6 = $MAX_SEVERITY->{eq3eq6}->{$eq3}->{$eq6} * $step;
    my $max_severity_eq4    = $MAX_SEVERITY->{eq4}->{$eq4} * $step;


    #   c. The proportion of the distance is determined by dividing
    #      the severity distance of the to-be-scored vector by the depth
    #      of the MacroVector.
    #   d. The maximal scoring difference is multiplied by the proportion of
    #      distance.

    my $n_existing_lower = 0;

    if (!isNaN($available_distance_eq1) && $available_distance_eq1 >= 0) {
        $n_existing_lower += 1;
        $percent_to_next_eq1_severity = ($current_severity_distance_eq1) / $max_severity_eq1;
        $normalized_severity_eq1      = $available_distance_eq1 * $percent_to_next_eq1_severity;
    }

    if (!isNaN($available_distance_eq2) && $available_distance_eq2 >= 0) {
        $n_existing_lower += 1;
        $percent_to_next_eq2_severity = ($current_severity_distance_eq2) / $max_severity_eq2;
        $normalized_severity_eq2      = $available_distance_eq2 * $percent_to_next_eq2_severity;
    }

    if (!isNaN($available_distance_eq3eq6) && $available_distance_eq3eq6 >= 0) {
        $n_existing_lower += 1;
        $percent_to_next_eq3eq6_severity = ($current_severity_distance_eq3eq6) / $max_severity_eq3eq6;
        $normalized_severity_eq3eq6      = $available_distance_eq3eq6 * $percent_to_next_eq3eq6_severity;
    }

    if (!isNaN($available_distance_eq4) && $available_distance_eq4 >= 0) {
        $n_existing_lower += 1;
        $percent_to_next_eq4_severity = ($current_severity_distance_eq4) / $max_severity_eq4;
        $normalized_severity_eq4      = $available_distance_eq4 * $percent_to_next_eq4_severity;
    }

    if (!isNaN($available_distance_eq5) && $available_distance_eq5 >= 0) {
        $n_existing_lower += 1;
        $percent_to_next_eq5_severity = 0;
        $normalized_severity_eq5      = $available_distance_eq5 * $percent_to_next_eq5_severity;
    }

    my $mean_distance = undef;

    # 2. The mean of the above computed proportional distances is computed.
    if ($n_existing_lower == 0) {
        $mean_distance = 0;
    }
    else {
      # sometimes we need to go up but there is nothing there, or down but there is nothing there so it's a change of 0.
        $mean_distance
            = (   $normalized_severity_eq1
                + $normalized_severity_eq2
                + $normalized_severity_eq3eq6
                + $normalized_severity_eq4
                + $normalized_severity_eq5)
            / $n_existing_lower;
    }

    # /

    DEBUG and say STDERR "-- Value: $value - MeanDistance: $mean_distance";

    # 3. The score of the vector is the score of the MacroVector
    #    (i.e. the score of the highest severity vector) minus the mean
    #    distance so computed. This score is rounded to one decimal place.
    $value -= $mean_distance;

    DEBUG and say STDERR "-- Value $value";

    $value = max(0.0, $value);
    $value = min(10.0, $value);

    my $base_score = sprintf('%.1f', $value);

    DEBUG and say STDERR "-- BaseScore: $base_score ($value)";

    $self->{scores}->{base} = $base_score;

    return 1;

}

sub extract_value_metric {
    my ($self, $metric, $vector_string) = @_;
    my %metrics = split /[\/:]/, $vector_string;
    return $metrics{$metric};
}

sub isNaN { !defined($_[0] <=> 9**9**9) }

sub to_xml {

    my ($self) = @_;

    my $metric_value_names = $self->METRIC_NAMES;

    $self->calculate_score unless ($self->base_score);

    my $version                = $self->version;



( run in 0.481 second using v1.01-cache-2.11-cpan-99c4e6809bf )