npm package: @secvisogram/csaf-validator-lib
Description: - [About The Project](#about-the-project) - [Getting Started](#getting-started) - [How to use](#how-to-use)   - [Strict Mode](#strict-mode)   - [API](#api)     - [Interfaces](#interfaces)     - CSAF 2.0       - [Module `schemaTests.js`](#module-schematest
Latest version: 2.0.21

# BSI CSAF Validator Lib

- [About The Project](#about-the-project)
- [Getting Started](#getting-started)
- [How to use](#how-to-use)
  - [Strict Mode](#strict-mode)
  - [API](#api)
    - [Interfaces](#interfaces)
    - CSAF 2.0
      - [Module `schemaTests.js`](#module-schematestsjs)
      - [Module `mandatoryTests.js`](#module-mandatorytestsjs)
      - [Module `optionalTests.js`](#module-optionaltestsjs)
      - [Module `informativeTests.js`](#module-informativetestsjs)
      - [Module `basic.js`](#module-basicjs)
      - [Module `extended.js`](#module-extendedjs)
      - [Module `full.js`](#module-fulljs)
    - CSAF 2.1 (experimental)
      - [Known Issues](#known-issues)
      - [Module `csaf_2_1/schemaTests.js`](#module-csaf_2_1schematestsjs)
      - [Module `csaf_2_1/mandatoryTests.js`](#module-csaf_2_1mandatorytestsjs)
      - [Module `csaf_2_1/recommendedTests.js`](#module-csaf_2_1recommendedtestsjs)
      - [Module `csaf_2_1/informativeTests.js`](#module-csaf_2_1informativetestsjs)
      - [Module `csaf_2_1/basic.js`](#module-csaf_2_1basicjs)
      - [Module `csaf_2_1/extended.js`](#module-csaf_2_1extendedjs)
      - [Module `csaf_2_1/full.js`](#module-csaf_2_1fulljs)
    - [Module `validate.js`](#module-validatejs)
    - [Module `validateStrict.js`](#module-validatestrictjs)
    - [Module `strip.js`](#module-stripjs)
    - [Module `cwe.js`](#module-cwejs)
- [Testing](#testing)
- [Contributing](#contributing)
- [Dependencies](#dependencies)

## About The Project

This JavaScript library is intended to include logic that can be shared across application working with CSAF.

[(back to top)](#bsi-csaf-validator-lib)

## Getting Started

Add the library to your project by using one of the following methods.
After that you can reference the modules from within your JavaScript application.

### Using the official npm package

There is an [official package](https://www.npmjs.com/package/@secvisogram/csaf-validator-lib) in the npm registry.

You can add it to your project using the following command:

```sh
npm install @secvisogram/csaf-validator-lib
```

### Using a git subtree

You can also include this library as a subtree in your repository.

- include as git subtree

  ```sh
  git subtree add --prefix csaf-validator-lib https://github.com/secvisogram/csaf-validator-lib.git main --squash
  ```

- install dependencies

  ```sh
  cd csaf-validator-lib && npm ci --prod
  ```

- This repository includes git submodules. Make sure to initialize and update
  the submodules before you start working with the repository.

  ```sh
  git submodule update --init --recursive
  ```

- For test 6.3.8 an installation of hunspell as well as all languages that
  you want to spell check is required.

### Managing Hunspell languages

A CSAF Document can contain a [language](https://docs.oasis-open.org/csaf/csaf/v2.0/cs02/csaf-v2.0-cs02.html#3216-document-property---language).
For example, valid entries could be `en` or `en-US`. When running test 6.3.8 we
try to match this language to the list of installed hunspell languages. If the
region is specified (like in `en-US`) and the corresponding language is
installed the test will run. If you want/need to check a `en` language
specifically with `en-US` (or any other variant) you need to make sure that you
link `en` to `en-US` using a symlink.

Example of linking `en` to `en-US`:

```sh
ln -s /usr/share/hunspell/en_US.aff /usr/share/hunspell/en.aff
ln -s /usr/share/hunspell/en_US.dic /usr/share/hunspell/en.dic
```

You can find out what languages you have installed by running `hunspell -D`.

If you need additional languages they are most likely available in the
repository of your distribution. If you have a custom dictionary
copy them in the directory provided by the command above. Hunspell should
automatically recognize them.

[(back to top)](#bsi-csaf-validator-lib)

## How to use

- example usage

  ```js
  import validateStrict from '../csaf-validator-lib/validateStrict.js'
  import * as mandatory from '../csaf-validator-lib/mandatoryTests.js'
  import { optionalTest_6_2_1 } from '../csaf-validator-lib/optionalTests.js'
  import { csaf_2_0_strict } from './schemaTests.js'

  const document = {}
  const tests = [
    csaf_2_0_strict,
    ...Object.values(mandatory),
    optionalTest_6_2_1,
  ]

  const result = await validateStrict(tests, document)
  ```

[(back to top)](#bsi-csaf-validator-lib)

### Strict Mode

The library has two validate functions, `validate` and `validateStrict`.
`validateStrict` checks whether the test that should be executed was defined in
the library. Otherwise, it throws an error. To extend the library you can use
the `validate` function instead. In such case, **the calling function is
responsible for checking** whether the test function passed to the
`csaf-validator-lib` is benign. **Calling arbitrary** functions (especially
those resulting from user input) may result in a **code execution
vulnerability**. Therefore, the check of the test function to determine whether
it is benign **MUST be done before calling** it.
To proceed this dangerous path, use the `validate` function.

[(back to top)](#bsi-csaf-validator-lib)

## API

### Interfaces

```typescript
interface Result {
  isValid: boolean
  warnings: Array<{ message: string; instancePath: string }>
  errors: Array<{ message: string; instancePath: string }>
  infos: Array<{ message: string; instancePath: string }>
}
```

```typescript
interface TestResult {
  isValid?: boolean
  warnings?: Array<{ message: string; instancePath: string }>
  errors?: Array<{ message: string; instancePath: string }>
  infos?: Array<{ message: string; instancePath: string }>
}
```

```typescript
/**
 * Every document test has its identifier set as the functions name. You can access
 * it using `<myTest>.name`
 */
type DocumentTest = (doc: any) => TestResult | Promise<TestResult>
```

[(back to top)](#bsi-csaf-validator-lib)

### CSAF 2.0

#### Module `schemaTests.js`

```typescript
export const csaf_2_0_strict: DocumentTest
export const csaf_2_0: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `mandatoryTests.js`

```typescript
export const mandatoryTest_6_1_1: DocumentTest
export const mandatoryTest_6_1_2: DocumentTest
export const mandatoryTest_6_1_3: DocumentTest
export const mandatoryTest_6_1_4: DocumentTest
export const mandatoryTest_6_1_5: DocumentTest
export const mandatoryTest_6_1_6: DocumentTest
export const mandatoryTest_6_1_7: DocumentTest
export const mandatoryTest_6_1_8: DocumentTest
export const mandatoryTest_6_1_9: DocumentTest
export const mandatoryTest_6_1_10: DocumentTest
export const mandatoryTest_6_1_11: DocumentTest
export const mandatoryTest_6_1_12: DocumentTest
export const mandatoryTest_6_1_13: DocumentTest
export const mandatoryTest_6_1_14: DocumentTest
export const mandatoryTest_6_1_15: DocumentTest
export const mandatoryTest_6_1_16: DocumentTest
export const mandatoryTest_6_1_17: DocumentTest
export const mandatoryTest_6_1_18: DocumentTest
export const mandatoryTest_6_1_19: DocumentTest
export const mandatoryTest_6_1_20: DocumentTest
export const mandatoryTest_6_1_21: DocumentTest
export const mandatoryTest_6_1_22: DocumentTest
export const mandatoryTest_6_1_23: DocumentTest
export const mandatoryTest_6_1_24: DocumentTest
export const mandatoryTest_6_1_25: DocumentTest
export const mandatoryTest_6_1_26: DocumentTest
export const mandatoryTest_6_1_27_1: DocumentTest
export const mandatoryTest_6_1_27_2: DocumentTest
export const mandatoryTest_6_1_27_3: DocumentTest
export const mandatoryTest_6_1_27_4: DocumentTest
export const mandatoryTest_6_1_27_5: DocumentTest
export const mandatoryTest_6_1_27_6: DocumentTest
export const mandatoryTest_6_1_27_7: DocumentTest
export const mandatoryTest_6_1_27_8: DocumentTest
export const mandatoryTest_6_1_27_9: DocumentTest
export const mandatoryTest_6_1_27_10: DocumentTest
export const mandatoryTest_6_1_27_11: DocumentTest
export const mandatoryTest_6_1_28: DocumentTest
export const mandatoryTest_6_1_29: DocumentTest
export const mandatoryTest_6_1_30: DocumentTest
export const mandatoryTest_6_1_31: DocumentTest
export const mandatoryTest_6_1_32: DocumentTest
export const mandatoryTest_6_1_33: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `optionalTests.js`

```typescript
export const optionalTest_6_2_1: DocumentTest
export const optionalTest_6_2_2: DocumentTest
export const optionalTest_6_2_3: DocumentTest
export const optionalTest_6_2_4: DocumentTest
export const optionalTest_6_2_5: DocumentTest
export const optionalTest_6_2_6: DocumentTest
export const optionalTest_6_2_7: DocumentTest
export const optionalTest_6_2_8: DocumentTest
export const optionalTest_6_2_9: DocumentTest
export const optionalTest_6_2_10: DocumentTest
export const optionalTest_6_2_11: DocumentTest
export const optionalTest_6_2_12: DocumentTest
export const optionalTest_6_2_13: DocumentTest
export const optionalTest_6_2_14: DocumentTest
export const optionalTest_6_2_15: DocumentTest
export const optionalTest_6_2_16: DocumentTest
export const optionalTest_6_2_17: DocumentTest
export const optionalTest_6_2_18: DocumentTest
export const optionalTest_6_2_19: DocumentTest
export const optionalTest_6_2_20: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `informativeTests.js`

```typescript
export const informativeTest_6_3_1: DocumentTest
export const informativeTest_6_3_2: DocumentTest
export const informativeTest_6_3_3: DocumentTest
export const informativeTest_6_3_4: DocumentTest
export const informativeTest_6_3_5: DocumentTest
export const informativeTest_6_3_6: DocumentTest
export const informativeTest_6_3_7: DocumentTest
export const informativeTest_6_3_8: DocumentTest
export const informativeTest_6_3_9: DocumentTest
export const informativeTest_6_3_10: DocumentTest
export const informativeTest_6_3_11: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `basic.js`

This module exports the strict schema test and all mandatory tests except `6.1.8`.

[(back to top)](#bsi-csaf-validator-lib)

#### Module `extended.js`

This module exports all tests included in `basic.js` and all optional tests.

[(back to top)](#bsi-csaf-validator-lib)

#### Module `full.js`

This module exports all tests included in `extended.js` and all informative tests.

[(back to top)](#bsi-csaf-validator-lib)

### CSAF 2.1 (experimental)

**HEADS UP**: The feature set in this section is not stable nor complete yet and changes without introducing a major version update. Please use it with caution! As soon as it becomes stable this README will be updated.

In CSAF 2.1 the "optional tests" have been renamed to "recommended tests".

#### Known Issues

The CVSS 4.0 computation is still under debate as it it unclear from the specification how to compute threatScore and environmentalScore.

The following tests are not yet implemented and therefore missing:

**Mandatory Tests**

- Mandatory Test 6.1.26
- Mandatory Test 6.1.27.13
- Mandatory Test 6.1.46
- Mandatory Test 6.1.47
- Mandatory Test 6.1.48
- Mandatory Test 6.1.49
- Mandatory Test 6.1.50
- Mandatory Test 6.1.53
- Mandatory Test 6.1.54
- Mandatory Test 6.1.55
- Mandatory Test 6.1.57
- Mandatory Test 6.1.58
- Mandatory Test 6.1.59
- Mandatory Test 6.1.60.1
- Mandatory Test 6.1.60.2
- Mandatory Test 6.1.60.3
- Mandatory Test 6.1.61

**Recommended Tests**

- Recommended Test 6.2.11
- Recommended Test 6.2.19
- Recommended Test 6.2.20
- Recommended Test 6.2.24
- Recommended Test 6.2.26
- Recommended Test 6.2.31
- Recommended Test 6.2.32
- Recommended Test 6.2.33
- Recommended Test 6.2.34
- Recommended Test 6.2.35
- Recommended Test 6.2.36
- Recommended Test 6.2.37
- Recommended Test 6.2.38
- Recommended Test 6.2.39.1
- Recommended Test 6.2.39.3
- Recommended Test 6.2.39.4
- Recommended Test 6.2.39.5
- Recommended Test 6.2.42
- Recommended Test 6.2.44
- Recommended Test 6.2.45
- Recommended Test 6.2.46
- Recommended Test 6.2.49
- Recommended Test 6.2.50.1
- Recommended Test 6.2.50.2
- Recommended Test 6.2.50.3
- Recommended Test 6.2.51
- Recommended Test 6.2.52
- Recommended Test 6.2.53
- Recommended Test 6.2.54.1
- Recommended Test 6.2.54.2
- Recommended Test 6.2.54.3
- Recommended Test 6.2.54.4

**Informative Tests**

- Informative Test 6.2.13
- Informative Test 6.2.14
- Informative Test 6.2.15
- Informative Test 6.2.16
- Informative Test 6.2.17
- Informative Test 6.2.19.1
- Informative Test 6.2.19.2
- Informative Test 6.2.19.3
- Informative Test 6.2.19.4
- Informative Test 6.2.19.5
- Informative Test 6.2.20
- Informative Test 6.2.21.1
- Informative Test 6.2.21.2
- Informative Test 6.2.21.3
- Informative Test 6.2.21.4
- Informative Test 6.2.21.5
- Informative Test 6.2.21.6
- Informative Test 6.2.21.7
- Informative Test 6.2.21.8
- Informative Test 6.2.21.9
- Informative Test 6.2.22

#### Module `csaf_2_1/schemaTests.js`

```typescript
export const csaf_2_0_strict: DocumentTest
export const csaf_2_0: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/mandatoryTests.js`

```typescript
export const mandatoryTest_6_1_1: DocumentTest
export const mandatoryTest_6_1_2: DocumentTest
export const mandatoryTest_6_1_3: DocumentTest
export const mandatoryTest_6_1_4: DocumentTest
export const mandatoryTest_6_1_5: DocumentTest
export const mandatoryTest_6_1_6: DocumentTest
export const mandatoryTest_6_1_7: DocumentTest
export const mandatoryTest_6_1_8: DocumentTest
export const mandatoryTest_6_1_9: DocumentTest
export const mandatoryTest_6_1_10: DocumentTest
export const mandatoryTest_6_1_11: DocumentTest
export const mandatoryTest_6_1_12: DocumentTest
export const mandatoryTest_6_1_13: DocumentTest
export const mandatoryTest_6_1_14: DocumentTest
export const mandatoryTest_6_1_15: DocumentTest
export const mandatoryTest_6_1_16: DocumentTest
export const mandatoryTest_6_1_17: DocumentTest
export const mandatoryTest_6_1_18: DocumentTest
export const mandatoryTest_6_1_19: DocumentTest
export const mandatoryTest_6_1_20: DocumentTest
export const mandatoryTest_6_1_21: DocumentTest
export const mandatoryTest_6_1_22: DocumentTest
export const mandatoryTest_6_1_23: DocumentTest
export const mandatoryTest_6_1_24: DocumentTest
export const mandatoryTest_6_1_25: DocumentTest
export const mandatoryTest_6_1_27_1: DocumentTest
export const mandatoryTest_6_1_27_2: DocumentTest
export const mandatoryTest_6_1_27_3: DocumentTest
export const mandatoryTest_6_1_27_4: DocumentTest
export const mandatoryTest_6_1_27_5: DocumentTest
export const mandatoryTest_6_1_27_6: DocumentTest
export const mandatoryTest_6_1_27_7: DocumentTest
export const mandatoryTest_6_1_27_8: DocumentTest
export const mandatoryTest_6_1_27_9: DocumentTest
export const mandatoryTest_6_1_27_10: DocumentTest
export const mandatoryTest_6_1_27_11: DocumentTest
export const mandatoryTest_6_1_27_12: DocumentTest
export const mandatoryTest_6_1_27_14: DocumentTest
export const mandatoryTest_6_1_27_15: DocumentTest
export const mandatoryTest_6_1_27_16: DocumentTest
export const mandatoryTest_6_1_27_17: DocumentTest
export const mandatoryTest_6_1_27_18: DocumentTest
export const mandatoryTest_6_1_27_19: DocumentTest
export const mandatoryTest_6_1_28: DocumentTest
export const mandatoryTest_6_1_29: DocumentTest
export const mandatoryTest_6_1_30: DocumentTest
export const mandatoryTest_6_1_31: DocumentTest
export const mandatoryTest_6_1_32: DocumentTest
export const mandatoryTest_6_1_33: DocumentTest
export const mandatoryTest_6_1_34: DocumentTest
export const mandatoryTest_6_1_35: DocumentTest
export const mandatoryTest_6_1_36: DocumentTest
export const mandatoryTest_6_1_37: DocumentTest
export const mandatoryTest_6_1_38: DocumentTest
export const mandatoryTest_6_1_39: DocumentTest
export const mandatoryTest_6_1_40: DocumentTest
export const mandatoryTest_6_1_41: DocumentTest
export const mandatoryTest_6_1_42: DocumentTest
export const mandatoryTest_6_1_43: DocumentTest
export const mandatoryTest_6_1_44: DocumentTest
export const mandatoryTest_6_1_45: DocumentTest
export const mandatoryTest_6_1_51: DocumentTest
export const mandatoryTest_6_1_52: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/recommendedTests.js`

```typescript
export const recommendedTest_6_2_1: DocumentTest
export const recommendedTest_6_2_2: DocumentTest
export const recommendedTest_6_2_3: DocumentTest
export const recommendedTest_6_2_4: DocumentTest
export const recommendedTest_6_2_5: DocumentTest
export const recommendedTest_6_2_6: DocumentTest
export const recommendedTest_6_2_7: DocumentTest
export const recommendedTest_6_2_8: DocumentTest
export const recommendedTest_6_2_9: DocumentTest
export const recommendedTest_6_2_10: DocumentTest
export const recommendedTest_6_2_12: DocumentTest
export const recommendedTest_6_2_13: DocumentTest
export const recommendedTest_6_2_14: DocumentTest
export const recommendedTest_6_2_15: DocumentTest
export const recommendedTest_6_2_16: DocumentTest
export const recommendedTest_6_2_17: DocumentTest
export const recommendedTest_6_2_18: DocumentTest
export const recommendedTest_6_2_21: DocumentTest
export const recommendedTest_6_2_22: DocumentTest
export const recommendedTest_6_2_23: DocumentTest
export const recommendedTest_6_2_25: DocumentTest
export const recommendedTest_6_2_27: DocumentTest
export const recommendedTest_6_2_28: DocumentTest
export const recommendedTest_6_2_29: DocumentTest
export const recommendedTest_6_2_30: DocumentTest
export const recommendedTest_6_2_39_2: DocumentTest
export const recommendedTest_6_2_40: DocumentTest
export const recommendedTest_6_2_41: DocumentTest
export const recommendedTest_6_2_43: DocumentTest
export const recommendedTest_6_2_47: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/informativeTests.js`

```typescript
export const informativeTest_6_3_1: DocumentTest
export const informativeTest_6_3_2: DocumentTest
export const informativeTest_6_3_3: DocumentTest
export const informativeTest_6_3_4: DocumentTest
export const informativeTest_6_3_5: DocumentTest
export const informativeTest_6_3_6: DocumentTest
export const informativeTest_6_3_7: DocumentTest
export const informativeTest_6_3_8: DocumentTest
export const informativeTest_6_3_9: DocumentTest
export const informativeTest_6_3_10: DocumentTest
export const informativeTest_6_3_11: DocumentTest
export const informativeTest_6_3_12: DocumentTest
export const informativeTest_6_3_18: DocumentTest
```

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/basic.js`

This module exports the strict schema test and all mandatory tests except `6.1.8`.

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/extended.js`

This module exports all tests included in `basic.js` and all optional tests.

[(back to top)](#bsi-csaf-validator-lib)

#### Module `csaf_2_1/full.js`

This module exports all tests included in `extended.js` and all informative tests.

[(back to top)](#bsi-csaf-validator-lib)

### Module `validate.js`

This function validates the given document against the given tests.

### Module `validateStrict.js`

This function validates the given document against the given tests. It throws
an error if an unknown test function was passed. See [Strict Mode](#strict-mode)
for more details.

[(back to top)](#bsi-csaf-validator-lib)

### Module `strip.js`

This function strips empty nodes and nodes with errors. The `strict` option (default `true`) throws an error if an unknown test function was passed. See [Strict Mode](#strict-mode) for more details.

```typescript
type StripFn = (
  tests: DocumentTest[],
  document: any,
  options?: { strict?: boolean }
) => Promise<{
  document: any
  strippedPaths: {
    instancePath: string
    message: string
    error: boolean
  }[]
}>

export default StripFn
```

[(back to top)](#bsi-csaf-validator-lib)

### Module `cwe.js`

```typescript
export const weaknesses: Array<{ id: string; name: string }>
```

[(back to top)](#bsi-csaf-validator-lib)

## Testing

Tests are implemented using [mocha](https://mochajs.org/). The minimal supported Node.js version is **20**. They can be run using the following command:

```sh
npm test
```

[(back to top)](#bsi-csaf-validator-lib)

## Contributing

You can find our guidelines here [CONTRIBUTING.md](https://github.com/secvisogram/secvisogram/blob/main/CONTRIBUTING.md)

[(back to top)](#bsi-csaf-validator-lib)

## Dependencies

For the complete list of dependencies please take a look at [package.json](https://github.com/secvisogram/csaf-validator-lib/blob/main/package.json)

- [Ajv JSON schema validator](https://github.com/ajv-validator/ajv)
- [JSON Schema formats for Ajv](https://github.com/ajv-validator/ajv-formats)
- [bcp47](https://github.com/gagle/node-bcp47)
- [cvss2js](https://github.com/sparticvs/cvss2js)
- [json-pointer](https://github.com/manuelstofer/json-pointer)
- [lodash](https://lodash.com/)
- [packageurl-js](https://github.com/package-url/packageurl-js)
- [semver](https://github.com/npm/node-semver)
- [undici](https://undici.nodejs.org)
- [@js-joda/core](https://js-joda.github.io/js-joda/)
- [@js-joda/timezone](https://js-joda.github.io/js-joda/)

[(back to top)](#bsi-csaf-validator-lib)