UNPKG

ssvc

Version:

TypeScript implementation of SSVC (Stakeholder-Specific Vulnerability Categorization). A prioritization framework to triage CVE vulnerabilities as an alternative or compliment to CVSS

514 lines (437 loc) 17.7 kB
import { CoordinatorPublicationPlugin } from './coordinator_publication'; import { DecisionCoordinatorPublication, OutcomeCoordinatorPublication, SupplierInvolvementLevel, ExploitationStatus, PublicValueAddedLevel, ActionType, DecisionPriorityLevel } from './coordinator_publication-generated'; describe('CoordinatorPublicationPlugin', () => { let plugin: CoordinatorPublicationPlugin; beforeEach(() => { plugin = new CoordinatorPublicationPlugin(); }); describe('plugin properties', () => { it('should have correct name', () => { expect(plugin.name).toBe('Coordinator Publication'); }); it('should have correct description', () => { expect(plugin.description).toBe('CERT/CC Coordinator Publication Decision Model'); }); it('should have correct version', () => { expect(plugin.version).toBe('1.0'); }); }); describe('createDecision', () => { it('should create decision with standard parameter names', () => { const decision = plugin.createDecision({ supplier_involvement: 'fix_ready', exploitation: 'active', public_value_added: 'precedence' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should create decision with alternative parameter names', () => { const decision = plugin.createDecision({ supplierInvolvementLevel: 'fix_ready', exploitationStatus: 'active', publicValueAddedLevel: 'precedence' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should handle enum values directly', () => { const decision = plugin.createDecision({ supplier_involvement: SupplierInvolvementLevel.fix_ready, exploitation: ExploitationStatus.active, public_value_added: PublicValueAddedLevel.precedence }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should handle mixed string and enum values', () => { const decision = plugin.createDecision({ supplier_involvement: SupplierInvolvementLevel.fix_ready, exploitation: 'active', public_value_added: PublicValueAddedLevel.precedence }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should handle empty options', () => { const decision = plugin.createDecision({}); expect(() => decision.evaluate()).not.toThrow(); }); }); describe('decision outcomes for various scenarios', () => { it('should return PUBLISH for fix ready scenarios with precedence', () => { const decision = plugin.createDecision({ supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'precedence' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should return DONT_PUBLISH for fix ready with limited value', () => { const decision = plugin.createDecision({ supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'limited' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('dont_publish'); expect(outcome.priority).toBe('low'); }); it('should return PUBLISH for active exploitation with fix ready', () => { const decision = plugin.createDecision({ supplier_involvement: 'fix_ready', exploitation: 'active', public_value_added: 'limited' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should return DONT_PUBLISH for cooperative supplier with limited value and no exploitation', () => { const decision = plugin.createDecision({ supplier_involvement: 'cooperative', exploitation: 'none', public_value_added: 'limited' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('dont_publish'); expect(outcome.priority).toBe('low'); }); it('should return PUBLISH for uncooperative supplier with public PoC', () => { const decision = plugin.createDecision({ supplier_involvement: 'uncooperative_unresponsive', exploitation: 'public_poc', public_value_added: 'limited' }); const outcome = decision.evaluate(); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should handle all supplier involvement levels', () => { // Test FIX_READY let decision = plugin.createDecision({ supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'ampliative' }); expect(decision.evaluate().action).toBe('publish'); // Test COOPERATIVE decision = plugin.createDecision({ supplier_involvement: 'cooperative', exploitation: 'none', public_value_added: 'precedence' }); expect(decision.evaluate().action).toBe('publish'); // Test UNCOOPERATIVE_UNRESPONSIVE decision = plugin.createDecision({ supplier_involvement: 'uncooperative_unresponsive', exploitation: 'active', public_value_added: 'ampliative' }); expect(decision.evaluate().action).toBe('publish'); }); it('should handle all exploitation levels', () => { const baseParams = { supplier_involvement: 'fix_ready', public_value_added: 'precedence' }; // Test NONE let decision = plugin.createDecision({ ...baseParams, exploitation: 'none' }); expect(decision.evaluate().action).toBe('publish'); // Test PUBLIC_POC decision = plugin.createDecision({ ...baseParams, exploitation: 'public_poc' }); expect(decision.evaluate().action).toBe('publish'); // Test ACTIVE decision = plugin.createDecision({ ...baseParams, exploitation: 'active' }); expect(decision.evaluate().action).toBe('publish'); }); it('should handle all public value added levels', () => { const baseParams = { supplier_involvement: 'fix_ready', exploitation: 'none' }; // Test LIMITED let decision = plugin.createDecision({ ...baseParams, public_value_added: 'limited' }); expect(decision.evaluate().action).toBe('dont_publish'); // Test AMPLIATIVE decision = plugin.createDecision({ ...baseParams, public_value_added: 'ampliative' }); expect(decision.evaluate().action).toBe('publish'); // Test PRECEDENCE decision = plugin.createDecision({ ...baseParams, public_value_added: 'precedence' }); expect(decision.evaluate().action).toBe('publish'); }); }); describe('complex decision paths', () => { it('should escalate priority with system exposure', () => { // Compare same scenario with different system exposure levels const baseParams = { supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'limited' }; const smallDecision = plugin.createDecision(baseParams); const openDecision = plugin.createDecision(baseParams); const smallOutcome = smallDecision.evaluate(); const openOutcome = openDecision.evaluate(); expect(smallOutcome.action).toBe('dont_publish'); expect(openOutcome.action).toBe('dont_publish'); }); it('should escalate with human impact', () => { const baseParams = { supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'limited' }; const lowDecision = plugin.createDecision(baseParams); const veryHighDecision = plugin.createDecision(baseParams); const lowOutcome = lowDecision.evaluate(); const veryHighOutcome = veryHighDecision.evaluate(); expect(lowOutcome.action).toBe('dont_publish'); expect(veryHighOutcome.action).toBe('dont_publish'); }); it('should handle active exploitation escalation', () => { const baseParams = { supplier_involvement: 'fix_ready', public_value_added: 'limited' }; const noneDecision = plugin.createDecision({ ...baseParams, exploitation: 'none' }); const activeDecision = plugin.createDecision({ ...baseParams, exploitation: 'active' }); const noneOutcome = noneDecision.evaluate(); const activeOutcome = activeDecision.evaluate(); expect(noneOutcome.action).toBe('dont_publish'); expect(activeOutcome.action).toBe('publish'); }); it('should handle boundary conditions', () => { // Test various combinations to improve coverage const testCases = [ { params: { supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'limited' }, expectedAction: 'dont_publish' }, { params: { supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'ampliative' }, expectedAction: 'publish' }, { params: { supplier_involvement: 'fix_ready', exploitation: 'none', public_value_added: 'precedence' }, expectedAction: 'publish' }, { params: { supplier_involvement: 'cooperative', exploitation: 'none', public_value_added: 'limited' }, expectedAction: 'dont_publish' }, { params: { supplier_involvement: 'cooperative', exploitation: 'none', public_value_added: 'ampliative' }, expectedAction: 'dont_publish' }, { params: { supplier_involvement: 'cooperative', exploitation: 'none', public_value_added: 'precedence' }, expectedAction: 'publish' } ]; testCases.forEach(({ params, expectedAction }) => { const decision = plugin.createDecision(params); const outcome = decision.evaluate(); expect(outcome.action).toBe(expectedAction); }); }); }); }); describe('Generated Coordinator Publication Components', () => { describe('DecisionCoordinatorPublication', () => { it('should initialize with valid parameters', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: SupplierInvolvementLevel.fix_ready, exploitation: ExploitationStatus.active, publicValueAdded: PublicValueAddedLevel.precedence }); expect(decision.supplierInvolvement).toBe(SupplierInvolvementLevel.fix_ready); expect(decision.exploitation).toBe(ExploitationStatus.active); expect(decision.publicValueAdded).toBe(PublicValueAddedLevel.precedence); }); it('should auto-evaluate when all parameters are provided', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: SupplierInvolvementLevel.fix_ready, exploitation: ExploitationStatus.active, publicValueAdded: PublicValueAddedLevel.precedence }); expect(decision.outcome).toBeDefined(); expect(decision.outcome?.action).toBe('publish'); }); it('should convert string values to enums', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: 'fix_ready', exploitation: 'active', publicValueAdded: 'precedence' }); expect(decision.supplierInvolvement).toBe(SupplierInvolvementLevel.fix_ready); expect(decision.exploitation).toBe(ExploitationStatus.active); expect(decision.publicValueAdded).toBe(PublicValueAddedLevel.precedence); }); it('should handle partial parameters without auto-evaluation', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: SupplierInvolvementLevel.fix_ready, exploitation: ExploitationStatus.active // Missing publicValueAdded }); expect(decision.outcome).toBeUndefined(); }); it('should handle invalid enum values', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: 'invalid_value', exploitation: 'invalid_value', publicValueAdded: 'invalid_value' }); expect(decision.supplierInvolvement).toBeUndefined(); expect(decision.exploitation).toBeUndefined(); expect(decision.publicValueAdded).toBeUndefined(); }); it('should handle mixed valid and invalid values', () => { const decision = new DecisionCoordinatorPublication({ supplierInvolvement: SupplierInvolvementLevel.fix_ready, exploitation: 'invalid_value', publicValueAdded: PublicValueAddedLevel.precedence }); expect(decision.supplierInvolvement).toBe(SupplierInvolvementLevel.fix_ready); expect(decision.exploitation).toBeUndefined(); expect(decision.publicValueAdded).toBe(PublicValueAddedLevel.precedence); }); }); describe('OutcomeCoordinatorPublication', () => { it('should create outcome with correct priority mapping', () => { const outcome = new OutcomeCoordinatorPublication(ActionType.publish); expect(outcome.action).toBe('publish'); expect(outcome.priority).toBe('high'); }); it('should handle all action types', () => { const testCases = [ { action: ActionType.dont_publish, expectedPriority: 'low' }, { action: ActionType.publish, expectedPriority: 'high' } ]; testCases.forEach(({ action, expectedPriority }) => { const outcome = new OutcomeCoordinatorPublication(action); expect(outcome.priority).toBe(expectedPriority); }); }); it('should create outcome with correct priority mapping for all actions', () => { // Test publish action const publishOutcome = new OutcomeCoordinatorPublication(ActionType.publish); expect(publishOutcome.action).toBe('publish'); expect(publishOutcome.priority).toBe('high'); // Test dont_publish action const dontPublishOutcome = new OutcomeCoordinatorPublication(ActionType.dont_publish); expect(dontPublishOutcome.action).toBe('dont_publish'); expect(dontPublishOutcome.priority).toBe('low'); }); }); describe('Enums', () => { it('should have correct SupplierInvolvementLevel values', () => { expect(SupplierInvolvementLevel.fix_ready).toBe('fix_ready'); expect(SupplierInvolvementLevel.cooperative).toBe('cooperative'); expect(SupplierInvolvementLevel.uncooperative_unresponsive).toBe('uncooperative_unresponsive'); }); it('should have all SupplierInvolvementLevel values', () => { expect(SupplierInvolvementLevel.fix_ready).toBe('fix_ready'); expect(SupplierInvolvementLevel.cooperative).toBe('cooperative'); expect(SupplierInvolvementLevel.uncooperative_unresponsive).toBe('uncooperative_unresponsive'); }); it('should have correct ExploitationStatus values', () => { expect(ExploitationStatus.none).toBe('none'); expect(ExploitationStatus.public_poc).toBe('public_poc'); expect(ExploitationStatus.active).toBe('active'); }); it('should have all ExploitationStatus values', () => { expect(ExploitationStatus.none).toBe('none'); expect(ExploitationStatus.public_poc).toBe('public_poc'); expect(ExploitationStatus.active).toBe('active'); }); it('should have correct PublicValueAddedLevel values', () => { expect(PublicValueAddedLevel.limited).toBe('limited'); expect(PublicValueAddedLevel.ampliative).toBe('ampliative'); expect(PublicValueAddedLevel.precedence).toBe('precedence'); }); it('should have all PublicValueAddedLevel values', () => { expect(PublicValueAddedLevel.limited).toBe('limited'); expect(PublicValueAddedLevel.ampliative).toBe('ampliative'); expect(PublicValueAddedLevel.precedence).toBe('precedence'); }); it('should have correct ActionType values', () => { expect(ActionType.dont_publish).toBe('dont_publish'); expect(ActionType.publish).toBe('publish'); }); it('should have all ActionType values', () => { expect(ActionType.dont_publish).toBe('dont_publish'); expect(ActionType.publish).toBe('publish'); }); it('should have correct DecisionPriorityLevel values', () => { expect(DecisionPriorityLevel.low).toBe('low'); expect(DecisionPriorityLevel.high).toBe('high'); }); it('should have all DecisionPriorityLevel values', () => { expect(DecisionPriorityLevel.low).toBe('low'); expect(DecisionPriorityLevel.high).toBe('high'); }); }); });