UNPKG

@turingpointde/cvss.js

Version:

A tiny library to work with cvss vectors

589 lines (520 loc) 17.5 kB
import { CVSS } from "../lib/cvss"; describe("Score Tests", () => { it("Should return the score", () => { // These are just some example test cases. // TODO: clean this up and test more systematically. const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:N/I:L/A:L"); expect(vector.getScore()).toBe(4.4); const vector2 = CVSS("CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:N/I:L/A:N"); expect(vector2.getScore()).toBe(4.0); const vector3 = CVSS("CVSS:3.0/AV:A/AC:H/PR:N/UI:N/S:U/C:H/I:L/A:H"); expect(vector3.getScore()).toBe(7.1); const vector4 = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N"); expect(vector4.getScore()).toBe(8.2); const vector6 = CVSS("CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H"); expect(vector6.getScore()).toBe(9.6); expect(vector6.getTemporalScore()).toBe(9.6); expect(vector6.getEnvironmentalScore()).toBe(9.7); const vector5 = CVSS({ A: "N", AC: "L", AV: "N", C: "L", CVSS: "3.0", E: "X", I: "H", PR: "N", RC: "X", RL: "X", S: "U", UI: "N" }); expect(vector5.getScore()).toBe(8.2); }); }); describe("Version Tests", () => { it("Should return the Version", () => { const vector5 = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); expect(vector5.getVersion()).toBe("3.0"); const vector6 = CVSS("CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); expect(vector6.getVersion()).toBe("3.1"); const vector7 = () => { CVSS("CVSS:xyz/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(vector7).toThrow("The vector version is not valid"); const vector8 = () => { CVSS("CVSS:/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(vector8).toThrow("The vector version is not valid"); }); }); describe("Temporal Tests", () => { it("Should return the temporal score", () => { const vector5 = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); expect(vector5.getTemporalScore()).toBe(4.7); const vector6 = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:F/RL:U/RC:X"); expect(vector6.getTemporalScore()).toBe(5.4); const vector7 = CVSS({ A: "N", AC: "L", AV: "N", C: "L", CVSS: "3.0", E: "X", I: "H", PR: "N", RC: "X", RL: "X", S: "U", UI: "N" }); expect(vector7.getTemporalScore()).toBe(8.2); }); }); describe("Environmental score tests", () => { it("Should return the environmental score", () => { const vector = CVSS( "CVSS:3.0/AV:L/AC:H/PR:N/UI:R/S:U/C:L/I:L/A:N/CR:M/IR:H/AR:M/MAV:N/MAC:H/MPR:L/MUI:N/MS:C/MC:N/MI:L/MA:L" ); expect(vector.getEnvironmentalScore()).toBe(5.6); const vector2 = CVSS( "CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:L/E:P/RL:T/RC:U/CR:H/IR:M/AR:M/MAV:A/MAC:H/MPR:N/MUI:N/MS:U/MC:H/MI:H/MA:H" ); expect(vector2.getEnvironmentalScore()).toBe(6.3); const vector3 = CVSS( "CVSS:3.0/AV:P/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:H/E:H/RL:U/RC:R/CR:M/IR:M/AR:M/MAV:N/MAC:H/MPR:N/MUI:N/MS:C/MC:N/MI:N/MA:L" ); expect(vector3.getEnvironmentalScore()).toBe(3.9); const vector4 = CVSS( "CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:H/RL:T/CR:L/IR:M/AR:H/MAV:N/MAC:L/MPR:N/MUI:R/MS:C/MC:H/MI:H/MA:H" ); expect(vector4.getEnvironmentalScore()).toBe(9.3); const vector5 = CVSS( "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:P/RL:O/IR:M/MAV:A/MPR:N/MI:L" ); expect(vector5.getEnvironmentalScore()).toBe(4.9); const vector6 = CVSS( "CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L/CR:H/IR:H/MS:C/MC:H/MI:H/MA:H" ); expect(vector6.getEnvironmentalScore()).toBe(8.0); const vector7 = CVSS( "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:L/I:L/A:L/CR:H/IR:H/MS:C/MC:H/MI:H/MA:H" ); expect(vector7.getEnvironmentalScore()).toBe(8.1); const vector8 = CVSS( "CVSS:3.0/AV:N/AC:H/PR:N/UI:N/S:C/C:L/I:L/A:L/E:X/RL:X/RC:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X" ); expect(vector8.getEnvironmentalScore()).toBe(6.5); }); it("Should return base score when all environmental metrics are not defined", () => { const vector = CVSS( "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:X/RL:X/RC:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X" ); expect(vector.getEnvironmentalScore()).toBe(vector.getScore()); }); }); describe("Rating Tests", () => { it("Should return 'None' if the vector's score is 0", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N"); expect(vector.getScore()).toBe(0); expect(vector.getRating()).toBe("None"); expect(vector.getTemporalRating()).toBe("None"); expect(vector.getEnvironmentalRating()).toBe("None"); }); it("Should return 'Low' if the vector's score is >= 0.1 and <= 3.9", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:N/I:L/A:N"); expect(vector.getScore()).toBe(2); expect(vector.getRating()).toBe("Low"); expect(vector.getTemporalRating()).toBe("Low"); expect(vector.getEnvironmentalRating()).toBe("Low"); }); it("Should return 'Medium' if the vector's score is >= 4.0 and <= 6.9", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:N/A:N"); expect(vector.getScore()).toBe(4.2); expect(vector.getRating()).toBe("Medium"); expect(vector.getTemporalRating()).toBe("Medium"); expect(vector.getEnvironmentalRating()).toBe("Medium"); }); it("Should return 'High' if the vector's score is >= 7.0 and <= 8.9", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H"); expect(vector.getScore()).toBe(8.8); expect(vector.getRating()).toBe("High"); expect(vector.getTemporalRating()).toBe("High"); expect(vector.getEnvironmentalRating()).toBe("High"); }); it("Should return 'Critical' if the vector's score is >= 9.0 and <= 10.0", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"); expect(vector.getScore()).toBe(9.8); expect(vector.getRating()).toBe("Critical"); expect(vector.getTemporalRating()).toBe("Critical"); expect(vector.getEnvironmentalRating()).toBe("Critical"); }); it("Should be able to discern individual ratings (base, temp, env) even if these don't match", () => { const vector = CVSS( "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N/E:U/RL:O/RC:U/CR:H/IR:H/AR:H/MAV:N/MAC:L/MPR:N/MUI:N/MS:U/MC:H/MI:H/MA:H" ); expect(vector.getScore()).toBe(4.3); expect(vector.getRating()).toBe("Medium"); expect(vector.getTemporalScore()).toBe(3.5); expect(vector.getTemporalRating()).toBe("Low"); expect(vector.getEnvironmentalScore()).toBe(7.8); expect(vector.getEnvironmentalRating()).toBe("High"); }); }); describe("Vector Object Tests", () => { it("Should return vector object with same key-value pairs", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"); expect(vector.getScore()).toBe(9.8); expect(vector.getVectorObject()).toEqual({ CVSS: "3.0", AV: "N", AC: "L", PR: "N", UI: "N", S: "U", C: "H", I: "H", A: "H", E: "X", RL: "X", RC: "X", CR: "X", IR: "X", AR: "X", MAV: "X", MAC: "X", MPR: "X", MUI: "X", MS: "X", MC: "X", MI: "X", MA: "X" }); }); it("Should return vector object with same key-value pairs", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:N/A:N"); expect(vector.getScore()).toBe(4.2); expect(vector.getVectorObject()).toEqual({ CVSS: "3.0", AV: "N", AC: "H", PR: "H", UI: "R", S: "U", C: "H", I: "N", A: "N", E: "X", RL: "X", RC: "X", CR: "X", IR: "X", AR: "X", MAV: "X", MAC: "X", MPR: "X", MUI: "X", MS: "X", MC: "X", MI: "X", MA: "X" }); }); }); describe("Check vector", () => { it("must return invalid format for the vector", () => { const t1 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:TRC:R"); }; expect(t1).toThrow("The vector format is not valid!"); const t2 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:F/RL:U/RC:X/"); }; expect(t2).toThrow("The vector format is not valid!"); const t3 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:F/RL:U/RC:X/test"); }; expect(t3).toThrow("The vector format is not valid!"); }); it("must return repeated values in the vector", () => { const t1 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R/RC:R"); }; expect(t1).toThrow("The vector format is not valid!"); const t2 = () => { CVSS("CVSS:3.0/AV:N/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(t2).toThrow("The vector format is not valid!"); const t3 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(t3).toThrow("The vector format is not valid!"); }); it("checks if mandatory values have been passed", () => { const t1 = () => { CVSS("CVSS:3.0/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(t1).toThrow("The vector format is not valid!"); const t2 = () => { CVSS("CVSS:3.0/AV:N/AC:H/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); }; expect(t2).toThrow("The vector format is not valid!"); const t3 = () => { CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/E:U/RL:T/RC:R"); }; expect(t3).toThrow("The vector format is not valid!"); }); it("all tests must have the vectors in valid format", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); expect(vector.isValid).toBe(true); const vector2 = CVSS("CVSS:3.0/AV:L/AC:H/PR:L/UI:R/S:C/C:L/I:L/A:L/E:U/RL:T/RC:R"); expect(vector2.isValid).toBe(true); const vector3 = CVSS("CVSS:3.0/AV:N/AC:H/PR:L/UI:R/S:C/C:L/I:H/A:L/E:U/RL:T/RC:R"); expect(vector3.isValid).toBe(true); }); }); describe("Detailed Vector Object Tests", () => { it("Should return detailed vector object with same key-value pairs and extra relevant values", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"); expect(vector.getScore()).toBe(9.8); expect(vector.getDetailedVectorObject()).toEqual({ CVSS: "3.0", metrics: { AV: { name: "Attack Vector", abbr: "AV", fullName: "Attack Vector (AV)", value: "Network", valueAbbr: "N" }, AC: { name: "Attack Complexity", abbr: "AC", fullName: "Attack Complexity (AC)", value: "Low", valueAbbr: "L" }, PR: { name: "Privileges Required", abbr: "PR", fullName: "Privileges Required (PR)", value: "None", valueAbbr: "N" }, UI: { name: "User Interaction", abbr: "UI", fullName: "User Interaction (UI)", value: "None", valueAbbr: "N" }, S: { name: "Scope", abbr: "S", fullName: "Scope (S)", value: "Unchanged", valueAbbr: "U" }, C: { name: "Confidentiality", abbr: "C", fullName: "Confidentiality (C)", value: "High", valueAbbr: "H" }, I: { name: "Integrity", abbr: "I", fullName: "Integrity (I)", value: "High", valueAbbr: "H" }, A: { name: "Availability", abbr: "A", fullName: "Availability (A)", value: "High", valueAbbr: "H" } } }); }); it("Should return detailed vector object with same key-value pairs and extra relevant values", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:N/A:N"); expect(vector.getScore()).toBe(4.2); expect(vector.getDetailedVectorObject()).toEqual({ CVSS: "3.0", metrics: { AV: { name: "Attack Vector", abbr: "AV", fullName: "Attack Vector (AV)", value: "Network", valueAbbr: "N" }, AC: { name: "Attack Complexity", abbr: "AC", fullName: "Attack Complexity (AC)", value: "High", valueAbbr: "H" }, PR: { name: "Privileges Required", abbr: "PR", fullName: "Privileges Required (PR)", value: "High", valueAbbr: "H" }, UI: { name: "User Interaction", abbr: "UI", fullName: "User Interaction (UI)", value: "Required", valueAbbr: "R" }, S: { name: "Scope", abbr: "S", fullName: "Scope (S)", value: "Unchanged", valueAbbr: "U" }, C: { name: "Confidentiality", abbr: "C", fullName: "Confidentiality (C)", value: "High", valueAbbr: "H" }, I: { name: "Integrity", abbr: "I", fullName: "Integrity (I)", value: "None", valueAbbr: "N" }, A: { name: "Availability", abbr: "A", fullName: "Availability (A)", value: "None", valueAbbr: "N" } } }); }); }); describe("Create vector from object", () => { it("Should return the vector as string", () => { const vectorObject = { CVSS: "3.0", AV: "N", AC: "H", PR: "H", UI: "R", S: "U", C: "H", I: "N", A: "N" } as const; expect(CVSS(vectorObject).vector).toBe("CVSS:3.0/AV:N/AC:H/PR:H/UI:R/S:U/C:H/I:N/A:N"); const vectorObject1 = { A: "N", AC: "L", AV: "N", C: "L", CVSS: "3.0", E: "X", I: "H", PR: "N", RC: "X", RL: "X", S: "U", UI: "N" } as const; expect(CVSS(vectorObject1).vector).toBe( "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:X/RL:X/RC:X" ); }); it("Should calculate the correct scores", () => { const vectorObject = { CVSS: "3.0", AV: "N", AC: "H", PR: "L", UI: "R", S: "U", C: "H", I: "H", A: "H", RL: "T", CR: "L", IR: "M", AR: "H", MAV: "N", MAC: "L", MPR: "N", MUI: "R", MS: "C", MC: "H", MI: "H", MA: "H" } as const; expect(CVSS(vectorObject).getScore()).toBe(7.1); expect(CVSS(vectorObject).getTemporalScore()).toBe(6.9); expect(CVSS(vectorObject).getEnvironmentalScore()).toBe(9.3); }); }); describe("Clean Vector String Test", () => { it("Should return the clean vector as string", () => { expect( CVSS( "CVSS:3.0/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:N/E:P/RL:W/RC:X/CR:X/IR:X/AR:M/MAV:A/MAC:X/MPR:X/MUI:N/MS:X/MC:X/MI:X/MA:X" ).getCleanVectorString() ).toBe("CVSS:3.0/AV:L/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:N/E:P/RL:W/AR:M/MAV:A/MUI:N"); expect( CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:X/RL:X/RC:X").getCleanVectorString() ).toBe("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N"); expect( CVSS( "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/E:X/RL:X/RC:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MPR:X/MUI:X/MS:X/MC:X/MI:X/MA:X" ).getCleanVectorString() ).toBe("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N"); }); }); describe("Update Vector Value Test", () => { it("Should return the updated vector as string", () => { expect( CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N/RL:X/RC:X").updateVectorValue("AV", "L") ).toBe("CVSS:3.0/AV:L/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N"); }); }); describe("Impact Sub Score Tests", () => { it("Should return the impact sub score equal 6.0", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"); expect(vector.getImpactSubScore()).toBe(6.0); }); it("Should return the impact sub score equal 5.9", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"); expect(vector.getImpactSubScore()).toBe(5.9); }); it("Should return the impact sub score equal 0", () => { const vector = CVSS("CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N"); expect(vector.getImpactSubScore()).toBe(0); }); }); describe("Exploitability sub score Tests", () => { it("Should return the Exploitability sub score equal 3.9", () => { const vector = CVSS("CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H"); expect(vector.getExploitabilitySubScore()).toBe(3.9); }); it("Should return the Exploitability sub score equal 0.9", () => { const vector = CVSS("CVSS:3.0/AV:A/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:H"); expect(vector.getExploitabilitySubScore()).toBe(0.9); }); it("Should return the Exploitability sub score equal 0.1", () => { const vector = CVSS("CVSS:3.0/AV:P/AC:H/PR:H/UI:R/S:U/C:N/I:N/A:N"); expect(vector.getExploitabilitySubScore()).toBe(0.1); }); });