Generate CycloneDX SBOM at release time via CI#9550
Generate CycloneDX SBOM at release time via CI#9550aclark4life wants to merge 17 commits intomainfrom
Conversation
| 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
| "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.
.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
There was a problem hiding this comment.
@jkowalleck Isolated outside of wheels.yml you mean? Here's what we have now:
|
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. 👍 |
.github/generate-sbom.py
Outdated
| } | ||
| ], | ||
| "pedigree": { | ||
| "notes": "Vendored unmodified from upstream HOST-Oman/libraqm v0.10.5." |
There was a problem hiding this comment.
It's not completely unmodified.
See
https://github.com/HOST-Oman/libraqm/blob/main/src/raqm-version.h.in#L34
vs
https://github.com/python-pillow/Pillow/blob/main/src/thirdparty/raqm/raqm-version.h#L34
(and also note that the filename is changed)
and
https://github.com/HOST-Oman/libraqm/blob/main/src/raqm.c#L39
vs
https://github.com/python-pillow/Pillow/blob/main/src/thirdparty/raqm/raqm.c#L39
diff --git a/src/thirdparty/raqm/raqm-version.h b/src/thirdparty/raqm/raqm-version.h
index 93b20d23f..9908f06bd 100644
--- a/src/thirdparty/raqm/raqm-version.h
+++ b/src/thirdparty/raqm/raqm-version.h
@@ -31,14 +31,14 @@
#ifndef _RAQM_VERSION_H_
#define _RAQM_VERSION_H_
-#define RAQM_VERSION_MAJOR @RAQM_VERSION_MAJOR@
-#define RAQM_VERSION_MINOR @RAQM_VERSION_MINOR@
-#define RAQM_VERSION_MICRO @RAQM_VERSION_MICRO@
+#define RAQM_VERSION_MAJOR 0
+#define RAQM_VERSION_MINOR 10
+#define RAQM_VERSION_MICRO 5
-#define RAQM_VERSION_STRING "@RAQM_VERSION@"
+#define RAQM_VERSION_STRING "0.10.5"
#define RAQM_VERSION_ATLEAST(major,minor,micro) \
- ((major)*10000+(minor)*100+(micro) <= \
- RAQM_VERSION_MAJOR*10000+RAQM_VERSION_MINOR*100+RAQM_VERSION_MICRO)
+ ((major)*10000+(minor)*100+(micro) <= \
+ RAQM_VERSION_MAJOR*10000+RAQM_VERSION_MINOR*100+RAQM_VERSION_MICRO)
#endif /* _RAQM_VERSION_H_ */
diff --git a/src/thirdparty/raqm/raqm.c b/src/thirdparty/raqm/raqm.c
index 5b2690978..88bbbfd5e 100644
--- a/src/thirdparty/raqm/raqm.c
+++ b/src/thirdparty/raqm/raqm.c
@@ -36,7 +36,11 @@
#include <SheenBidi.h>
#endif
#else
+#ifdef HAVE_FRIBIDI_SYSTEM
#include <fribidi.h>
+#else
+#include "../fribidi-shim/fribidi.h"
+#endif
#endif
#include <hb.h>There was a problem hiding this comment.
It's not completely unmodified.
modifications can be tracked in the SBOM: https://cyclonedx.org/use-cases/pedigree/
| ] | ||
|
|
||
| vendored_components = [ | ||
| { |
.github/generate-sbom.py
Outdated
| } | ||
| ], | ||
| "pedigree": { | ||
| "notes": "Vendored unmodified from upstream HOST-Oman/libraqm v0.10.5." |
There was a problem hiding this comment.
It's not completely unmodified.
modifications can be tracked in the SBOM: https://cyclonedx.org/use-cases/pedigree/
| "specVersion": "1.6", | ||
| "serialNumber": f"urn:uuid:{serial}", | ||
| "version": 1, | ||
| "metadata": { |
- 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>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
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
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
Co-authored-by: Jan Kowalleck <jan.kowalleck@gmail.com>
for more information, see https://pre-commit.ci
The vendored raqm files are from v0.10.3 (not v0.10.5 as previously
stated) and contain two Pillow-specific modifications. Document these
via the CycloneDX pedigree field as requested in the review:
- Correct version: 0.10.3 (raqm-version.h says 0.10.3; raqm.c matches
upstream 0.10.3 + one local patch)
- Add pedigree.ancestors pointing to the upstream v0.10.3 release
- Add two pedigree.patches with base64-encoded unified diffs:
1. type=generated: raqm-version.h.in pre-processed into raqm-version.h
(template placeholders replaced with literal 0.10.3 values)
2. type=unofficial: raqm.c wrapped the <fribidi.h> include in an
#ifdef HAVE_FRIBIDI_SYSTEM guard to support Pillow's fribidi-shim
- Update notes to accurately describe both modifications
- Update all bom-ref/purl/dependsOn references from 0.10.5 to 0.10.3
Addresses: https://cyclonedx.org/use-cases/pedigree/
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The vendored raqm files have been upgraded to v0.10.5. Update all version references in the SBOM (bom-ref, purl, version, ancestor, distribution URL, dependsOn, notes) from 0.10.3 to 0.10.5. The same two Pillow-specific patches still apply: 1. raqm-version.h.in pre-processed with 0.10.5 literal values 2. raqm.c fribidi-shim #ifdef guard (unchanged) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>


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.