UNPKG

@pandatix/js-cvss

Version:

JavaScript implementation of the CVSS (Common Vulnerability Scoring System) standard from FIRST.ORG.

201 lines (192 loc) 7.87 kB
import { CVSS40 } from '../src/cvss40'; describe('CVSS v4.0 Section 7 test cases', () => { type TestCase = { name: string vector: string } describe('valid', () => { const testCases: TestCase[] = [ { name: 'specification-example-B', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N', }, { name: 'specification-example-BT', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:A', }, // Following test cases are expected to increase the code coverage naturally. // They were added to the official specification Section 7. // => valid vectors { name: 'CVSS-BT', vector: 'CVSS:4.0/AV:A/AC:H/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L/E:P', }, { name: 'CVSS-BE', vector: 'CVSS:4.0/AV:L/AC:H/AT:N/PR:N/UI:A/VC:N/VI:N/VA:L/SC:H/SI:H/SA:H/CR:H/IR:H/AR:M/MAV:N/MAC:L/MAT:P/MPR:L/MUI:A/MVC:N/MVI:H/MVA:L/MSC:L/MSI:S/MSA:H', }, { name: 'CVSS-B with Supplemental', vector: 'CVSS:4.0/AV:P/AC:H/AT:P/PR:L/UI:P/VC:H/VI:H/VA:H/SC:L/SI:L/SA:L/E:A/S:P/AU:Y/R:A/V:D/RE:L/U:Red', }, { // Changed IR:X and MVC:X for the test purpose name: 'CVSS-BTE with Supplemental', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:U/CR:L/IR:H/AR:L/MAV:A/MAC:H/MAT:N/MPR:N/MUI:P/MVC:H/MVI:N/MVA:H/MSC:N/MSI:L/MSA:S/S:N/AU:N/R:I/V:C/RE:H/U:Green', }, ] testCases.forEach((testCase) => { test(testCase.name, () => { expect(new CVSS40(testCase.vector)) }) }) }) describe('invalid', () => { const testCases: TestCase[] = [ { name: 'AV has no valid value F', vector: 'CVSS:4.0/AV:F/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N', }, { name: 'E defined more than once', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N/E:A/E:X', }, { name: 'ui is not a valid metric abbreviation', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/ui:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N', }, { name: 'CVSS v4.0 prefix is missing', vector: 'AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N', }, { name: 'mandatory VA is missing', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/SC:N/SI:N/SA:N', }, { name: 'fixed ordering is not respected, CVSS-BTE with Supplemental', vector: 'CVSS:4.0/AC:L/AV:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/CR:L/IR:X/AR:L/RE:H/MAV:A/MAC:H/MAT:N/MPR:N/MUI:P/AT:N/MVC:X/MVI:N/MVA:H/MSC:N/MSI:L/MSA:S/E:U/S:N/AU:N/R:I/V:C/U:Green', }, ] testCases.forEach((testCase) => { test(testCase.name, () => { expect(() => { new CVSS40(testCase.vector) }).toThrow(); }) }) }) }); test('CVSS v4.0 vector', () => { // This test ensures it produces metrics in the proper order as defined in CVSS v4.0 // specification Table 23, and it does not export undefined/X (Not Defined) metrics. const input = 'CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:U/CR:L/IR:X/AR:L/MAV:A/MAC:H/MAT:N/MPR:N/MUI:P/MVC:X/MVI:N/MVA:H/MSC:N/MSI:L/MSA:S/S:N/AU:N/R:I/V:C/RE:H/U:Green'; var vec = new CVSS40(input); expect(vec.Vector()).toBe('CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:U/CR:L/AR:L/MAV:A/MAC:H/MAT:N/MPR:N/MUI:P/MVI:N/MVA:H/MSC:N/MSI:L/MSA:S/S:N/AU:N/R:I/V:C/RE:H/U:Green'); }); test('Setter', () => { var vec = new CVSS40(); expect(() => { vec.Set('SA', 'H'); }); expect(() => { vec.Set('invalid', 'invalid'); }).toThrow(); expect(() => { vec.Set('SA', 'invalid'); }).toThrow(); }); describe('Score', () => { type TestCase = { name: string vector: string score: number nomenclature: string }; const testCases: TestCase[] = [ { name: 'full-impact', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H', score: 10.0, nomenclature: 'CVSS-B', }, { name: 'no-impact', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:N/SI:N/SA:N', score: 0.0, nomenclature: 'CVSS-B', }, { name: 'full-system-no-subsequent', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N', score: 9.3, nomenclature: 'CVSS-B', }, { name: 'no-system-full-subsequent', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:H', score: 7.9, nomenclature: 'CVSS-B', }, { // This one verify the "full-impact" test case, with Threat intelligence // information, is effectively lowered. name: 'with-t', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/E:U', score: 9.1, nomenclature: 'CVSS-BT', }, { // This one verify the "full-impact" test case, with Threat intelligence // information and Environmental metrics set to higher constraints raise // the score. name: 'with-e', vector: 'CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/MVI:L/MSA:S', score: 9.8, nomenclature: 'CVSS-BE', }, { // This one only has a funny name :) name: 'smol', vector: 'CVSS:4.0/AV:P/AC:H/AT:P/PR:H/UI:A/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N', score: 1.0, nomenclature: 'CVSS-B', }, // Those ones used Clement as a random source. // It enabled detecting multiple internal issues to the github.com/pandatix/go-cvss // Go module and a typo in the official calculator a week before publication. // Those have been adopted as part of the unit test corpus and should be kept for // regression testing. { name: 'clement-b', vector: 'CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:N/VI:H/VA:H/SC:N/SI:L/SA:L', score: 5.2, nomenclature: 'CVSS-B', }, { name: 'clement-bte', vector: 'CVSS:4.0/AV:L/AC:L/AT:N/PR:L/UI:P/VC:N/VI:H/VA:H/SC:N/SI:L/SA:L/E:P/CR:H/IR:M/AR:H/MAV:A/MAT:P/MPR:N/MVI:H/MVA:N/MSI:H/MSA:N/S:N/V:C/U:Amber', score: 4.7, nomenclature: 'CVSS-BTE', }, { name: 'reg-deptheq3eq6', vector: 'CVSS:4.0/AV:N/AC:H/AT:N/PR:H/UI:N/VC:N/VI:N/VA:H/SC:H/SI:H/SA:H/CR:L/IR:L/AR:L', score: 5.8, nomenclature: 'CVSS-BE', }, { name: 'RedHatProductSecurity/cvss-v4-calculator/#48', vector: 'CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:A/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N/E:U', score: 0.4, nomenclature: 'CVSS-BT' }, ]; testCases.forEach((testCase) => { test(testCase.name, () => { var vec = new CVSS40(testCase.vector); expect(vec.Score()).toBe(testCase.score); expect(vec.Nomenclature()).toBe(testCase.nomenclature); }) }); });