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);
}