@cdxgen/cdxgen 13.1.0 → 13.3.0

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.
Files changed (283) hide show
  1. package/README.md +32 -15
  2. package/bin/cdxgen.js +243 -122
  3. package/bin/evinse.js +7 -0
  4. package/bin/sign.js +88 -14
  5. package/bin/tracebom.js +64 -4
  6. package/bin/validate.js +29 -7
  7. package/bin/verify.js +79 -39
  8. package/data/crypto-oid.json +88 -12
  9. package/data/remediations.json +47 -0
  10. package/data/rules/ai-bom.yaml +78 -0
  11. package/data/rules/cargo-rust.yaml +132 -0
  12. package/data/rules/mcp-servers.yaml +122 -0
  13. package/lib/audit/targets.js +6 -1
  14. package/lib/cli/bomAssembly.js +117 -15
  15. package/lib/cli/cliOptions.js +93 -1
  16. package/lib/cli/index.js +235 -5
  17. package/lib/cli/jsBom.js +108 -26
  18. package/lib/cli/jvmBom.js +68 -12
  19. package/lib/cli/managedBom.js +264 -41
  20. package/lib/cli/nativeBom.js +923 -15
  21. package/lib/core/activity.js +120 -2
  22. package/lib/core/env.js +44 -7
  23. package/lib/core/fs.js +174 -6
  24. package/lib/core/metadataProperties.js +97 -0
  25. package/lib/core/projectConfig.js +31 -4
  26. package/lib/core/userAgent.js +151 -0
  27. package/lib/ecosystems/bunutils.js +269 -101
  28. package/lib/ecosystems/cargoCache.js +364 -0
  29. package/lib/ecosystems/caxa.js +447 -7
  30. package/lib/ecosystems/cmakeResolver.js +66 -0
  31. package/lib/ecosystems/cppEvidence.js +104 -33
  32. package/lib/ecosystems/ecosystems.js +260 -99
  33. package/lib/ecosystems/golem.js +11 -1
  34. package/lib/ecosystems/gradleutils.js +185 -9
  35. package/lib/ecosystems/jsEvidence.js +19 -20
  36. package/lib/ecosystems/kosi.js +1263 -0
  37. package/lib/ecosystems/npmutils.js +110 -9
  38. package/lib/ecosystems/parsers-crystal.js +179 -0
  39. package/lib/ecosystems/parsers-dotnet.js +120 -49
  40. package/lib/ecosystems/parsers-elm.js +816 -0
  41. package/lib/ecosystems/parsers-gleam.js +1 -1
  42. package/lib/ecosystems/parsers-go.js +47 -9
  43. package/lib/ecosystems/parsers-js.js +171 -50
  44. package/lib/ecosystems/parsers-julia.js +268 -0
  45. package/lib/ecosystems/parsers-lua.js +218 -0
  46. package/lib/ecosystems/parsers-misc.js +919 -161
  47. package/lib/ecosystems/parsers-nim.js +221 -0
  48. package/lib/ecosystems/parsers-opam.js +180 -0
  49. package/lib/ecosystems/parsers-perl.js +277 -0
  50. package/lib/ecosystems/parsers-python.js +27 -15
  51. package/lib/ecosystems/parsers-r.js +148 -0
  52. package/lib/ecosystems/parsers-rebar.js +411 -0
  53. package/lib/ecosystems/parsers-rust.js +954 -33
  54. package/lib/ecosystems/parsers-spack.js +204 -0
  55. package/lib/ecosystems/parsers-stack.js +264 -0
  56. package/lib/ecosystems/parsers-terraform.js +194 -0
  57. package/lib/ecosystems/rubyutils.js +1426 -166
  58. package/lib/ecosystems/rusi.js +158 -7
  59. package/lib/evinser/evinser.js +547 -129
  60. package/lib/evinser/swiftsem.js +1914 -302
  61. package/lib/helpers/agenticToolutils.js +925 -0
  62. package/lib/helpers/bomSigner.js +652 -221
  63. package/lib/inventory/agentFormulationParser.js +57 -4
  64. package/lib/inventory/aiCollector.js +504 -10
  65. package/lib/inventory/aiInventory.js +12 -0
  66. package/lib/inventory/analyzer.js +488 -30
  67. package/lib/inventory/astWorker.js +6 -0
  68. package/lib/inventory/atomUtils.js +568 -31
  69. package/lib/inventory/auditCategories.js +8 -0
  70. package/lib/inventory/cbomutils.js +30 -0
  71. package/lib/inventory/cdxrs.js +110 -14
  72. package/lib/inventory/communityAiConfigParser.js +215 -2
  73. package/lib/inventory/depsUtils.js +183 -11
  74. package/lib/inventory/display.js +4 -5
  75. package/lib/inventory/dosai.js +627 -13
  76. package/lib/inventory/dynamic.js +39 -1
  77. package/lib/inventory/envcontext.js +9 -6
  78. package/lib/inventory/evidenceUtils.js +26 -5
  79. package/lib/inventory/fetchBatch.js +190 -19
  80. package/lib/inventory/fetchRate.js +74 -11
  81. package/lib/inventory/forgeEnricher.js +3 -2
  82. package/lib/inventory/jvmToolEnv.js +6 -5
  83. package/lib/inventory/mcpConfigParser.js +166 -2
  84. package/lib/inventory/mcpDiscovery.js +11 -0
  85. package/lib/inventory/mcpServerManifest.js +389 -0
  86. package/lib/inventory/mcpbBundle.js +419 -0
  87. package/lib/inventory/plugins.js +3 -0
  88. package/lib/inventory/protobom.js +62 -89
  89. package/lib/inventory/protobomLoader.js +4 -0
  90. package/lib/inventory/purl.js +152 -3
  91. package/lib/inventory/rustFormulationParser.js +1 -1
  92. package/lib/inventory/sbomDocument.js +2 -70
  93. package/lib/inventory/source.js +47 -23
  94. package/lib/inventory/stylePackageRefs.js +41 -0
  95. package/lib/inventory/svelteUtils.js +524 -0
  96. package/lib/inventory/traceRunner.js +210 -21
  97. package/lib/managers/binary.js +115 -24
  98. package/lib/managers/docker.js +440 -20
  99. package/lib/managers/oci.js +39 -1
  100. package/lib/parsers/cmakeLists.js +452 -0
  101. package/lib/parsers/huggingfaceUtils.js +15 -7
  102. package/lib/parsers/largeJson.js +454 -0
  103. package/lib/parsers/npmrc.js +19 -1
  104. package/lib/parsers/onnx.js +294 -0
  105. package/lib/parsers/safetensors.js +114 -0
  106. package/lib/stages/postgen/introspection/markers.js +29 -6
  107. package/lib/stages/postgen/postgen.js +237 -16
  108. package/lib/third-party/arborist/snapshots/calc-dep-flags.test.cjs +462 -0
  109. package/lib/validator/bomValidator.js +6 -16
  110. package/lib/validator/index.js +48 -10
  111. package/lib/validator/reporters/console.js +3 -0
  112. package/lib/validator/reporters/json.js +1 -0
  113. package/lib/validator/reporters/sarif.js +7 -0
  114. package/package.json +27 -27
  115. package/types/lib/audit/targets.d.ts.map +1 -1
  116. package/types/lib/cli/bomAssembly.d.ts +2 -1
  117. package/types/lib/cli/bomAssembly.d.ts.map +1 -1
  118. package/types/lib/cli/cliOptions.d.ts +33 -1
  119. package/types/lib/cli/cliOptions.d.ts.map +1 -1
  120. package/types/lib/cli/index.d.ts +2 -2
  121. package/types/lib/cli/index.d.ts.map +1 -1
  122. package/types/lib/cli/jsBom.d.ts +23 -0
  123. package/types/lib/cli/jsBom.d.ts.map +1 -1
  124. package/types/lib/cli/jvmBom.d.ts.map +1 -1
  125. package/types/lib/cli/managedBom.d.ts +33 -0
  126. package/types/lib/cli/managedBom.d.ts.map +1 -1
  127. package/types/lib/cli/nativeBom.d.ts +88 -8
  128. package/types/lib/cli/nativeBom.d.ts.map +1 -1
  129. package/types/lib/core/activity.d.ts.map +1 -1
  130. package/types/lib/core/env.d.ts +21 -0
  131. package/types/lib/core/env.d.ts.map +1 -1
  132. package/types/lib/core/fs.d.ts +55 -0
  133. package/types/lib/core/fs.d.ts.map +1 -1
  134. package/types/lib/core/metadataProperties.d.ts +39 -0
  135. package/types/lib/core/metadataProperties.d.ts.map +1 -0
  136. package/types/lib/core/projectConfig.d.ts +6 -2
  137. package/types/lib/core/projectConfig.d.ts.map +1 -1
  138. package/types/lib/core/userAgent.d.ts +56 -0
  139. package/types/lib/core/userAgent.d.ts.map +1 -0
  140. package/types/lib/ecosystems/bunutils.d.ts +12 -5
  141. package/types/lib/ecosystems/bunutils.d.ts.map +1 -1
  142. package/types/lib/ecosystems/cargoCache.d.ts +75 -0
  143. package/types/lib/ecosystems/cargoCache.d.ts.map +1 -0
  144. package/types/lib/ecosystems/caxa.d.ts +14 -0
  145. package/types/lib/ecosystems/caxa.d.ts.map +1 -1
  146. package/types/lib/ecosystems/cmakeResolver.d.ts +23 -0
  147. package/types/lib/ecosystems/cmakeResolver.d.ts.map +1 -1
  148. package/types/lib/ecosystems/cppEvidence.d.ts +2 -2
  149. package/types/lib/ecosystems/cppEvidence.d.ts.map +1 -1
  150. package/types/lib/ecosystems/ecosystems.d.ts +15 -1
  151. package/types/lib/ecosystems/ecosystems.d.ts.map +1 -1
  152. package/types/lib/ecosystems/golem.d.ts.map +1 -1
  153. package/types/lib/ecosystems/gradleutils.d.ts +40 -4
  154. package/types/lib/ecosystems/gradleutils.d.ts.map +1 -1
  155. package/types/lib/ecosystems/jsEvidence.d.ts +5 -2
  156. package/types/lib/ecosystems/jsEvidence.d.ts.map +1 -1
  157. package/types/lib/ecosystems/kosi.d.ts +86 -0
  158. package/types/lib/ecosystems/kosi.d.ts.map +1 -0
  159. package/types/lib/ecosystems/npmutils.d.ts +42 -0
  160. package/types/lib/ecosystems/npmutils.d.ts.map +1 -1
  161. package/types/lib/ecosystems/parsers-crystal.d.ts +27 -0
  162. package/types/lib/ecosystems/parsers-crystal.d.ts.map +1 -0
  163. package/types/lib/ecosystems/parsers-dotnet.d.ts +19 -0
  164. package/types/lib/ecosystems/parsers-dotnet.d.ts.map +1 -1
  165. package/types/lib/ecosystems/parsers-elm.d.ts +79 -0
  166. package/types/lib/ecosystems/parsers-elm.d.ts.map +1 -0
  167. package/types/lib/ecosystems/parsers-go.d.ts +10 -0
  168. package/types/lib/ecosystems/parsers-go.d.ts.map +1 -1
  169. package/types/lib/ecosystems/parsers-js.d.ts +10 -4
  170. package/types/lib/ecosystems/parsers-js.d.ts.map +1 -1
  171. package/types/lib/ecosystems/parsers-julia.d.ts +57 -0
  172. package/types/lib/ecosystems/parsers-julia.d.ts.map +1 -0
  173. package/types/lib/ecosystems/parsers-lua.d.ts +50 -0
  174. package/types/lib/ecosystems/parsers-lua.d.ts.map +1 -0
  175. package/types/lib/ecosystems/parsers-misc.d.ts +90 -3
  176. package/types/lib/ecosystems/parsers-misc.d.ts.map +1 -1
  177. package/types/lib/ecosystems/parsers-nim.d.ts +43 -0
  178. package/types/lib/ecosystems/parsers-nim.d.ts.map +1 -0
  179. package/types/lib/ecosystems/parsers-opam.d.ts +31 -0
  180. package/types/lib/ecosystems/parsers-opam.d.ts.map +1 -0
  181. package/types/lib/ecosystems/parsers-perl.d.ts +36 -0
  182. package/types/lib/ecosystems/parsers-perl.d.ts.map +1 -0
  183. package/types/lib/ecosystems/parsers-python.d.ts.map +1 -1
  184. package/types/lib/ecosystems/parsers-r.d.ts +35 -0
  185. package/types/lib/ecosystems/parsers-r.d.ts.map +1 -0
  186. package/types/lib/ecosystems/parsers-rebar.d.ts +42 -0
  187. package/types/lib/ecosystems/parsers-rebar.d.ts.map +1 -0
  188. package/types/lib/ecosystems/parsers-rust.d.ts +199 -0
  189. package/types/lib/ecosystems/parsers-rust.d.ts.map +1 -1
  190. package/types/lib/ecosystems/parsers-spack.d.ts +33 -0
  191. package/types/lib/ecosystems/parsers-spack.d.ts.map +1 -0
  192. package/types/lib/ecosystems/parsers-stack.d.ts +35 -0
  193. package/types/lib/ecosystems/parsers-stack.d.ts.map +1 -0
  194. package/types/lib/ecosystems/parsers-terraform.d.ts +34 -0
  195. package/types/lib/ecosystems/parsers-terraform.d.ts.map +1 -0
  196. package/types/lib/ecosystems/pythonutils.d.ts +1 -1
  197. package/types/lib/ecosystems/rubyutils.d.ts +143 -2
  198. package/types/lib/ecosystems/rubyutils.d.ts.map +1 -1
  199. package/types/lib/ecosystems/rusi.d.ts +13 -0
  200. package/types/lib/ecosystems/rusi.d.ts.map +1 -1
  201. package/types/lib/evinser/evinser.d.ts +81 -2
  202. package/types/lib/evinser/evinser.d.ts.map +1 -1
  203. package/types/lib/evinser/swiftsem.d.ts +280 -15
  204. package/types/lib/evinser/swiftsem.d.ts.map +1 -1
  205. package/types/lib/helpers/agenticToolutils.d.ts +87 -0
  206. package/types/lib/helpers/agenticToolutils.d.ts.map +1 -0
  207. package/types/lib/helpers/bomSigner.d.ts +106 -13
  208. package/types/lib/helpers/bomSigner.d.ts.map +1 -1
  209. package/types/lib/inventory/agentFormulationParser.d.ts.map +1 -1
  210. package/types/lib/inventory/aiCollector.d.ts.map +1 -1
  211. package/types/lib/inventory/aiInventory.d.ts.map +1 -1
  212. package/types/lib/inventory/analyzer.d.ts.map +1 -1
  213. package/types/lib/inventory/atomUtils.d.ts +145 -3
  214. package/types/lib/inventory/atomUtils.d.ts.map +1 -1
  215. package/types/lib/inventory/auditCategories.d.ts +4 -0
  216. package/types/lib/inventory/auditCategories.d.ts.map +1 -1
  217. package/types/lib/inventory/cbomutils.d.ts.map +1 -1
  218. package/types/lib/inventory/cdxrs.d.ts +8 -3
  219. package/types/lib/inventory/cdxrs.d.ts.map +1 -1
  220. package/types/lib/inventory/communityAiConfigParser.d.ts.map +1 -1
  221. package/types/lib/inventory/depsUtils.d.ts +15 -0
  222. package/types/lib/inventory/depsUtils.d.ts.map +1 -1
  223. package/types/lib/inventory/display.d.ts.map +1 -1
  224. package/types/lib/inventory/dosai.d.ts +87 -1
  225. package/types/lib/inventory/dosai.d.ts.map +1 -1
  226. package/types/lib/inventory/dynamic.d.ts.map +1 -1
  227. package/types/lib/inventory/envcontext.d.ts.map +1 -1
  228. package/types/lib/inventory/evidenceUtils.d.ts.map +1 -1
  229. package/types/lib/inventory/fetchBatch.d.ts +34 -0
  230. package/types/lib/inventory/fetchBatch.d.ts.map +1 -1
  231. package/types/lib/inventory/fetchRate.d.ts +9 -6
  232. package/types/lib/inventory/fetchRate.d.ts.map +1 -1
  233. package/types/lib/inventory/forgeEnricher.d.ts.map +1 -1
  234. package/types/lib/inventory/jvmToolEnv.d.ts +5 -4
  235. package/types/lib/inventory/jvmToolEnv.d.ts.map +1 -1
  236. package/types/lib/inventory/mcpConfigParser.d.ts.map +1 -1
  237. package/types/lib/inventory/mcpDiscovery.d.ts.map +1 -1
  238. package/types/lib/inventory/mcpServerManifest.d.ts +19 -0
  239. package/types/lib/inventory/mcpServerManifest.d.ts.map +1 -0
  240. package/types/lib/inventory/mcpbBundle.d.ts +19 -0
  241. package/types/lib/inventory/mcpbBundle.d.ts.map +1 -0
  242. package/types/lib/inventory/plugins.d.ts.map +1 -1
  243. package/types/lib/inventory/protobom.d.ts +18 -13
  244. package/types/lib/inventory/protobom.d.ts.map +1 -1
  245. package/types/lib/inventory/protobomLoader.d.ts.map +1 -1
  246. package/types/lib/inventory/purl.d.ts +71 -2
  247. package/types/lib/inventory/purl.d.ts.map +1 -1
  248. package/types/lib/inventory/sbomDocument.d.ts.map +1 -1
  249. package/types/lib/inventory/source.d.ts.map +1 -1
  250. package/types/lib/inventory/stylePackageRefs.d.ts +17 -0
  251. package/types/lib/inventory/stylePackageRefs.d.ts.map +1 -0
  252. package/types/lib/inventory/svelteUtils.d.ts +124 -0
  253. package/types/lib/inventory/svelteUtils.d.ts.map +1 -0
  254. package/types/lib/inventory/traceRunner.d.ts +47 -1
  255. package/types/lib/inventory/traceRunner.d.ts.map +1 -1
  256. package/types/lib/managers/binary.d.ts +30 -1
  257. package/types/lib/managers/binary.d.ts.map +1 -1
  258. package/types/lib/managers/docker.d.ts +29 -0
  259. package/types/lib/managers/docker.d.ts.map +1 -1
  260. package/types/lib/managers/oci.d.ts +14 -0
  261. package/types/lib/managers/oci.d.ts.map +1 -1
  262. package/types/lib/parsers/cmakeLists.d.ts +76 -0
  263. package/types/lib/parsers/cmakeLists.d.ts.map +1 -0
  264. package/types/lib/parsers/huggingfaceUtils.d.ts +8 -1
  265. package/types/lib/parsers/huggingfaceUtils.d.ts.map +1 -1
  266. package/types/lib/parsers/largeJson.d.ts +52 -0
  267. package/types/lib/parsers/largeJson.d.ts.map +1 -0
  268. package/types/lib/parsers/npmrc.d.ts +5 -0
  269. package/types/lib/parsers/npmrc.d.ts.map +1 -1
  270. package/types/lib/parsers/onnx.d.ts +28 -0
  271. package/types/lib/parsers/onnx.d.ts.map +1 -0
  272. package/types/lib/parsers/safetensors.d.ts +22 -0
  273. package/types/lib/parsers/safetensors.d.ts.map +1 -0
  274. package/types/lib/stages/postgen/introspection/markers.d.ts +3 -2
  275. package/types/lib/stages/postgen/introspection/markers.d.ts.map +1 -1
  276. package/types/lib/stages/postgen/postgen.d.ts +33 -0
  277. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  278. package/types/lib/validator/bomValidator.d.ts.map +1 -1
  279. package/types/lib/validator/index.d.ts +10 -1
  280. package/types/lib/validator/index.d.ts.map +1 -1
  281. package/types/lib/validator/reporters/console.d.ts.map +1 -1
  282. package/types/lib/validator/reporters/json.d.ts.map +1 -1
  283. package/types/lib/validator/reporters/sarif.d.ts.map +1 -1
@@ -0,0 +1,462 @@
1
+ /* IMPORTANT
2
+ * This snapshot file is auto-generated, but designed for humans.
3
+ * It should be checked into source control and tracked carefully.
4
+ * Re-generate by setting TAP_SNAPSHOT=1 and running tests.
5
+ * Make sure to inspect the output below. Do not ignore changes!
6
+ */
7
+ 'use strict'
8
+ exports[`test/calc-dep-flags.js TAP flag stuff > after 1`] = `
9
+ ArboristNode {
10
+ "children": Map {
11
+ "dev" => ArboristNode {
12
+ "dev": true,
13
+ "edgesIn": Set {
14
+ EdgeIn {
15
+ "from": "",
16
+ "name": "dev",
17
+ "spec": "*",
18
+ "type": "dev",
19
+ },
20
+ },
21
+ "edgesOut": Map {
22
+ "devdep" => EdgeOut {
23
+ "name": "devdep",
24
+ "spec": "*",
25
+ "to": "node_modules/devdep",
26
+ "type": "prod",
27
+ },
28
+ },
29
+ "location": "node_modules/dev",
30
+ "name": "dev",
31
+ "path": "/x/node_modules/dev",
32
+ "version": "1.2.3",
33
+ },
34
+ "devandoptional" => ArboristNode {
35
+ "dev": true,
36
+ "edgesIn": Set {
37
+ EdgeIn {
38
+ "from": "node_modules/devdep",
39
+ "name": "devandoptional",
40
+ "spec": "*",
41
+ "type": "optional",
42
+ },
43
+ },
44
+ "location": "node_modules/devandoptional",
45
+ "name": "devandoptional",
46
+ "optional": true,
47
+ "path": "/x/node_modules/devandoptional",
48
+ "version": "1.2.3",
49
+ },
50
+ "devdep" => ArboristNode {
51
+ "children": Map {
52
+ "linky" => ArboristLink {
53
+ "dev": true,
54
+ "edgesIn": Set {
55
+ EdgeIn {
56
+ "from": "node_modules/devdep",
57
+ "name": "linky",
58
+ "spec": "*",
59
+ "type": "prod",
60
+ },
61
+ },
62
+ "location": "node_modules/devdep/node_modules/linky",
63
+ "name": "linky",
64
+ "path": "/x/node_modules/devdep/node_modules/linky",
65
+ "realpath": "/x/y/z",
66
+ "resolved": "file:../../../y/z",
67
+ "target": ArboristNode {
68
+ "location": "y/z",
69
+ },
70
+ "version": "1.2.3",
71
+ },
72
+ },
73
+ "dev": true,
74
+ "edgesIn": Set {
75
+ EdgeIn {
76
+ "from": "node_modules/dev",
77
+ "name": "devdep",
78
+ "spec": "*",
79
+ "type": "prod",
80
+ },
81
+ },
82
+ "edgesOut": Map {
83
+ "devandoptional" => EdgeOut {
84
+ "name": "devandoptional",
85
+ "spec": "*",
86
+ "to": "node_modules/devandoptional",
87
+ "type": "optional",
88
+ },
89
+ "devoptional" => EdgeOut {
90
+ "name": "devoptional",
91
+ "spec": "*",
92
+ "to": "node_modules/devoptional",
93
+ "type": "prod",
94
+ },
95
+ "linky" => EdgeOut {
96
+ "name": "linky",
97
+ "spec": "*",
98
+ "to": "node_modules/devdep/node_modules/linky",
99
+ "type": "prod",
100
+ },
101
+ "proddep" => EdgeOut {
102
+ "name": "proddep",
103
+ "spec": "*",
104
+ "to": "node_modules/proddep",
105
+ "type": "prod",
106
+ },
107
+ },
108
+ "location": "node_modules/devdep",
109
+ "name": "devdep",
110
+ "path": "/x/node_modules/devdep",
111
+ "version": "1.2.3",
112
+ },
113
+ "devoptional" => ArboristNode {
114
+ "devOptional": true,
115
+ "edgesIn": Set {
116
+ EdgeIn {
117
+ "from": "node_modules/devdep",
118
+ "name": "devoptional",
119
+ "spec": "*",
120
+ "type": "prod",
121
+ },
122
+ EdgeIn {
123
+ "from": "node_modules/optional",
124
+ "name": "devoptional",
125
+ "spec": "*",
126
+ "type": "prod",
127
+ },
128
+ },
129
+ "location": "node_modules/devoptional",
130
+ "name": "devoptional",
131
+ "path": "/x/node_modules/devoptional",
132
+ "version": "1.2.3",
133
+ },
134
+ "extraneous" => ArboristNode {
135
+ "dev": true,
136
+ "extraneous": true,
137
+ "location": "node_modules/extraneous",
138
+ "name": "extraneous",
139
+ "optional": true,
140
+ "path": "/x/node_modules/extraneous",
141
+ "peer": true,
142
+ },
143
+ "metapeer" => ArboristNode {
144
+ "edgesIn": Set {
145
+ EdgeIn {
146
+ "from": "node_modules/prod",
147
+ "name": "metapeer",
148
+ "spec": "*",
149
+ "type": "peer",
150
+ },
151
+ },
152
+ "edgesOut": Map {
153
+ "metapeerdep" => EdgeOut {
154
+ "name": "metapeerdep",
155
+ "spec": "*",
156
+ "to": "node_modules/metapeerdep",
157
+ "type": "prod",
158
+ },
159
+ },
160
+ "location": "node_modules/metapeer",
161
+ "name": "metapeer",
162
+ "path": "/x/node_modules/metapeer",
163
+ "peer": true,
164
+ "version": "1.2.3",
165
+ },
166
+ "metapeerdep" => ArboristNode {
167
+ "edgesIn": Set {
168
+ EdgeIn {
169
+ "from": "node_modules/metapeer",
170
+ "name": "metapeerdep",
171
+ "spec": "*",
172
+ "type": "prod",
173
+ },
174
+ },
175
+ "location": "node_modules/metapeerdep",
176
+ "name": "metapeerdep",
177
+ "path": "/x/node_modules/metapeerdep",
178
+ "peer": true,
179
+ "version": "1.2.3",
180
+ },
181
+ "optional" => ArboristNode {
182
+ "edgesIn": Set {
183
+ EdgeIn {
184
+ "from": "",
185
+ "name": "optional",
186
+ "spec": "*",
187
+ "type": "optional",
188
+ },
189
+ EdgeIn {
190
+ "from": "node_modules/peeroptional",
191
+ "name": "optional",
192
+ "spec": "*",
193
+ "type": "prod",
194
+ },
195
+ },
196
+ "edgesOut": Map {
197
+ "devoptional" => EdgeOut {
198
+ "name": "devoptional",
199
+ "spec": "*",
200
+ "to": "node_modules/devoptional",
201
+ "type": "prod",
202
+ },
203
+ "missing" => EdgeOut {
204
+ "error": "MISSING",
205
+ "name": "missing",
206
+ "spec": "*",
207
+ "to": null,
208
+ "type": "prod",
209
+ },
210
+ },
211
+ "location": "node_modules/optional",
212
+ "name": "optional",
213
+ "optional": true,
214
+ "path": "/x/node_modules/optional",
215
+ "version": "1.2.3",
216
+ },
217
+ "peer" => ArboristNode {
218
+ "edgesIn": Set {
219
+ EdgeIn {
220
+ "from": "",
221
+ "name": "peer",
222
+ "spec": "*",
223
+ "type": "peer",
224
+ },
225
+ },
226
+ "edgesOut": Map {
227
+ "peerdep" => EdgeOut {
228
+ "name": "peerdep",
229
+ "spec": "*",
230
+ "to": "node_modules/peerdep",
231
+ "type": "prod",
232
+ },
233
+ },
234
+ "location": "node_modules/peer",
235
+ "name": "peer",
236
+ "path": "/x/node_modules/peer",
237
+ "peer": true,
238
+ "version": "1.2.3",
239
+ },
240
+ "peerdep" => ArboristNode {
241
+ "edgesIn": Set {
242
+ EdgeIn {
243
+ "from": "node_modules/peer",
244
+ "name": "peerdep",
245
+ "spec": "*",
246
+ "type": "prod",
247
+ },
248
+ },
249
+ "location": "node_modules/peerdep",
250
+ "name": "peerdep",
251
+ "path": "/x/node_modules/peerdep",
252
+ "peer": true,
253
+ "version": "1.2.3",
254
+ },
255
+ "peeroptional" => ArboristNode {
256
+ "edgesIn": Set {
257
+ EdgeIn {
258
+ "from": "",
259
+ "name": "peeroptional",
260
+ "spec": "*",
261
+ "type": "peerOptional",
262
+ },
263
+ },
264
+ "edgesOut": Map {
265
+ "optional" => EdgeOut {
266
+ "name": "optional",
267
+ "spec": "*",
268
+ "to": "node_modules/optional",
269
+ "type": "prod",
270
+ },
271
+ },
272
+ "extraneous": true,
273
+ "location": "node_modules/peeroptional",
274
+ "name": "peeroptional",
275
+ "optional": true,
276
+ "path": "/x/node_modules/peeroptional",
277
+ "peer": true,
278
+ "version": "1.2.3",
279
+ },
280
+ "prod" => ArboristNode {
281
+ "edgesIn": Set {
282
+ EdgeIn {
283
+ "from": "",
284
+ "name": "prod",
285
+ "spec": "*",
286
+ "type": "prod",
287
+ },
288
+ },
289
+ "edgesOut": Map {
290
+ "metapeer" => EdgeOut {
291
+ "name": "metapeer",
292
+ "spec": "*",
293
+ "to": "node_modules/metapeer",
294
+ "type": "peer",
295
+ },
296
+ "proddep" => EdgeOut {
297
+ "name": "proddep",
298
+ "spec": "*",
299
+ "to": "node_modules/proddep",
300
+ "type": "prod",
301
+ },
302
+ },
303
+ "location": "node_modules/prod",
304
+ "name": "prod",
305
+ "path": "/x/node_modules/prod",
306
+ "version": "1.2.3",
307
+ },
308
+ "proddep" => ArboristNode {
309
+ "edgesIn": Set {
310
+ EdgeIn {
311
+ "from": "node_modules/devdep",
312
+ "name": "proddep",
313
+ "spec": "*",
314
+ "type": "prod",
315
+ },
316
+ EdgeIn {
317
+ "from": "node_modules/prod",
318
+ "name": "proddep",
319
+ "spec": "*",
320
+ "type": "prod",
321
+ },
322
+ EdgeIn {
323
+ "from": "node_modules/proddep",
324
+ "name": "proddep",
325
+ "spec": "*",
326
+ "type": "prod",
327
+ },
328
+ },
329
+ "edgesOut": Map {
330
+ "proddep" => EdgeOut {
331
+ "name": "proddep",
332
+ "spec": "*",
333
+ "to": "node_modules/proddep",
334
+ "type": "prod",
335
+ },
336
+ },
337
+ "location": "node_modules/proddep",
338
+ "name": "proddep",
339
+ "path": "/x/node_modules/proddep",
340
+ "version": "1.2.3",
341
+ },
342
+ },
343
+ "edgesOut": Map {
344
+ "dev" => EdgeOut {
345
+ "name": "dev",
346
+ "spec": "*",
347
+ "to": "node_modules/dev",
348
+ "type": "dev",
349
+ },
350
+ "optional" => EdgeOut {
351
+ "name": "optional",
352
+ "spec": "*",
353
+ "to": "node_modules/optional",
354
+ "type": "optional",
355
+ },
356
+ "peer" => EdgeOut {
357
+ "name": "peer",
358
+ "spec": "*",
359
+ "to": "node_modules/peer",
360
+ "type": "peer",
361
+ },
362
+ "peeroptional" => EdgeOut {
363
+ "name": "peeroptional",
364
+ "spec": "*",
365
+ "to": "node_modules/peeroptional",
366
+ "type": "peerOptional",
367
+ },
368
+ "prod" => EdgeOut {
369
+ "name": "prod",
370
+ "spec": "*",
371
+ "to": "node_modules/prod",
372
+ "type": "prod",
373
+ },
374
+ },
375
+ "fsChildren": Set {
376
+ ArboristNode {
377
+ "children": Map {
378
+ "linklink" => ArboristLink {
379
+ "dev": true,
380
+ "edgesIn": Set {
381
+ EdgeIn {
382
+ "from": "y/z",
383
+ "name": "linklink",
384
+ "spec": "*",
385
+ "type": "prod",
386
+ },
387
+ },
388
+ "location": "y/z/node_modules/linklink",
389
+ "name": "linklink",
390
+ "path": "/x/y/z/node_modules/linklink",
391
+ "realpath": "/l/i/n/k/link",
392
+ "resolved": "file:../../../../l/i/n/k/link",
393
+ "target": ArboristNode {
394
+ "dev": true,
395
+ "location": "../l/i/n/k/link",
396
+ "name": "link",
397
+ "packageName": "linklink",
398
+ "path": "/l/i/n/k/link",
399
+ "version": "1.2.3",
400
+ },
401
+ "version": "1.2.3",
402
+ },
403
+ },
404
+ "dev": true,
405
+ "edgesOut": Map {
406
+ "linklink" => EdgeOut {
407
+ "name": "linklink",
408
+ "spec": "*",
409
+ "to": "y/z/node_modules/linklink",
410
+ "type": "prod",
411
+ },
412
+ },
413
+ "location": "y/z",
414
+ "name": "z",
415
+ "packageName": "linky",
416
+ "path": "/x/y/z",
417
+ "version": "1.2.3",
418
+ },
419
+ },
420
+ "isProjectRoot": true,
421
+ "location": "",
422
+ "name": "x",
423
+ "path": "/x",
424
+ }
425
+ `
426
+
427
+ exports[`test/calc-dep-flags.js TAP no reset > after 1`] = `
428
+ ArboristNode {
429
+ "children": Map {
430
+ "foo" => ArboristNode {
431
+ "dev": true,
432
+ "edgesIn": Set {
433
+ EdgeIn {
434
+ "from": "",
435
+ "name": "foo",
436
+ "spec": "*",
437
+ "type": "prod",
438
+ },
439
+ },
440
+ "location": "node_modules/foo",
441
+ "name": "foo",
442
+ "path": "/some/path/node_modules/foo",
443
+ "peer": true,
444
+ "version": "1.2.3",
445
+ },
446
+ },
447
+ "dev": true,
448
+ "edgesOut": Map {
449
+ "foo" => EdgeOut {
450
+ "name": "foo",
451
+ "spec": "*",
452
+ "to": "node_modules/foo",
453
+ "type": "prod",
454
+ },
455
+ },
456
+ "isProjectRoot": true,
457
+ "location": "",
458
+ "name": "path",
459
+ "path": "/some/path",
460
+ "peer": true,
461
+ }
462
+ `
@@ -15,7 +15,7 @@ import {
15
15
  toCycloneDxSpecVersionString,
16
16
  } from "../inventory/bomUtils.js";
17
17
  import { isPartialTree } from "../inventory/depsUtils.js";
18
- import { isValidPurl } from "../inventory/purl.js";
18
+ import { isValidPurl, parsePurlLoose } from "../inventory/purl.js";
19
19
 
20
20
  const dirName = dirNameStr;
21
21
  // The v13 floor is spec 1.6. 1.4 and 1.5 were dropped here so that the JS and
@@ -790,17 +790,13 @@ export const validateRefs = (bomJson) => {
790
790
  if (!refMap[dep.ref]) {
791
791
  warningsList.push(`Invalid ref in dependencies ${dep.ref}`);
792
792
  }
793
- let parentPurlType;
794
- try {
795
- const purlObj = Purl.parse(dep.ref);
796
- parentPurlType = purlObj.type;
797
- } catch (_e) {
798
- // pass
799
- }
793
+ // A ref is the decoded form of a purl, so a version with `+` does not
794
+ // parse strictly; the type is all that is needed here.
795
+ const parentPurlType = parsePurlLoose(dep.ref)?.type;
800
796
  if (
801
797
  parentComponentRef &&
802
798
  dep.ref === parentComponentRef &&
803
- dep.dependsOn.length === 0 &&
799
+ !dep.dependsOn?.length &&
804
800
  bomJson.dependencies.length > 1
805
801
  ) {
806
802
  warningsList.push(
@@ -814,13 +810,7 @@ export const validateRefs = (bomJson) => {
814
810
  `Invalid ref in dependencies.dependsOn ${don}. Parent: ${dep.ref}`,
815
811
  );
816
812
  }
817
- let childPurlType;
818
- try {
819
- const purlObj = Purl.parse(don);
820
- childPurlType = purlObj.type;
821
- } catch (_e) {
822
- // pass
823
- }
813
+ const childPurlType = parsePurlLoose(don)?.type;
824
814
  if (
825
815
  parentPurlType &&
826
816
  childPurlType &&
@@ -11,7 +11,11 @@
11
11
  * wrapper (`bin/validate.js`) is responsible for reading the input BOM.
12
12
  */
13
13
 
14
- import { verifyNode } from "../helpers/bomSigner.js";
14
+ import {
15
+ loadSharedSecret,
16
+ verifyBom,
17
+ verifyNode,
18
+ } from "../helpers/bomSigner.js";
15
19
  import {
16
20
  validateBom,
17
21
  validateMetadata,
@@ -109,18 +113,26 @@ export async function validateGeneratedBom(bomJson) {
109
113
  * Run schema + deep validation checks from the existing validator helpers and
110
114
  * capture their boolean results without letting them blow up the process.
111
115
  *
116
+ * An exception is not a verdict on the BOM, so it is recorded in
117
+ * `validationErrors` instead of silently counting as a plain failure.
118
+ *
112
119
  * @param {object} bomJson
113
120
  * @param {object} opts
114
- * @returns {Promise<{ schemaValid: boolean, deepValid: boolean }>}
121
+ * @returns {Promise<{ schemaValid: boolean, deepValid: boolean, validationErrors: Array<{ stage: string, message: string }> }>}
115
122
  */
116
123
  async function runSchemaAndDeep(bomJson, opts) {
117
124
  let schemaValid = true;
118
125
  let deepValid = true;
126
+ const validationErrors = [];
119
127
  if (opts.schema !== false) {
120
128
  try {
121
129
  schemaValid = (await validateBom(bomJson)) !== false;
122
130
  } catch (err) {
123
131
  schemaValid = false;
132
+ validationErrors.push({
133
+ stage: "schema",
134
+ message: err?.message || String(err),
135
+ });
124
136
  if (opts.onError) opts.onError("schema", err);
125
137
  }
126
138
  }
@@ -133,10 +145,14 @@ async function runSchemaAndDeep(bomJson, opts) {
133
145
  validateProps(bomJson) !== false;
134
146
  } catch (err) {
135
147
  deepValid = false;
148
+ validationErrors.push({
149
+ stage: "deep",
150
+ message: err?.message || String(err),
151
+ });
136
152
  if (opts.onError) opts.onError("deep", err);
137
153
  }
138
154
  }
139
- return { schemaValid, deepValid };
155
+ return { schemaValid, deepValid, validationErrors };
140
156
  }
141
157
 
142
158
  /**
@@ -151,10 +167,13 @@ async function runSchemaAndDeep(bomJson, opts) {
151
167
  * @param {string} [options.minSeverity] Minimum severity for returned findings.
152
168
  * @param {boolean} [options.includeManual] Include manual-review findings (default true).
153
169
  * @param {boolean} [options.includePass] Include passing findings (default false).
154
- * @param {string} [options.publicKey] If set, verify the BOM signature.
170
+ * @param {string} [options.publicKey] If set, verify the BOM signature with this public key.
171
+ * @param {string|Buffer} [options.secretKey] If set, verify an HMAC (HS*) BOM signature with this shared secret.
172
+ * @param {boolean} [options.nestedSignatures] Also verify component, service, and annotation signatures (default true), as cdx-verify does.
155
173
  * @returns {{
156
174
  * schemaValid: boolean,
157
175
  * deepValid: boolean,
176
+ * validationErrors: Array<{ stage: string, message: string }>,
158
177
  * signatureVerified: boolean | null,
159
178
  * signatureDetails: object | null,
160
179
  * findings: Array<object>,
@@ -164,7 +183,10 @@ async function runSchemaAndDeep(bomJson, opts) {
164
183
  * }}
165
184
  */
166
185
  export async function validateBomAdvanced(bomJson, options = {}) {
167
- const { schemaValid, deepValid } = await runSchemaAndDeep(bomJson, options);
186
+ const { schemaValid, deepValid, validationErrors } = await runSchemaAndDeep(
187
+ bomJson,
188
+ options,
189
+ );
168
190
  const allFindings = evaluateAll(bomJson, {
169
191
  categories: options.categories,
170
192
  benchmarks: options.benchmarks,
@@ -177,17 +199,32 @@ export async function validateBomAdvanced(bomJson, options = {}) {
177
199
  });
178
200
  let signatureVerified = null;
179
201
  let signatureDetails = null;
180
- if (options.publicKey && bomJson?.signature) {
202
+ const verificationRequested = Boolean(options.publicKey || options.secretKey);
203
+ if (verificationRequested && bomJson?.signature) {
181
204
  try {
182
- const match = verifyNode(bomJson, options.publicKey);
205
+ const key = options.secretKey
206
+ ? loadSharedSecret(options.secretKey)
207
+ : options.publicKey;
208
+ const reasons = [];
209
+ const verify =
210
+ options.nestedSignatures === false ? verifyNode : verifyBom;
211
+ const match = verify(bomJson, key, { reasons });
183
212
  signatureVerified = Boolean(match);
184
- signatureDetails = match || null;
213
+ if (match) {
214
+ signatureDetails = match;
215
+ } else {
216
+ signatureDetails = {
217
+ error: reasons.length
218
+ ? [...new Set(reasons)].join(" ")
219
+ : "No signature matched the key.",
220
+ };
221
+ }
185
222
  } catch (err) {
186
223
  signatureVerified = false;
187
224
  signatureDetails = { error: err?.message || String(err) };
188
225
  }
189
- } else if (options.publicKey) {
190
- // Public key provided but BOM has no signature.
226
+ } else if (verificationRequested) {
227
+ // Verification key provided but BOM has no signature.
191
228
  signatureVerified = false;
192
229
  signatureDetails = { error: "BOM has no signature block." };
193
230
  }
@@ -197,6 +234,7 @@ export async function validateBomAdvanced(bomJson, options = {}) {
197
234
  return {
198
235
  schemaValid,
199
236
  deepValid,
237
+ validationErrors,
200
238
  signatureVerified,
201
239
  signatureDetails,
202
240
  findings: filtered,
@@ -128,6 +128,9 @@ export function formatSummary(summary) {
128
128
  export function render(report) {
129
129
  const pieces = [];
130
130
  pieces.push(formatSummary(report.summary));
131
+ for (const e of report.validationErrors || []) {
132
+ pieces.push(`Validator error during ${e.stage} validation: ${e.message}`);
133
+ }
131
134
  if (report.benchmarks?.length) {
132
135
  pieces.push(formatBenchmarks(report.benchmarks));
133
136
  }
@@ -12,6 +12,7 @@ export function render(report, _options = {}) {
12
12
  const payload = {
13
13
  schemaValid: report.schemaValid,
14
14
  deepValid: report.deepValid,
15
+ validationErrors: report.validationErrors || [],
15
16
  signatureVerified: report.signatureVerified ?? null,
16
17
  summary: report.summary,
17
18
  benchmarks: report.benchmarks || [],
@@ -167,12 +167,19 @@ export function render(report, options = {}) {
167
167
  {
168
168
  executionSuccessful:
169
169
  report.summary?.fail === 0 && report.schemaValid !== false,
170
+ toolExecutionNotifications: (report.validationErrors || []).map(
171
+ (e) => ({
172
+ level: "error",
173
+ message: { text: `${e.stage} validation error: ${e.message}` },
174
+ }),
175
+ ),
170
176
  },
171
177
  ],
172
178
  results: findings.map(toSarifResult),
173
179
  properties: {
174
180
  schemaValid: report.schemaValid,
175
181
  deepValid: report.deepValid,
182
+ validationErrors: report.validationErrors || [],
176
183
  signatureVerified: report.signatureVerified ?? null,
177
184
  summary: report.summary,
178
185
  benchmarks: report.benchmarks || [],