Commit 484ec47
fix(sbom): read the tool from a CycloneDX services entry
A hosted generator records itself under metadata.tools.services rather than
under components, so the tool came back empty for any document using that
slot. The SBOM our own pipeline produces is one: it names Snyk there and
nowhere else. Measured on that document, tools went from nil to
["SBOM Export API v1.131.1"], with 1023 packages unchanged.
The schema vendored with cyclonedx-go defines metadata.tools as the tools
used in the creation, enrichment and validation of the BOM, and its services
slot as "a list of services used as tools". CycloneDX's own 1.6 example
fills components and services together, so a signing service that signed a
document is now listed as a tool. Two existing expectations were updated.
Each slot contributes a name and a version and no vendor. Not a new rule:
the deprecated slot carries a Vendor field and this reader has always
ignored it.
An entry that identifies nothing is skipped. Document.Tools has two writers,
at sbom.go:273 and sbom.go:441, and each used to record a blank. Measured
against the unguarded code:
CycloneDX component name " ", version "1.0"
-> " 1.0"
CycloneDX xml name and version wrapped across lines
-> "\n Awesome Tool\n \n 9.1.2\n "
SPDX creator "Tool:"
-> ""
The shared rule is what blank means, not the append. An SPDX creator is one
free-text field with no separable version, so routing it through the
CycloneDX helper would assert that syft-1.50.0 has no version. Each writer
applies the same predicate to whichever field identifies a tool in its
format. A block whose entries are all skipped yields nil, not an empty list.
Fixtures, and where each came from:
cyclonedx-tools-services.json cut from the SBOM the pipeline produced
on 2026-09-14: its header, metadata and
first component
cyclonedx-tools-nameless-service.json that file, with two services entries
added, one named "" and one named " "
cyclonedx-wrapped-tool-name.xml the repo's CycloneDX 1.6 XML fixture with
the tool name and version wrapped across
lines, as a pretty-printer emits them
spdx-blank-tool-creator.json the repo's SPDX 2.3 fixture, creators list
spdx-only-blank-tool-creator.json changed and nothing else; edited as text,
because a JSON round trip re-encoded a
non-ASCII character in a licence body
search: grep -n '\.Tools\s*=' internal/sbom/sbom.go -> two writers, both now
reaching blank(). An earlier search for the helper name found only
what already routed through it, which is why the second was missed.
mutation: guards mutated one at a time. Weakening the CycloneDX check from
blank(name) to name == "", dropping the SPDX blank check, or dropping
either trim, each turns a named case red. Trimming the SPDX creator
turned nothing red, because both spdx readers trim before this code
sees the value, so it was removed rather than shipped untested.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>1 parent 0840e54 commit 484ec47
7 files changed
Lines changed: 1184 additions & 13 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
324 | 324 | | |
325 | 325 | | |
326 | 326 | | |
327 | | - | |
328 | | - | |
329 | | - | |
330 | | - | |
331 | | - | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
332 | 335 | | |
333 | 336 | | |
334 | 337 | | |
335 | 338 | | |
336 | 339 | | |
337 | 340 | | |
338 | 341 | | |
339 | | - | |
| 342 | + | |
340 | 343 | | |
341 | 344 | | |
342 | 345 | | |
343 | 346 | | |
344 | | - | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
345 | 353 | | |
346 | 354 | | |
347 | 355 | | |
348 | 356 | | |
349 | 357 | | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
350 | 379 | | |
351 | 380 | | |
352 | 381 | | |
| |||
404 | 433 | | |
405 | 434 | | |
406 | 435 | | |
407 | | - | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
408 | 441 | | |
409 | 442 | | |
410 | 443 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
85 | | - | |
| 85 | + | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| 89 | + | |
89 | 90 | | |
90 | | - | |
91 | | - | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
92 | 105 | | |
93 | 106 | | |
94 | 107 | | |
95 | 108 | | |
96 | 109 | | |
97 | | - | |
| 110 | + | |
98 | 111 | | |
99 | 112 | | |
100 | 113 | | |
| |||
267 | 280 | | |
268 | 281 | | |
269 | 282 | | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
270 | 306 | | |
271 | 307 | | |
272 | 308 | | |
| |||
423 | 459 | | |
424 | 460 | | |
425 | 461 | | |
426 | | - | |
| 462 | + | |
427 | 463 | | |
428 | 464 | | |
429 | 465 | | |
| |||
Lines changed: 49 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
Large diffs are not rendered by default.
0 commit comments