@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
@@ -9,11 +9,16 @@ import {
9
9
  safeRmSync,
10
10
  safeSpawnSync,
11
11
  } from "../core/fs.js";
12
+ import { dirNameStr } from "../core/paths.js";
12
13
  import { applyAlgorithmProperties } from "../inventory/cryptoAlgorithmFamily.js";
13
14
  import { resolvePluginBinary } from "../inventory/plugins.js";
14
15
 
15
16
  const RUST_LANGUAGES = new Set(["rust", "rs", "rust-lang"]);
16
17
 
18
+ const RUSI_CRYPTO_OIDS = JSON.parse(
19
+ readFileSync(join(dirNameStr, "data", "crypto-oid.json"), "utf-8"),
20
+ );
21
+
17
22
  /**
18
23
  * Resolves the rusi binary.
19
24
  *
@@ -82,6 +87,75 @@ function createPurlAliasMap(components = []) {
82
87
  return purlAliasMap;
83
88
  }
84
89
 
90
+ /**
91
+ * Path roots that never name a dependency crate.
92
+ */
93
+ const RUST_NON_CRATE_PATH_ROOTS = new Set([
94
+ "crate",
95
+ "self",
96
+ "super",
97
+ "std",
98
+ "core",
99
+ "alloc",
100
+ "proc_macro",
101
+ "test",
102
+ ]);
103
+
104
+ /**
105
+ * Index the cargo components by the identifier a Rust path spells them with.
106
+ *
107
+ * A crate named `cfg-if` is written `cfg_if` in source, and a lock file can
108
+ * carry several versions of the same crate, so a name maps to every matching
109
+ * purl.
110
+ *
111
+ * @param {Object[]} components Components from the BOM
112
+ * @returns {Map<string, string[]>} Crate identifier to purls
113
+ */
114
+ function createCrateNameIndex(components = []) {
115
+ const crateNameIndex = new Map();
116
+ for (const component of components) {
117
+ if (!component?.purl?.startsWith("pkg:cargo/") || !component.name) {
118
+ continue;
119
+ }
120
+ const crateIdentifier = component.name.toLowerCase().replaceAll("-", "_");
121
+ const purls = crateNameIndex.get(crateIdentifier) || [];
122
+ if (!purls.includes(component.purl)) {
123
+ purls.push(component.purl);
124
+ }
125
+ crateNameIndex.set(crateIdentifier, purls);
126
+ }
127
+ return crateNameIndex;
128
+ }
129
+
130
+ /**
131
+ * Resolve the dependency crates a Rust path refers to.
132
+ *
133
+ * rusi reports an import against the package that declares it, so the imported
134
+ * crate has to be recovered from the path itself. This is what turns an
135
+ * `use hex::encode;` into usage evidence for the `hex` component.
136
+ *
137
+ * @param {string} importPath Rust path, such as `hex::encode`
138
+ * @param {Map<string, string[]>} crateNameIndex Index from {@link createCrateNameIndex}
139
+ * @param {string} [ownerPurl] purl of the package that declares the path
140
+ * @returns {string[]} Matching component purls
141
+ */
142
+ function resolveImportedCratePurls(importPath, crateNameIndex, ownerPurl) {
143
+ if (!importPath || !crateNameIndex?.size) {
144
+ return [];
145
+ }
146
+ const pathRoot = String(importPath)
147
+ .replace(/^::/, "")
148
+ .split("::")[0]
149
+ .trim()
150
+ .toLowerCase();
151
+ if (!pathRoot || RUST_NON_CRATE_PATH_ROOTS.has(pathRoot)) {
152
+ return [];
153
+ }
154
+ return (crateNameIndex.get(pathRoot) || []).filter(
155
+ (purl) => purl !== ownerPurl,
156
+ );
157
+ }
158
+
85
159
  function resolveComponentPurl(purl, purlAliasMap) {
86
160
  if (!purl) {
87
161
  return undefined;
@@ -182,19 +256,37 @@ function mergeCryptoComponent(componentsByRef, component, item) {
182
256
  return existing;
183
257
  }
184
258
 
259
+ // The schema requires an oid for algorithm assets, so an algorithm the OID
260
+ // table cannot name is skipped rather than emitted invalid. rusi reports
261
+ // display-cased names ("SHA-256") while the table is lowercase ("sha-256").
262
+ function resolveCryptoAlgorithmMetadata(name) {
263
+ if (!name) {
264
+ return undefined;
265
+ }
266
+ const lowered = String(name).toLowerCase();
267
+ return (
268
+ RUSI_CRYPTO_OIDS[name] ||
269
+ RUSI_CRYPTO_OIDS[lowered] ||
270
+ RUSI_CRYPTO_OIDS[lowered.replace(/[\s_]+/g, "-")]
271
+ );
272
+ }
273
+
185
274
  function cryptoAlgorithmComponent(asset) {
275
+ const algorithmName = asset.algorithm || asset.kind || "unknown";
276
+ const algorithmMetadata = resolveCryptoAlgorithmMetadata(algorithmName);
277
+ if (!algorithmMetadata?.oid) {
278
+ return undefined;
279
+ }
186
280
  const component = {
187
281
  type: "cryptographic-asset",
188
- name: asset.algorithm || asset.kind || "unknown",
189
- "bom-ref": cryptoBomRef(
190
- "algorithm",
191
- asset.algorithm || asset.kind,
192
- asset.provider || "unknown",
193
- ),
282
+ name: algorithmName,
283
+ "bom-ref": cryptoBomRef("algorithm", algorithmName, algorithmMetadata.oid),
194
284
  description:
285
+ algorithmMetadata.description ||
195
286
  "Cryptographic algorithm/component detected by rusi source analysis",
196
287
  cryptoProperties: {
197
288
  assetType: "algorithm",
289
+ oid: algorithmMetadata.oid,
198
290
  algorithmProperties: { primitive: asset.kind || "unknown" },
199
291
  },
200
292
  properties: [],
@@ -258,6 +350,29 @@ function cryptoMaterialComponent(material) {
258
350
  return component;
259
351
  }
260
352
 
353
+ /**
354
+ * Returns the backend rusi actually used. `options.backend` is only the
355
+ * requested backend: when the compiler backend cannot run (missing
356
+ * components, wrapper build failure), rusi still echoes "compiler" but falls
357
+ * back to the stable source analysis. Compiler evidence was collected only
358
+ * when rusi emits its compiler-source-evidence diagnostic; a backend-error
359
+ * alone is not conclusive because native interop scanning reports failures
360
+ * under that kind too.
361
+ *
362
+ * @param {Object} rusiReport Parsed rusi report
363
+ * @returns {string|undefined} Effective backend name
364
+ */
365
+ export function effectiveRusiBackend(rusiReport = {}) {
366
+ const requested = rusiReport.options?.backend;
367
+ if (requested !== "compiler") {
368
+ return requested;
369
+ }
370
+ const collected = (rusiReport.diagnostics || []).some(
371
+ (d) => d?.kind === "compiler-source-evidence",
372
+ );
373
+ return collected ? requested : "stable";
374
+ }
375
+
261
376
  function addMetadataProperties(properties, rusiReport = {}) {
262
377
  appendUniqueProperty(
263
378
  properties,
@@ -282,7 +397,15 @@ function addMetadataProperties(properties, rusiReport = {}) {
282
397
  appendUniqueProperty(properties, "cdx:rusi:host", rusiReport.runtime?.host);
283
398
 
284
399
  const options = rusiReport.options || {};
285
- appendUniqueProperty(properties, "cdx:rusi:backend", options.backend);
400
+ const backend = effectiveRusiBackend(rusiReport);
401
+ appendUniqueProperty(properties, "cdx:rusi:backend", backend);
402
+ if (options.backend && options.backend !== backend) {
403
+ appendUniqueProperty(
404
+ properties,
405
+ "cdx:rusi:requestedBackend",
406
+ options.backend,
407
+ );
408
+ }
286
409
  appendUniqueProperty(
287
410
  properties,
288
411
  "cdx:rusi:analysisScope",
@@ -361,6 +484,7 @@ function addImportEvidence(
361
484
  purlAliasMap,
362
485
  purlLocationMap,
363
486
  componentPropertiesMap,
487
+ crateNameIndex,
364
488
  ) {
365
489
  for (const importUsage of rusiReport.imports || []) {
366
490
  const purl = resolveComponentPurl(importUsage.purl, purlAliasMap);
@@ -380,6 +504,31 @@ function addImportEvidence(
380
504
  "cdx:rusi:importAlias",
381
505
  importUsage.alias,
382
506
  );
507
+ // The import is also evidence about the crate being imported, which is the
508
+ // component a consumer filters on.
509
+ for (const cratePurl of resolveImportedCratePurls(
510
+ importUsage.path,
511
+ crateNameIndex,
512
+ purl,
513
+ )) {
514
+ addSetValue(
515
+ purlLocationMap,
516
+ cratePurl,
517
+ positionLocation(importUsage.position),
518
+ );
519
+ addPropertyValue(
520
+ componentPropertiesMap,
521
+ cratePurl,
522
+ "cdx:rusi:importedBy",
523
+ purl,
524
+ );
525
+ addPropertyValue(
526
+ componentPropertiesMap,
527
+ cratePurl,
528
+ "cdx:rusi:importPath",
529
+ importUsage.path,
530
+ );
531
+ }
383
532
  }
384
533
  }
385
534
 
@@ -761,6 +910,7 @@ export function analyzeRusiProject(src, options = {}) {
761
910
  */
762
911
  export function collectRusiEvidence(rusiReport = {}, components = []) {
763
912
  const purlAliasMap = createPurlAliasMap(components);
913
+ const crateNameIndex = createCrateNameIndex(components);
764
914
  const purlLocationMap = {};
765
915
  const dataFlowFrames = {};
766
916
  const componentPropertiesMap = {};
@@ -774,6 +924,7 @@ export function collectRusiEvidence(rusiReport = {}, components = []) {
774
924
  purlAliasMap,
775
925
  purlLocationMap,
776
926
  componentPropertiesMap,
927
+ crateNameIndex,
777
928
  );
778
929
  addUsageEvidence(
779
930
  rusiReport,