@csaf-rs/ssvc 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,71 +1,34 @@
1
- # SSVC Rust Implementation
1
+ # @csaf-rs/ssvc
2
2
 
3
- A Rust implementation of the **SSVC (Stakeholder-Specific Vulnerability Categorization)** specification.
3
+ A WebAssembly build of the **SSVC (Stakeholder-Specific Vulnerability Categorization)** Rust implementation, for use with JavaScript/TypeScript.
4
4
  SSVC is a framework for prioritizing software vulnerability remediation efforts. It helps stakeholders make informed decisions about which vulnerabilities to address first by considering factors like vulnerability severity, the stakeholder's position in the ecosystem, and their specific constraints.
5
5
  Learn more at the [official SSVC documentation](https://certcc.github.io/SSVC/).
6
6
 
7
+ For the Rust crate, source code, and full project documentation, see the [csaf-rs/ssvc on GitHub](https://github.com/csaf-rs/ssvc).
8
+
7
9
  ## Features
8
10
 
9
- This library provides validation and processing of SSVC decision points and selection lists, with support for SSVC namespaces and extensions.
10
- It features full serde support. The library supports both native Rust usage and WebAssembly (WASM) bindings for JavaScript/web applications.
11
+ This package provides validation and processing of SSVC decision points and selection lists, with support for SSVC namespaces and extensions.
11
12
 
12
13
  ## Installation
13
14
 
14
- Add to your project:
15
-
16
15
  ```bash
17
- cargo add ssvc
18
- ```
19
-
20
- ## MSRV
21
-
22
- 1.85.0
23
-
24
- ## Examples
25
-
26
- ### Rust
27
-
28
- ```rust
29
- use ssvc::selection_list::SelectionList;
30
- use ssvc::validate_selection_list;
31
-
32
- let json_data = "..."; // Your SSVC selection list
33
-
34
- let selection_list: SelectionList =
35
- serde_json::from_str(json_data).expect("SSVC SelectionList was invalid JSON");
36
-
37
- // Validate the selection list
38
- let result = validate_selection_list(&selection_list, false);
39
-
40
- if result.success {
41
- println!("Selection list is valid!");
42
- } else {
43
- for error in result.errors {
44
- println!("Validation error: {}", error.message);
45
- }
46
- }
16
+ npm install @csaf-rs/ssvc
47
17
  ```
48
18
 
49
- ### WebAssembly
19
+ ## Usage
50
20
 
51
- #### Build
52
-
53
- ```bash
54
- # Install wasm-pack if you haven't already
55
- cargo install wasm-pack
56
- # Build for web
57
- wasm-pack build --target web --out-dir pkg -- --features wasm
58
- ```
59
-
60
- #### Usage
21
+ The WASM module must be initialized once before its functions can be used:
61
22
 
62
23
  ```javascript
63
- import * as wasm from './pkg/ssvc.js';
24
+ import init, { validateSelectionList } from '@csaf-rs/ssvc';
25
+
26
+ await init();
64
27
 
65
28
  const jsonData = {...}; // Your SSVC selection list
66
29
 
67
30
  try {
68
- const result = wasm.validateSelectionList(JSON.stringify(jsonData), false);
31
+ const result = validateSelectionList(JSON.stringify(jsonData), false);
69
32
  if (result.success) {
70
33
  console.log("Valid SSVC data");
71
34
  } else {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@csaf-rs/ssvc",
3
3
  "type": "module",
4
4
  "description": "Implementation of the SSVC specification in Rust",
5
- "version": "0.3.1",
5
+ "version": "0.4.1",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
package/ssvc.d.ts CHANGED
@@ -1,22 +1,152 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
+ /**
4
+ *A minimal representation of a decision point value.
5
+ Intended to parallel the DecisionPointValue object, but with fewer required fields.
6
+ A decision point value is uniquely identified within a decision point by its key.
7
+ Globally, the combination of Decision Point namespace, key, and version coupled with the value key
8
+ uniquely identifies a value across all decision points and values.
9
+ Other required fields in the DecisionPointValue object, such as name and description, are optional here.
10
+ */
11
+ export interface MinimalDecisionPointValue {
12
+ definition: Definition | undefined;
13
+ /**
14
+ *A short, non-empty string identifier for the object. Keys must start with an alphanumeric, contain only alphanumerics and `_`, and end with an alphanumeric.(`T*` is explicitly grandfathered in as a valid key, but should not be used for new objects.)
15
+ */
16
+ key: Key;
17
+ name: Name | undefined;
18
+ }
19
+
20
+ /**
21
+ *A minimal selection object that contains the decision point ID and the selected values.
22
+ While the Selection object parallels the DecisionPoint object, it is intentionally minimal, with
23
+ fewer required fields and no additional metadata, as it is meant to represent a selection made from a
24
+ previously defined decision point. The expectation is that a Selection object will usually have
25
+ fewer values than the original decision point, as it represents a specific evaluation
26
+ at a specific time and may therefore rule out some values that were previously considered.
27
+ Other fields like name and description may be copied from the decision point, but are not required.
28
+ */
29
+ export interface Selection {
30
+ definition: Definition | undefined;
31
+ /**
32
+ *A short, non-empty string identifier for the object. Keys must start with an alphanumeric, contain only alphanumerics and `_`, and end with an alphanumeric.(`T*` is explicitly grandfathered in as a valid key, but should not be used for new objects.)
33
+ */
34
+ key: Key;
35
+ name: Name | undefined;
36
+ /**
37
+ *The namespace of the SSVC object.
38
+ */
39
+ namespace: Namespace;
40
+ /**
41
+ *A list of selected value keys from the decision point values.
42
+ */
43
+ values: MinimalDecisionPointValue[];
44
+ /**
45
+ *The version of the SSVC object. This must be a valid semantic version string.
46
+ */
47
+ version: Version;
48
+ }
49
+
50
+ /**
51
+ *A reference to a resource that provides additional context about the decision points or selections.
52
+ This object is intentionally minimal and contains only the URL and an optional description.
53
+ */
54
+ export interface Reference {
55
+ summary: string;
56
+ uri: Uri;
57
+ }
58
+
59
+ /**
60
+ *A short, non-empty string identifier for the object. Keys must start with an alphanumeric, contain only alphanumerics and `_`, and end with an alphanumeric.(`T*` is explicitly grandfathered in as a valid key, but should not be used for new objects.)
61
+ */
62
+ export type Key = string;
63
+
64
+ /**
65
+ *The namespace of the SSVC object.
66
+ */
67
+ export type Namespace = string;
68
+
69
+ /**
70
+ *The version of the SSVC object. This must be a valid semantic version string.
71
+ */
72
+ export type Version = string;
73
+
74
+ /**
75
+ *This schema defines the structure to represent an SSVC SelectionList object.
76
+ */
77
+ export interface SelectionList {
78
+ /**
79
+ *A list of resources that provide additional context about the decision points found in this selection.
80
+ */
81
+ decision_point_resources?: Reference[];
82
+ /**
83
+ *A list of references that provide additional context about the specific values selected.
84
+ */
85
+ references?: Reference[];
86
+ /**
87
+ *The schema version of this selection list.
88
+ */
89
+ schemaVersion: string;
90
+ /**
91
+ *List of selections made from decision points. Each selection item corresponds to value keys contained in a specific decision point identified by its namespace, key, and version. Note that selection objects are deliberately minimal objects and do not contain the full decision point details.
92
+ */
93
+ selections: Selection[];
94
+ /**
95
+ *Optional list of identifiers for the item or items (vulnerabilities, reports, advisories, systems, assets, etc.) being evaluated by these selections.
96
+ */
97
+ target_ids: string[] | undefined;
98
+ /**
99
+ *Timestamp of the selections, in RFC 3339 format.
100
+ */
101
+ timestamp: string;
102
+ }
103
+
104
+ /**
105
+ *`Definition`
106
+ */
107
+ export type Definition = string;
108
+
109
+ /**
110
+ *`Name`
111
+ */
112
+ export type Name = string;
113
+
114
+ /**
115
+ *`Uri`
116
+ */
117
+ export type Uri = string;
118
+
119
+ export interface ValidationError {
120
+ message: string;
121
+ instancePath: string[];
122
+ }
123
+
124
+ export interface ValidationResult {
125
+ success: boolean;
126
+ errors: ValidationError[];
127
+ }
128
+
3
129
 
4
130
  /**
5
131
  * Initialize panic hook for better error messages in the browser console
6
132
  */
7
133
  export function init(): void;
8
134
 
9
- export function validateSelectionList(json_str: string, allow_test_namespaces: boolean): any;
135
+ export function validateSelectionList(json_str: string, allow_test_namespaces: boolean): ValidationResult;
10
136
 
11
- export function validateSelectionListValue(json_value: any, allow_test_namespaces: boolean): any;
137
+ /**
138
+ * Validates a strongly-typed `SelectionList`, giving TypeScript callers full
139
+ * type-checking and autocompletion on the input instead of `any`.
140
+ */
141
+ export function validateSelectionListFromValue(selection_list: SelectionList, allow_test_namespaces: boolean): ValidationResult;
12
142
 
13
143
  export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
14
144
 
15
145
  export interface InitOutput {
16
146
  readonly memory: WebAssembly.Memory;
17
- readonly validateSelectionList: (a: number, b: number, c: number) => [number, number, number];
18
- readonly validateSelectionListValue: (a: any, b: number) => [number, number, number];
19
147
  readonly init: () => void;
148
+ readonly validateSelectionList: (a: number, b: number, c: number) => [number, number, number];
149
+ readonly validateSelectionListFromValue: (a: any, b: number) => [number, number, number];
20
150
  readonly __wbindgen_malloc: (a: number, b: number) => number;
21
151
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
22
152
  readonly __wbindgen_exn_store: (a: number) => void;
package/ssvc.js CHANGED
@@ -10,7 +10,7 @@ export function init() {
10
10
  /**
11
11
  * @param {string} json_str
12
12
  * @param {boolean} allow_test_namespaces
13
- * @returns {any}
13
+ * @returns {ValidationResult}
14
14
  */
15
15
  export function validateSelectionList(json_str, allow_test_namespaces) {
16
16
  const ptr0 = passStringToWasm0(json_str, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -23,12 +23,14 @@ export function validateSelectionList(json_str, allow_test_namespaces) {
23
23
  }
24
24
 
25
25
  /**
26
- * @param {any} json_value
26
+ * Validates a strongly-typed `SelectionList`, giving TypeScript callers full
27
+ * type-checking and autocompletion on the input instead of `any`.
28
+ * @param {SelectionList} selection_list
27
29
  * @param {boolean} allow_test_namespaces
28
- * @returns {any}
30
+ * @returns {ValidationResult}
29
31
  */
30
- export function validateSelectionListValue(json_value, allow_test_namespaces) {
31
- const ret = wasm.validateSelectionListValue(json_value, allow_test_namespaces);
32
+ export function validateSelectionListFromValue(selection_list, allow_test_namespaces) {
33
+ const ret = wasm.validateSelectionListFromValue(selection_list, allow_test_namespaces);
32
34
  if (ret[2]) {
33
35
  throw takeFromExternrefTable0(ret[1]);
34
36
  }
@@ -37,7 +39,7 @@ export function validateSelectionListValue(json_value, allow_test_namespaces) {
37
39
  function __wbg_get_imports() {
38
40
  const import0 = {
39
41
  __proto__: null,
40
- __wbg_Error_92b29b0548f8b746: function(arg0, arg1) {
42
+ __wbg_Error_67e7344beaa85059: function(arg0, arg1) {
41
43
  const ret = Error(getStringFromWasm0(arg0, arg1));
42
44
  return ret;
43
45
  },
@@ -48,46 +50,46 @@ function __wbg_get_imports() {
48
50
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
49
51
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
50
52
  },
51
- __wbg___wbindgen_boolean_get_fa956cfa2d1bd751: function(arg0) {
53
+ __wbg___wbindgen_boolean_get_7a12af2b3f899c5a: function(arg0) {
52
54
  const v = arg0;
53
55
  const ret = typeof(v) === 'boolean' ? v : undefined;
54
56
  return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;
55
57
  },
56
- __wbg___wbindgen_debug_string_c25d447a39f5578f: function(arg0, arg1) {
58
+ __wbg___wbindgen_debug_string_0e68cf47c9cbd9b0: function(arg0, arg1) {
57
59
  const ret = debugString(arg1);
58
60
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
59
61
  const len1 = WASM_VECTOR_LEN;
60
62
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
61
63
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
62
64
  },
63
- __wbg___wbindgen_in_aca499c5de7ff5e5: function(arg0, arg1) {
65
+ __wbg___wbindgen_in_50072d4d6e45c193: function(arg0, arg1) {
64
66
  const ret = arg0 in arg1;
65
67
  return ret;
66
68
  },
67
- __wbg___wbindgen_is_function_1ff95bcc5517c252: function(arg0) {
69
+ __wbg___wbindgen_is_function_fcda5e3902d732fe: function(arg0) {
68
70
  const ret = typeof(arg0) === 'function';
69
71
  return ret;
70
72
  },
71
- __wbg___wbindgen_is_object_a27215656b807791: function(arg0) {
73
+ __wbg___wbindgen_is_object_edb6b15aa3afe12e: function(arg0) {
72
74
  const val = arg0;
73
75
  const ret = typeof(val) === 'object' && val !== null;
74
76
  return ret;
75
77
  },
76
- __wbg___wbindgen_is_undefined_c05833b95a3cf397: function(arg0) {
78
+ __wbg___wbindgen_is_undefined_8c687d0b90d5b524: function(arg0) {
77
79
  const ret = arg0 === undefined;
78
80
  return ret;
79
81
  },
80
- __wbg___wbindgen_jsval_loose_eq_db4c3b15f63fc170: function(arg0, arg1) {
82
+ __wbg___wbindgen_jsval_loose_eq_3c30021c243b64cd: function(arg0, arg1) {
81
83
  const ret = arg0 == arg1;
82
84
  return ret;
83
85
  },
84
- __wbg___wbindgen_number_get_394265ed1e1b84ee: function(arg0, arg1) {
86
+ __wbg___wbindgen_number_get_1dc732b810cb937c: function(arg0, arg1) {
85
87
  const obj = arg1;
86
88
  const ret = typeof(obj) === 'number' ? obj : undefined;
87
89
  getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
88
90
  getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
89
91
  },
90
- __wbg___wbindgen_string_get_b0ca35b86a603356: function(arg0, arg1) {
92
+ __wbg___wbindgen_string_get_92ab86bb19cbc12f: function(arg0, arg1) {
91
93
  const obj = arg1;
92
94
  const ret = typeof(obj) === 'string' ? obj : undefined;
93
95
  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -95,18 +97,18 @@ function __wbg_get_imports() {
95
97
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
96
98
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
97
99
  },
98
- __wbg___wbindgen_throw_344f42d3211c4765: function(arg0, arg1) {
100
+ __wbg___wbindgen_throw_5d9e815e6fdf150f: function(arg0, arg1) {
99
101
  throw new Error(getStringFromWasm0(arg0, arg1));
100
102
  },
101
- __wbg_call_8a2dd23819f8a60a: function() { return handleError(function (arg0, arg1) {
103
+ __wbg_call_269c5566fbede3eb: function() { return handleError(function (arg0, arg1) {
102
104
  const ret = arg0.call(arg1);
103
105
  return ret;
104
106
  }, arguments); },
105
- __wbg_done_89b2b13e91a60321: function(arg0) {
107
+ __wbg_done_cffed884d87aa22e: function(arg0) {
106
108
  const ret = arg0.done;
107
109
  return ret;
108
110
  },
109
- __wbg_error_a6fa202b58aa1cd3: function(arg0, arg1) {
111
+ __wbg_error_757e9472f8410341: function(arg0, arg1) {
110
112
  let deferred0_0;
111
113
  let deferred0_1;
112
114
  try {
@@ -117,11 +119,11 @@ function __wbg_get_imports() {
117
119
  wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);
118
120
  }
119
121
  },
120
- __wbg_get_c7eb1f358a7654df: function() { return handleError(function (arg0, arg1) {
122
+ __wbg_get_6cf5a4d4d8ad3c5a: function() { return handleError(function (arg0, arg1) {
121
123
  const ret = Reflect.get(arg0, arg1);
122
124
  return ret;
123
125
  }, arguments); },
124
- __wbg_get_unchecked_6e0ad6d2a41b06f6: function(arg0, arg1) {
126
+ __wbg_get_unchecked_363572bdd397d473: function(arg0, arg1) {
125
127
  const ret = arg0[arg1 >>> 0];
126
128
  return ret;
127
129
  },
@@ -129,7 +131,7 @@ function __wbg_get_imports() {
129
131
  const ret = arg0[arg1];
130
132
  return ret;
131
133
  },
132
- __wbg_instanceof_ArrayBuffer_4480b9e0068a8adb: function(arg0) {
134
+ __wbg_instanceof_ArrayBuffer_d4ff01f8247925ae: function(arg0) {
133
135
  let result;
134
136
  try {
135
137
  result = arg0 instanceof ArrayBuffer;
@@ -139,7 +141,7 @@ function __wbg_get_imports() {
139
141
  const ret = result;
140
142
  return ret;
141
143
  },
142
- __wbg_instanceof_Uint8Array_309b927aaf7a3fc7: function(arg0) {
144
+ __wbg_instanceof_Uint8Array_598adc0fef426aa8: function(arg0) {
143
145
  let result;
144
146
  try {
145
147
  result = arg0 instanceof Uint8Array;
@@ -149,55 +151,55 @@ function __wbg_get_imports() {
149
151
  const ret = result;
150
152
  return ret;
151
153
  },
152
- __wbg_isArray_0677c962b281d01a: function(arg0) {
154
+ __wbg_isArray_5674713bb7b79043: function(arg0) {
153
155
  const ret = Array.isArray(arg0);
154
156
  return ret;
155
157
  },
156
- __wbg_iterator_6f722e4a93058b71: function() {
158
+ __wbg_iterator_22ddeb808cf55a6f: function() {
157
159
  const ret = Symbol.iterator;
158
160
  return ret;
159
161
  },
160
- __wbg_length_1f0964f4a5e2c6d8: function(arg0) {
162
+ __wbg_length_31bdaf014f5fbde2: function(arg0) {
161
163
  const ret = arg0.length;
162
164
  return ret;
163
165
  },
164
- __wbg_length_370319915dc99107: function(arg0) {
166
+ __wbg_length_4e1adc0d42e23620: function(arg0) {
165
167
  const ret = arg0.length;
166
168
  return ret;
167
169
  },
168
- __wbg_new_227d7c05414eb861: function() {
169
- const ret = new Error();
170
+ __wbg_new_1da3429bc3c4541c: function(arg0) {
171
+ const ret = new Uint8Array(arg0);
170
172
  return ret;
171
173
  },
172
- __wbg_new_32b398fb48b6d94a: function() {
173
- const ret = new Array();
174
+ __wbg_new_227d7c05414eb861: function() {
175
+ const ret = new Error();
174
176
  return ret;
175
177
  },
176
- __wbg_new_cd45aabdf6073e84: function(arg0) {
177
- const ret = new Uint8Array(arg0);
178
+ __wbg_new_bebc3f4757acf305: function() {
179
+ const ret = new Object();
178
180
  return ret;
179
181
  },
180
- __wbg_new_da52cf8fe3429cb2: function() {
181
- const ret = new Object();
182
+ __wbg_new_ffa92086ea89f79c: function() {
183
+ const ret = new Array();
182
184
  return ret;
183
185
  },
184
- __wbg_next_6dbf2c0ac8cde20f: function(arg0) {
186
+ __wbg_next_95053e306b1c3aed: function(arg0) {
185
187
  const ret = arg0.next;
186
188
  return ret;
187
189
  },
188
- __wbg_next_71f2aa1cb3d1e37e: function() { return handleError(function (arg0) {
190
+ __wbg_next_f31ecb8646d2c605: function() { return handleError(function (arg0) {
189
191
  const ret = arg0.next();
190
192
  return ret;
191
193
  }, arguments); },
192
- __wbg_prototypesetcall_4770620bbe4688a0: function(arg0, arg1, arg2) {
194
+ __wbg_prototypesetcall_ae9f5e7459250748: function(arg0, arg1, arg2) {
193
195
  Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
194
196
  },
197
+ __wbg_set_13d25b81ab403f5e: function(arg0, arg1, arg2) {
198
+ arg0[arg1 >>> 0] = arg2;
199
+ },
195
200
  __wbg_set_6be42768c690e380: function(arg0, arg1, arg2) {
196
201
  arg0[arg1] = arg2;
197
202
  },
198
- __wbg_set_8a16b38e4805b298: function(arg0, arg1, arg2) {
199
- arg0[arg1 >>> 0] = arg2;
200
- },
201
203
  __wbg_stack_3b0d974bbf31e44f: function(arg0, arg1) {
202
204
  const ret = arg1.stack;
203
205
  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
@@ -205,11 +207,11 @@ function __wbg_get_imports() {
205
207
  getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
206
208
  getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
207
209
  },
208
- __wbg_value_a5d5488a9589444a: function(arg0) {
210
+ __wbg_value_c227f843d21da141: function(arg0) {
209
211
  const ret = arg0.value;
210
212
  return ret;
211
213
  },
212
- __wbindgen_cast_0000000000000001: function(arg0, arg1) {
214
+ __wbindgen_generic_0000000000000001: function(arg0, arg1) {
213
215
  // Cast intrinsic for `Ref(String) -> Externref`.
214
216
  const ret = getStringFromWasm0(arg0, arg1);
215
217
  return ret;
@@ -424,11 +426,15 @@ function __wbg_finalize_init(instance, module) {
424
426
 
425
427
  async function __wbg_load(module, imports) {
426
428
  if (typeof Response === 'function' && module instanceof Response) {
429
+ if (!module.ok) {
430
+ throw new Error(`failed to fetch Wasm: ${module.status} ${module.statusText} fetching '${module.url}'`);
431
+ }
432
+
427
433
  if (typeof WebAssembly.instantiateStreaming === 'function') {
428
434
  try {
429
435
  return await WebAssembly.instantiateStreaming(module, imports);
430
436
  } catch (e) {
431
- const validResponse = module.ok && expectedResponseType(module.type);
437
+ const validResponse = expectedResponseType(module.type);
432
438
 
433
439
  if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {
434
440
  console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
package/ssvc_bg.wasm CHANGED
Binary file