Score()

in default/cvss4/static/cvss40.js [130:266]


    Score() {
        // If the vulnerability does not affect the system AND the subsequent
        // system, there is no reason to try scoring what has no risk and impact.
        if (['VC', 'VI', 'VA', 'SC', 'SI', 'SA'].every((met) => this.getReal(met) == "N")) {
            return 0.0;
        }
        const mv = this.macrovector();
        const eq1 = Number(mv[0]);
        const eq2 = Number(mv[1]);
        const eq3 = Number(mv[2]);
        const eq4 = Number(mv[3]);
        const eq5 = Number(mv[4]);
        const eq6 = Number(mv[5]);
        const eqsv = mvs[mv];
        // Compute EQs next lower MacroVector
        // -> As the lower the EQ value is the bigger, the next lower MacroVector
        //    would be +1 to this one
        // -> If not possible (level+1 > level), it is set to NaN
        let lower = 0;
        let eq1nlm = NaN;
        if (eq1 < 2) { // 2 = maximum level for EQ1
            eq1nlm = mvs[String(eq1 + 1) + String(eq2) + String(eq3) + String(eq4) + String(eq5) + String(eq6)];
            lower++;
        }
        let eq2nlm = NaN;
        if (eq2 < 1) { // 1 = maximum level for EQ2
            eq2nlm = mvs[String(eq1) + String(eq2 + 1) + String(eq3) + String(eq4) + String(eq5) + String(eq6)];
            lower++;
        }
        let eq4nlm = NaN;
        if (eq4 < 2) { // 2 = maximum level for EQ4
            eq4nlm = mvs[String(eq1) + String(eq2) + String(eq3) + String(eq4 + 1) + String(eq5) + String(eq6)];
            lower++;
        }
        let eq5nlm = NaN;
        if (eq5 < 2) { // 2 = maximum level for EQ5
            eq5nlm = mvs[String(eq1) + String(eq2) + String(eq3) + String(eq4) + String(eq5 + 1) + String(eq6)];
            lower++;
        }
        // /!\ As EQ3 and EQ6 are related, we can't do the same as it could produce
        // eq3=2 and eq6=0 which is impossible thus will have a lookup (for EQ3) of 0.
        // This would fail the further computations.
        let eq3eq6nlm = NaN;
        if (eq3 == 1 && eq6 == 1) {
            // 11 -> 21
            eq3eq6nlm = mvs[String(eq1) + String(eq2) + String(eq3 + 1) + String(eq4) + String(eq5) + String(eq6)];
            lower++;
        }
        else if (eq3 == 0 && eq6 == 1) {
            // 01 -> 11
            eq3eq6nlm = mvs[String(eq1) + String(eq2) + String(eq3 + 1) + String(eq4) + String(eq5) + String(eq6)];
            lower++;
        }
        else if (eq3 == 1 && eq6 == 0) {
            // 10 -> 11
            eq3eq6nlm = mvs[String(eq1) + String(eq2) + String(eq3) + String(eq4) + String(eq5) + String(eq6 + 1)];
            lower++;
        }
        else if (eq3 == 0 && eq6 == 0) {
            // 00 -> 01 OR 00 -> 10, takes the bigger
            eq3eq6nlm = Math.max(mvs[String(eq1) + String(eq2) + String(eq3 + 1) + String(eq4) + String(eq5) + String(eq6)], mvs[String(eq1) + String(eq2) + String(eq3) + String(eq4) + String(eq5) + String(eq6 + 1)]);
            lower++;
        }
        // 1.a - Compute maximal scoring (absolute) differences
        const msd = ((nlm) => {
            let msd = Math.abs(nlm - eqsv);
            if (isNaN(msd)) {
                return 0;
            }
            return msd;
        });
        let eq1msd = msd(eq1nlm);
        let eq2msd = msd(eq2nlm);
        let eq3eq6msd = msd(eq3eq6nlm);
        let eq4msd = msd(eq4nlm);
        let eq5msd = msd(eq5nlm);
        // 1.b - Compute the severity distances of the to-be scored vectors
        //       to a highest AND higher severity vector in the MacroVector
        let eq1svdst = 0, eq2svdst = 0, eq3eq6svdst = 0, eq4svdst = 0, eq5svdst = 0;
        for (const eq1mx of highestSeverityVectors[1][eq1]) {
            for (const eq2mx of highestSeverityVectors[2][eq2]) {
                for (const eq3eq6mx of highestSeverityVectors[3][eq3][eq6]) {
                    for (const eq4mx of highestSeverityVectors[4][eq4]) {
                        // Don't need to iterate over eq5, only one dimension is involved
                        // so the highest of a MV's EQ is always unique, such that iterating
                        // over it would lead to nothing but cognitive complexity.
                        const partial = [eq1mx, eq2mx, eq3eq6mx, eq4mx].join('/');
                        // Compute severity distances
                        const avsvdst = CVSS40.severityDistance('AV', this.getReal('AV'), CVSS40.getValue(partial, 'AV'));
                        const prsvdst = CVSS40.severityDistance('PR', this.getReal('PR'), CVSS40.getValue(partial, 'PR'));
                        const uisvdst = CVSS40.severityDistance('UI', this.getReal('UI'), CVSS40.getValue(partial, 'UI'));
                        const acsvdst = CVSS40.severityDistance('AC', this.getReal('AC'), CVSS40.getValue(partial, 'AC'));
                        const atsvdst = CVSS40.severityDistance('AT', this.getReal('AT'), CVSS40.getValue(partial, 'AT'));
                        const vcsvdst = CVSS40.severityDistance('VC', this.getReal('VC'), CVSS40.getValue(partial, 'VC'));
                        const visvdst = CVSS40.severityDistance('VI', this.getReal('VI'), CVSS40.getValue(partial, 'VI'));
                        const vasvdst = CVSS40.severityDistance('VA', this.getReal('VA'), CVSS40.getValue(partial, 'VA'));
                        const scsvdst = CVSS40.severityDistance('SC', this.getReal('SC'), CVSS40.getValue(partial, 'SC'));
                        const sisvdst = CVSS40.severityDistance('SI', this.getReal('SI'), CVSS40.getValue(partial, 'SI'));
                        const sasvdst = CVSS40.severityDistance('SA', this.getReal('SA'), CVSS40.getValue(partial, 'SA'));
                        const crsvdst = CVSS40.severityDistance('CR', this.getReal('CR'), CVSS40.getValue(partial, 'CR'));
                        const irsvdst = CVSS40.severityDistance('IR', this.getReal('IR'), CVSS40.getValue(partial, 'IR'));
                        const arsvdst = CVSS40.severityDistance('AR', this.getReal('AR'), CVSS40.getValue(partial, 'AR'));
                        if ([avsvdst, prsvdst, uisvdst, acsvdst, atsvdst, vcsvdst, visvdst, vasvdst, scsvdst, sisvdst, sasvdst, crsvdst, irsvdst, arsvdst].some((met) => met < 0)) {
                            continue;
                        }
                        eq1svdst = avsvdst + prsvdst + uisvdst;
                        eq2svdst = acsvdst + atsvdst;
                        eq3eq6svdst = vcsvdst + visvdst + vasvdst + crsvdst + irsvdst + arsvdst;
                        eq4svdst = scsvdst + sisvdst + sasvdst;
                        // Don't need to compute E severity distance as the maximum will
                        // always remain the same due to only 1 dimension involved in EQ5.
                        eq5svdst = 0;
                        break;
                    }
                }
            }
        }
        // 1.c - Compute proportion of the distance
        const eq1prop = eq1svdst / (depth[1][eq1] + 1);
        const eq2prop = eq2svdst / (depth[2][eq2] + 1);
        const eq3eq6prop = eq3eq6svdst / (depth[3][eq3][eq6] + 1);
        const eq4prop = eq4svdst / (depth[4][eq4] + 1);
        const eq5prop = eq5svdst / (depth[5][eq5] + 1);
        // 1.d - Multiply maximal scoring diff. by prop. of distance
        eq1msd *= eq1prop;
        eq2msd *= eq2prop;
        eq3eq6msd *= eq3eq6prop;
        eq4msd *= eq4prop;
        eq5msd *= eq5prop;
        // 2 - Compute mean
        let mean = 0;
        if (lower != 0) {
            mean = (eq1msd + eq2msd + eq3eq6msd + eq4msd + eq5msd) / lower;
        }
        // 3 - Compute score
        return CVSS40.roundup(eqsv - mean);
    }