diff --git a/src/enums/componentType.ts b/src/enums/componentType.ts index 8673f1418..a5d52e989 100644 --- a/src/enums/componentType.ts +++ b/src/enums/componentType.ts @@ -22,8 +22,12 @@ export enum ComponentType { Framework = 'framework', Library = 'library', Container = 'container', + Platform = 'platform', OperatingSystem = 'operating-system', Device = 'device', + DeviceDriver = 'device-driver', Firmware = 'firmware', File = 'file', + MachineLearningModel = 'machine-learning-model', + Data = 'data', } diff --git a/src/enums/externalReferenceType.ts b/src/enums/externalReferenceType.ts index 388fe0bb7..82942ef99 100644 --- a/src/enums/externalReferenceType.ts +++ b/src/enums/externalReferenceType.ts @@ -29,9 +29,32 @@ export enum ExternalReferenceType { Documentation = 'documentation', Support = 'support', Distribution = 'distribution', + DistributionIntake = 'distribution-intake', License = 'license', BuildMeta = 'build-meta', BuildSystem = 'build-system', ReleaseNotes = 'release-notes', + SecurityContact = 'security-contact', + ModelCard = 'model-card', + Log = 'log', + Configuration = 'configuration', + Evidence = 'evidence', + Formulation = 'formulation', + Attestation = 'attestation', + ThreatModel = 'threat-model', + AdversaryModel = 'adversary-model', + RiskAssessment = 'risk-assessment', + VulnerabilityAssertion = 'vulnerability-assertion', + ExploitabilityStatement = 'exploitability-statement', + PentestReport = 'pentest-report', + StaticAnalysisReport = 'static-analysis-report', + DynamicAnalysisReport = 'dynamic-analysis-report', + RuntimeAnalysisReport = 'runtime-analysis-report', + ComponentAnalysisReport = 'component-analysis-report', + MaturityReport = 'maturity-report', + CertificationReport = 'certification-report', + CodifiedInfrastructure = 'codified-infrastructure', + QualityMetrics = 'quality-metrics', + POAM = 'poam', Other = 'other', } diff --git a/src/enums/vulnerability/ratingMethod.ts b/src/enums/vulnerability/ratingMethod.ts index 76eb41a13..cb226d3b4 100644 --- a/src/enums/vulnerability/ratingMethod.ts +++ b/src/enums/vulnerability/ratingMethod.ts @@ -21,13 +21,18 @@ Copyright (c) OWASP Foundation. All Rights Reserved. * Specifies the severity or risk scoring methodology or standard used. */ export enum RatingMethod { - /** [CVSS v2 standard](https://www.first.org/cvss/v2/) */ + /** CVSSv2 - [Common Vulnerability Scoring System v2](https://www.first.org/cvss/v2/) */ CVSSv2 = 'CVSSv2', - /** [CVSS v3.0 standard](https://www.first.org/cvss/v3-0/) */ + /** CVSSv3 - [Common Vulnerability Scoring System v3](https://www.first.org/cvss/v3-0/) */ CVSSv3 = 'CVSSv3', - /** [CVSS v3.1 standard](https://www.first.org/cvss/v3-1/) */ + /** CVSSv31 - [Common Vulnerability Scoring System v3.1](https://www.first.org/cvss/v3-1/) */ CVSSv31 = 'CVSSv31', - /** [OWASP Risk Rating](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology) */ + /** CVSSv4 - [Common Vulnerability Scoring System v4](https://www.first.org/cvss/v4-0/) */ + CVSSv4 = 'CVSSv4', + /** OWASP - [OWASP Risk Rating Methodology](https://owasp.org/www-community/OWASP_Risk_Rating_Methodology) */ OWASP = 'OWASP', + /** SSVC - [Stakeholder Specific Vulnerability Categorization](https://github.com/CERTCC/SSVC) (all versions) */ + SSVC = 'SSVC', + /** any other */ Other = 'other', } diff --git a/src/spec.ts b/src/spec.ts index 79952f548..d0438e03a 100644 --- a/src/spec.ts +++ b/src/spec.ts @@ -17,7 +17,7 @@ SPDX-License-Identifier: Apache-2.0 Copyright (c) OWASP Foundation. All Rights Reserved. */ -import { ComponentType, ExternalReferenceType, HashAlgorithm } from './enums' +import { ComponentType, ExternalReferenceType, HashAlgorithm, Vulnerability } from './enums' import type { HashContent } from './models' export enum Version { @@ -49,6 +49,7 @@ export interface Protocol { requiresComponentVersion: boolean supportsProperties: (model: any) => boolean supportsVulnerabilities: boolean + supportsVulnerabilityRatingMethod: (rm: Vulnerability.RatingMethod | any) => boolean supportsComponentEvidence: boolean } @@ -63,6 +64,7 @@ class Spec implements Protocol { readonly #hashAlgorithms: ReadonlySet readonly #hashValuePattern: RegExp readonly #externalReferenceTypes: ReadonlySet + readonly #vulnerabilityRatingMethods: ReadonlySet readonly #supportsDependencyGraph: boolean readonly #supportsToolReferences: boolean readonly #requiresComponentVersion: boolean @@ -82,6 +84,7 @@ class Spec implements Protocol { requiresComponentVersion: boolean, supportsProperties: boolean, supportsVulnerabilities: boolean, + vulnerabilityRatingMethods: Iterable, supportsComponentEvidence: boolean ) { this.#version = version @@ -95,6 +98,7 @@ class Spec implements Protocol { this.#requiresComponentVersion = requiresComponentVersion this.#supportsProperties = supportsProperties this.#supportsVulnerabilities = supportsVulnerabilities + this.#vulnerabilityRatingMethods = new Set(vulnerabilityRatingMethods) this.#supportsComponentEvidence = supportsComponentEvidence } @@ -144,6 +148,10 @@ class Spec implements Protocol { return this.#supportsVulnerabilities } + supportsVulnerabilityRatingMethod (rm: Vulnerability.RatingMethod | any): boolean { + return this.#vulnerabilityRatingMethods.has(rm) + } + get supportsComponentEvidence (): boolean { return this.#supportsComponentEvidence } @@ -203,6 +211,7 @@ export const Spec1dot2: Readonly = Object.freeze(new Spec( true, false, false, + [], false )) @@ -260,6 +269,7 @@ export const Spec1dot3: Readonly = Object.freeze(new Spec( true, true, false, + [], true )) @@ -318,6 +328,13 @@ export const Spec1dot4: Readonly = Object.freeze(new Spec( false, true, true, + [ + Vulnerability.RatingMethod.CVSSv2, + Vulnerability.RatingMethod.CVSSv3, + Vulnerability.RatingMethod.CVSSv31, + Vulnerability.RatingMethod.OWASP, + Vulnerability.RatingMethod.Other + ], true )) @@ -333,10 +350,14 @@ export const Spec1dot5: Readonly = Object.freeze(new Spec( ComponentType.Framework, ComponentType.Library, ComponentType.Container, + ComponentType.Platform, ComponentType.OperatingSystem, ComponentType.Device, + ComponentType.DeviceDriver, ComponentType.Firmware, - ComponentType.File + ComponentType.File, + ComponentType.MachineLearningModel, + ComponentType.Data ], [ HashAlgorithm.MD5, @@ -365,10 +386,33 @@ export const Spec1dot5: Readonly = Object.freeze(new Spec( ExternalReferenceType.Documentation, ExternalReferenceType.Support, ExternalReferenceType.Distribution, + ExternalReferenceType.DistributionIntake, ExternalReferenceType.License, ExternalReferenceType.BuildMeta, ExternalReferenceType.BuildSystem, ExternalReferenceType.ReleaseNotes, + ExternalReferenceType.SecurityContact, + ExternalReferenceType.ModelCard, + ExternalReferenceType.Log, + ExternalReferenceType.Configuration, + ExternalReferenceType.Evidence, + ExternalReferenceType.Formulation, + ExternalReferenceType.Attestation, + ExternalReferenceType.ThreatModel, + ExternalReferenceType.AdversaryModel, + ExternalReferenceType.RiskAssessment, + ExternalReferenceType.VulnerabilityAssertion, + ExternalReferenceType.ExploitabilityStatement, + ExternalReferenceType.PentestReport, + ExternalReferenceType.StaticAnalysisReport, + ExternalReferenceType.DynamicAnalysisReport, + ExternalReferenceType.RuntimeAnalysisReport, + ExternalReferenceType.ComponentAnalysisReport, + ExternalReferenceType.MaturityReport, + ExternalReferenceType.CertificationReport, + ExternalReferenceType.CodifiedInfrastructure, + ExternalReferenceType.QualityMetrics, + ExternalReferenceType.POAM, ExternalReferenceType.Other ], true, @@ -376,6 +420,15 @@ export const Spec1dot5: Readonly = Object.freeze(new Spec( false, true, true, + [ + Vulnerability.RatingMethod.CVSSv2, + Vulnerability.RatingMethod.CVSSv3, + Vulnerability.RatingMethod.CVSSv31, + Vulnerability.RatingMethod.CVSSv4, + Vulnerability.RatingMethod.OWASP, + Vulnerability.RatingMethod.SSVC, + Vulnerability.RatingMethod.Other + ], true )) diff --git a/tests/functional/Enums.ComponentType.spec.js b/tests/functional/Enums.ComponentType.spec.js index 0155663e5..babca2102 100644 --- a/tests/functional/Enums.ComponentType.spec.js +++ b/tests/functional/Enums.ComponentType.spec.js @@ -48,13 +48,13 @@ suite('ComponentType enum', () => { assert.strictEqual(ComponentType[expectedName], enumValue) ) test(`is supported: ${enumValue}`, () => - assert.ok(SpecVersionDict[specVersion]?.supportsComponentType(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsComponentType(enumValue), true) ) }) const unknownValues = Object.values(ComponentType).filter(enumValue => !knownValues.includes(enumValue)) unknownValues.forEach(enumValue => test(`not supported: ${enumValue}`, () => - assert.ok(!SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue), false) ) ) }) diff --git a/tests/functional/Enums.ExternalReferenceType.spec.js b/tests/functional/Enums.ExternalReferenceType.spec.js index 548a32ac9..348426368 100644 --- a/tests/functional/Enums.ExternalReferenceType.spec.js +++ b/tests/functional/Enums.ExternalReferenceType.spec.js @@ -47,6 +47,7 @@ suite('ExternalReferenceType enum', () => { switch (enumValue) { case 'vcs': case 'bom': + case 'poam': expectedName = enumValue.toUpperCase() break } @@ -54,13 +55,13 @@ suite('ExternalReferenceType enum', () => { assert.strictEqual(ExternalReferenceType[expectedName], enumValue) ) test(`is supported: ${enumValue}`, () => - assert.ok(SpecVersionDict[specVersion]?.supportsExternalReferenceType(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsExternalReferenceType(enumValue), true) ) }) const unknownValues = Object.values(ExternalReferenceType).filter(enumValue => !knownValues.includes(enumValue)) unknownValues.forEach(enumValue => test(`not supported: ${enumValue}`, () => - assert.ok(!SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue), false) ) ) }) diff --git a/tests/functional/Enums.HashAlogorithms.spec.js b/tests/functional/Enums.HashAlogorithms.spec.js index 034de511f..21ac4a4eb 100644 --- a/tests/functional/Enums.HashAlogorithms.spec.js +++ b/tests/functional/Enums.HashAlogorithms.spec.js @@ -48,13 +48,13 @@ suite('HashAlgorithm enum', () => { assert.strictEqual(HashAlgorithm[expectedName], enumValue) ) test(`is supported: ${enumValue}`, () => - assert.ok(SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue), true) ) }) const unknownValues = Object.values(HashAlgorithm).filter(enumValue => !knownValues.includes(enumValue)) unknownValues.forEach(enumValue => test(`not supported: ${enumValue}`, () => - assert.ok(!SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue)) + assert.strictEqual(SpecVersionDict[specVersion]?.supportsHashAlgorithm(enumValue), false) ) ) }) diff --git a/tests/functional/Enums.Vulnerability.RatingMethod.spec.js b/tests/functional/Enums.Vulnerability.RatingMethod.spec.js index ff9831cdd..b4371d6d9 100644 --- a/tests/functional/Enums.Vulnerability.RatingMethod.spec.js +++ b/tests/functional/Enums.Vulnerability.RatingMethod.spec.js @@ -25,7 +25,7 @@ const { upperCamelCase } = require('../_helpers/stringFunctions') const { Enums: { Vulnerability: { RatingMethod } }, - Spec: { Version }, + Spec: { Version, SpecVersionDict }, _Resources: { FILES: { CDX: { JSON_SCHEMA: CDX_JSON_SCHEMA } } } } = require('../../') @@ -37,13 +37,22 @@ suite('Vulnerability.RatingMethod enum', () => { specVersions.forEach(specVersion => suite(`from spec ${specVersion}`, () => { - const specValues = getSpecEnum(CDX_JSON_SCHEMA[specVersion], 'scoreMethod') - specValues.forEach(enumValue => { + const knownValues = getSpecEnum(CDX_JSON_SCHEMA[specVersion], 'scoreMethod') + knownValues.forEach(enumValue => { const expectedName = upperCamelCase(enumValue) test(`is known: ${expectedName} -> ${enumValue}`, () => assert.strictEqual(RatingMethod[expectedName], enumValue) ) + test(`is supported: ${enumValue}`, () => + assert.strictEqual(SpecVersionDict[specVersion]?.supportsVulnerabilityRatingMethod(enumValue), true) + ) }) + const unknownValues = Object.values(RatingMethod).filter(enumValue => !knownValues.includes(enumValue)) + unknownValues.forEach(enumValue => + test(`not supported: ${enumValue}`, () => + assert.strictEqual(SpecVersionDict[specVersion]?.supportsVulnerabilityRatingMethod(enumValue), false) + ) + ) }) ) }) diff --git a/tests/functional/Spec.SpecVersionDict.spec.js b/tests/functional/Spec.SpecVersionDict.spec.js index 49760c3ba..d3498245d 100644 --- a/tests/functional/Spec.SpecVersionDict.spec.js +++ b/tests/functional/Spec.SpecVersionDict.spec.js @@ -28,10 +28,10 @@ suite('SpecVersionDict', () => { Object.entries(SpecVersionDict).forEach(([key, spec]) => suite(`key: ${key}`, () => { test('key is well-known version', () => - assert.ok(Object.values(Version).includes(key)) + assert.strictEqual(Object.values(Version).includes(key), true) ) test('spec version equals key', () => - assert.equal(spec.version, key) + assert.strictEqual(spec.version, key) ) }) )