Generate CycloneDX SBOM at release time via CI#9550
Generate CycloneDX SBOM at release time via CI#9550aclark4life wants to merge 10 commits intomainfrom
Conversation
- Add .github/generate-sbom.py: reads the real version from src/PIL/_version.py and emits a CycloneDX 1.6 JSON SBOM covering the 8 C extension modules, 3 vendored thirdparty libraries, and 13 optional native library dependencies. - Add 'sbom' job to wheels.yml: runs on tag pushes, generates the SBOM, uploads it as a workflow artifact, and attaches it to the GitHub release via 'gh release upload'. - Remove the static pillow.cdx.json; CI now owns the generated file. Can also be run locally: python .github/generate-sbom.py Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| for name, desc in c_extensions | ||
| ] | ||
|
|
||
| vendored_components = [ |
There was a problem hiding this comment.
are these vendored_components untouched or are they patched somehow?
If they were modified, it would be good to know in which way -- see https://cyclonedx.org/use-cases/pedigree/
| }, | ||
| ] | ||
|
|
||
| native_deps = [ |
There was a problem hiding this comment.
I am missing the licenses of those native_deps.
I see them in https://github.com/python-pillow/Pillow/tree/main/wheels/dependency_licenses
you may add the license ID, and even the texts - https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_licenses_items_oneOf_i0_license_text
| }, | ||
| ] | ||
|
|
||
| native_deps = [ |
There was a problem hiding this comment.
some of the native_deps appear to be optional. better mark them as that.
see CycloneDX' component scope - https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_scope
|
Once everything is flushed out, may I ask you to showcase your SBOMs in the official examples repo? And when shipping the SBOM in the wheel ala PEP770, maybe give https://github.com/psf/sboms-for-python-packages a quick notice :) |
| ] | ||
|
|
||
| vendored_components = [ | ||
| { |
There was a problem hiding this comment.
maybe add a checksum in them, too?
see https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_hashes
| "description": "JPEG codec (required by default; disable with " | ||
| "-C jpeg=disable). Tested with libjpeg 6b/8/9-9d " | ||
| "and libjpeg-turbo 8.", | ||
| "externalReferences": [ |
There was a problem hiding this comment.
where did you fetch them from? have a distribution url?
see https://cyclonedx.org/docs/1.7/json/#metadata_tools_oneOf_i0_components_items_externalReferences_items_type
.github/generate-sbom.py
Outdated
|
|
||
| return { | ||
| "bomFormat": "CycloneDX", | ||
| "specVersion": "1.6", |
There was a problem hiding this comment.
just go with "1.7" - the adoption in ingesting tools should be good today
| "specVersion": "1.6", | ||
| "serialNumber": f"urn:uuid:{serial}", | ||
| "version": 1, | ||
| "metadata": { |
There was a problem hiding this comment.
lets add metadata.lifecycles = [ "build" ]
see https://cyclonedx.org/docs/1.7/json/#metadata_lifecycles_items_oneOf_i0_phase
| name: sbom | ||
| path: "*.cdx.json" | ||
|
|
||
| - name: Attach SBOM to GitHub release |
There was a problem hiding this comment.
better move the job condition to here:
if: github.repository_owner == 'python-pillow' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
this way, you would have an SBOM artifact even for tests - which might come in handy at some point. - during review of changes and such ...
and you would not have any surprises on releases, surprises that you could have seen in regular CI runs
There was a problem hiding this comment.
PS: if you have your SBOM artifact available, you might test it for validity and context.
There might be automated validators out there, like https://pypi.org/project/cyclonedx-python-lib/ can do this https://cyclonedx-python-library.readthedocs.io/en/latest/examples.html#complex-validation
To test the value, you might use visualizers like https://cyclonedx.studio/
The practical use of the SBOM would be, besides shipping it in PEP770 style, to feed the SBOM into some sort of tool that analyzes the SBOM and warns about new findings anachronously - like https://dependencytrack.org/ can do.
This way you would get alerts on shipped versions and might yank a vulnerable ones from package registries, and write the appropriate Security Advisory accordingly.
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
.github/workflows/wheels.yml
Outdated
|
|
||
| sbom: | ||
| if: github.repository_owner == 'python-pillow' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags') | ||
| needs: count-dists |
There was a problem hiding this comment.
There was a problem hiding this comment.
probably a very good idea to have the SBOM process isolated.
you are not using target-specific components , or do you?
Like on the windows build, you use this C library, and in the MacOS, you use a different one.
I mean, if you were having target-specific components, then you would need target-specific SBOMs generated on bdist's build-time (and additionally put the correct one in the respective wheel - if the bdist process would support PEP 770).
There was a problem hiding this comment.
Yes, there are platform differences, like iOS disabling raqm and imagequant:
Lines 108 to 110 in 7cf4dac
|
It would be great to get this eventually into the wheels (PEP 770) but that likely needs extra tooling, and generating and adding to the GH release is a good first step. 👍 |
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
for more information, see https://pre-commit.ci
- Fix missing datetime/hashlib imports; use datetime as dt
- Bump specVersion from 1.6 to 1.7
- Add metadata.lifecycles = [{"phase": "build"}]
- Add SHA-256 hashes to vendored components (raqm, fribidi-shim, pythoncapi_compat)
- Add pedigree notes clarifying whether vendored components are patched
- Add distribution externalReferences to vendored and native dep components
- Add SPDX license IDs to all native dependencies
- Mark optional native dependencies with scope: optional
- Split sbom job: generate early (no bottleneck), publish separately after count-dists
- Add .github/generate-sbom.py to push/PR trigger paths
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
for more information, see https://pre-commit.ci


Includes all 8 C extension modules, 3 vendored thirdparty libraries (raqm 0.10.3, fribidi-shim, pythoncapi_compat), and 13 optional native library dependencies with encoded dependency relationships.