11#!/usr/bin/env python3
2- """Generate a CycloneDX 1.6 SBOM for Pillow's C extensions and their
2+ """Generate a CycloneDX 1.7 SBOM for Pillow's C extensions and their
33vendored/optional native library dependencies.
44
55Usage:
1010
1111from __future__ import annotations
1212
13+ import datetime as dt
14+ import hashlib
1315import json
1416import sys
1517import uuid
@@ -21,10 +23,16 @@ def get_version() -> str:
2123 return version_file .read_text (encoding = "utf-8" ).split ('"' )[1 ]
2224
2325
26+ def sha256_file (path : Path ) -> str :
27+ return hashlib .sha256 (path .read_bytes ()).hexdigest ()
28+
29+
2430def generate (version : str ) -> dict :
2531 serial = str (uuid .uuid4 ())
26- now = datetime .now (timezone .utc ).strftime ("%Y-%m-%dT%H:%M:%SZ" )
32+ now = dt . datetime .now (dt . timezone .utc ).strftime ("%Y-%m-%dT%H:%M:%SZ" )
2733 purl = f"pkg:pypi/pillow@{ version } "
34+ root = Path (__file__ ).parent .parent
35+ thirdparty = root / "src" / "thirdparty"
2836
2937 metadata_component = {
3038 "bom-ref" : purl ,
@@ -79,8 +87,21 @@ def generate(version: str) -> dict:
7987 "(vendored in src/thirdparty/raqm/)" ,
8088 "licenses" : [{"license" : {"id" : "MIT" }}],
8189 "purl" : "pkg:github/HOST-Oman/libraqm@0.10.3" ,
90+ "hashes" : [
91+ {
92+ "alg" : "SHA-256" ,
93+ "content" : sha256_file (thirdparty / "raqm" / "raqm.c" ),
94+ }
95+ ],
96+ "pedigree" : {
97+ "notes" : "Vendored unmodified from upstream HOST-Oman/libraqm v0.10.3."
98+ },
8299 "externalReferences" : [
83100 {"type" : "vcs" , "url" : "https://github.com/HOST-Oman/libraqm" },
101+ {
102+ "type" : "distribution" ,
103+ "url" : "https://github.com/HOST-Oman/libraqm/releases/tag/v0.10.3" ,
104+ },
84105 ],
85106 },
86107 {
@@ -92,6 +113,17 @@ def generate(version: str) -> dict:
92113 "(vendored in src/thirdparty/fribidi-shim/); "
93114 "loads libfribidi dynamically" ,
94115 "licenses" : [{"license" : {"id" : "LGPL-2.1-or-later" }}],
116+ "hashes" : [
117+ {
118+ "alg" : "SHA-256" ,
119+ "content" : sha256_file (
120+ thirdparty / "fribidi-shim" / "fribidi.c"
121+ ),
122+ }
123+ ],
124+ "pedigree" : {
125+ "notes" : "Pillow-authored shim; not taken from an upstream project."
126+ },
95127 "externalReferences" : [
96128 {"type" : "website" , "url" : "https://github.com/fribidi/fribidi" },
97129 ],
@@ -103,11 +135,24 @@ def generate(version: str) -> dict:
103135 "description" : "Backport header for new CPython C-API functions "
104136 "(vendored in src/thirdparty/pythoncapi_compat.h)" ,
105137 "licenses" : [{"license" : {"id" : "MIT-0" }}],
138+ "hashes" : [
139+ {
140+ "alg" : "SHA-256" ,
141+ "content" : sha256_file (thirdparty / "pythoncapi_compat.h" ),
142+ }
143+ ],
144+ "pedigree" : {
145+ "notes" : "Vendored unmodified from upstream python/pythoncapi-compat."
146+ },
106147 "externalReferences" : [
107148 {
108149 "type" : "vcs" ,
109150 "url" : "https://github.com/python/pythoncapi-compat" ,
110151 },
152+ {
153+ "type" : "distribution" ,
154+ "url" : "https://github.com/python/pythoncapi-compat/releases" ,
155+ },
111156 ],
112157 },
113158 ]
@@ -120,9 +165,17 @@ def generate(version: str) -> dict:
120165 "description" : "JPEG codec (required by default; disable with "
121166 "-C jpeg=disable). Tested with libjpeg 6b/8/9-9d "
122167 "and libjpeg-turbo 8." ,
168+ "licenses" : [
169+ {"license" : {"id" : "IJG" }},
170+ {"license" : {"id" : "BSD-3-Clause" }},
171+ ],
123172 "externalReferences" : [
124173 {"type" : "website" , "url" : "https://libjpeg-turbo.org" },
125174 {"type" : "website" , "url" : "https://ijg.org" },
175+ {
176+ "type" : "distribution" ,
177+ "url" : "https://github.com/libjpeg-turbo/libjpeg-turbo/releases" ,
178+ },
126179 ],
127180 },
128181 {
@@ -131,120 +184,187 @@ def generate(version: str) -> dict:
131184 "name" : "zlib" ,
132185 "description" : "Deflate/PNG compression (required by default; "
133186 "disable with -C zlib=disable)." ,
187+ "licenses" : [{"license" : {"id" : "Zlib" }}],
134188 "externalReferences" : [
135189 {"type" : "website" , "url" : "https://zlib.net" },
190+ {"type" : "distribution" , "url" : "https://zlib.net/" },
136191 ],
137192 },
138193 {
139194 "bom-ref" : "pkg:generic/libtiff" ,
140195 "type" : "library" ,
141196 "name" : "libtiff" ,
197+ "scope" : "optional" ,
142198 "description" : "TIFF codec (optional). Tested with libtiff 4.0-4.7.1." ,
199+ "licenses" : [{"license" : {"id" : "HPND" }}],
143200 "externalReferences" : [
144201 {"type" : "website" , "url" : "https://libtiff.gitlab.io/libtiff/" },
202+ {
203+ "type" : "distribution" ,
204+ "url" : "https://download.osgeo.org/libtiff/" ,
205+ },
145206 ],
146207 },
147208 {
148209 "bom-ref" : "pkg:generic/freetype2" ,
149210 "type" : "library" ,
150211 "name" : "FreeType" ,
212+ "scope" : "optional" ,
151213 "description" : "Font rendering (optional, used by PIL._imagingft). "
152214 "Required for text/font support." ,
215+ "licenses" : [{"license" : {"id" : "FTL" }}],
153216 "externalReferences" : [
154217 {"type" : "website" , "url" : "https://freetype.org" },
218+ {
219+ "type" : "distribution" ,
220+ "url" : "https://download.savannah.gnu.org/releases/freetype/" ,
221+ },
155222 ],
156223 },
157224 {
158225 "bom-ref" : "pkg:generic/littlecms2" ,
159226 "type" : "library" ,
160227 "name" : "Little CMS 2" ,
228+ "scope" : "optional" ,
161229 "description" : "Colour management (optional, used by PIL._imagingcms). "
162230 "Tested with lcms2 2.7-2.18." ,
231+ "licenses" : [{"license" : {"id" : "MIT" }}],
163232 "externalReferences" : [
164233 {"type" : "website" , "url" : "https://www.littlecms.com" },
234+ {
235+ "type" : "distribution" ,
236+ "url" : "https://github.com/mm2/Little-CMS/releases" ,
237+ },
165238 ],
166239 },
167240 {
168241 "bom-ref" : "pkg:generic/libwebp" ,
169242 "type" : "library" ,
170243 "name" : "libwebp" ,
244+ "scope" : "optional" ,
171245 "description" : "WebP codec (optional, used by PIL._webp)." ,
246+ "licenses" : [{"license" : {"id" : "BSD-3-Clause" }}],
172247 "externalReferences" : [
173248 {
174249 "type" : "website" ,
175250 "url" : "https://chromium.googlesource.com/webm/libwebp" ,
176251 },
252+ {
253+ "type" : "distribution" ,
254+ "url" : "https://chromium.googlesource.com/webm/libwebp" ,
255+ },
177256 ],
178257 },
179258 {
180259 "bom-ref" : "pkg:generic/openjpeg" ,
181260 "type" : "library" ,
182261 "name" : "OpenJPEG" ,
262+ "scope" : "optional" ,
183263 "description" : "JPEG 2000 codec (optional). "
184264 "Tested with openjpeg 2.0.0-2.5.4." ,
265+ "licenses" : [{"license" : {"id" : "BSD-2-Clause" }}],
185266 "externalReferences" : [
186267 {"type" : "website" , "url" : "https://www.openjpeg.org" },
268+ {
269+ "type" : "distribution" ,
270+ "url" : "https://github.com/uclouvain/openjpeg/releases" ,
271+ },
187272 ],
188273 },
189274 {
190275 "bom-ref" : "pkg:generic/libavif" ,
191276 "type" : "library" ,
192277 "name" : "libavif" ,
278+ "scope" : "optional" ,
193279 "description" : "AVIF codec (optional, used by PIL._avif). "
194280 "Requires libavif >= 1.0.0." ,
281+ "licenses" : [{"license" : {"id" : "BSD-2-Clause" }}],
195282 "externalReferences" : [
196283 {"type" : "website" , "url" : "https://github.com/AOMediaCodec/libavif" },
284+ {
285+ "type" : "distribution" ,
286+ "url" : "https://github.com/AOMediaCodec/libavif/releases" ,
287+ },
197288 ],
198289 },
199290 {
200291 "bom-ref" : "pkg:generic/harfbuzz" ,
201292 "type" : "library" ,
202293 "name" : "HarfBuzz" ,
294+ "scope" : "optional" ,
203295 "description" : "Text shaping (optional, required by libraqm "
204296 "for complex text layout)." ,
297+ "licenses" : [{"license" : {"id" : "MIT" }}],
205298 "externalReferences" : [
206299 {"type" : "website" , "url" : "https://harfbuzz.github.io" },
300+ {
301+ "type" : "distribution" ,
302+ "url" : "https://github.com/harfbuzz/harfbuzz/releases" ,
303+ },
207304 ],
208305 },
209306 {
210307 "bom-ref" : "pkg:generic/fribidi" ,
211308 "type" : "library" ,
212309 "name" : "FriBiDi" ,
310+ "scope" : "optional" ,
213311 "description" : "Unicode bidi algorithm library (optional, "
214312 "loaded at runtime by fribidi-shim)." ,
313+ "licenses" : [{"license" : {"id" : "LGPL-2.1-or-later" }}],
215314 "externalReferences" : [
216315 {"type" : "website" , "url" : "https://github.com/fribidi/fribidi" },
316+ {
317+ "type" : "distribution" ,
318+ "url" : "https://github.com/fribidi/fribidi/releases" ,
319+ },
217320 ],
218321 },
219322 {
220323 "bom-ref" : "pkg:generic/libimagequant" ,
221324 "type" : "library" ,
222325 "name" : "libimagequant" ,
326+ "scope" : "optional" ,
223327 "description" : "Improved colour quantization (optional). "
224328 "Tested with 2.6-4.4.1. NOTE: GPLv3 licensed." ,
225329 "licenses" : [{"license" : {"id" : "GPL-3.0-only" }}],
226330 "externalReferences" : [
227331 {"type" : "website" , "url" : "https://pngquant.org/lib/" },
332+ {
333+ "type" : "distribution" ,
334+ "url" : "https://github.com/ImageOptim/libimagequant/releases" ,
335+ },
228336 ],
229337 },
230338 {
231339 "bom-ref" : "pkg:generic/libxcb" ,
232340 "type" : "library" ,
233341 "name" : "libxcb" ,
342+ "scope" : "optional" ,
234343 "description" : "X11 screen-grab support (optional, "
235344 "used by PIL._imagingtk on Linux)." ,
345+ "licenses" : [{"license" : {"id" : "MIT" }}],
236346 "externalReferences" : [
237347 {"type" : "website" , "url" : "https://xcb.freedesktop.org" },
348+ {
349+ "type" : "distribution" ,
350+ "url" : "https://xcb.freedesktop.org/dist/" ,
351+ },
238352 ],
239353 },
240354 {
241355 "bom-ref" : "pkg:pypi/pybind11" ,
242356 "type" : "library" ,
243357 "name" : "pybind11" ,
358+ "scope" : "optional" ,
244359 "description" : "C++/Python binding library "
245360 "(build-time dependency for PIL._imagingmath)." ,
361+ "licenses" : [{"license" : {"id" : "BSD-3-Clause" }}],
246362 "externalReferences" : [
247363 {"type" : "website" , "url" : "https://pybind11.readthedocs.io" },
364+ {
365+ "type" : "distribution" ,
366+ "url" : "https://github.com/pybind/pybind11/releases" ,
367+ },
248368 ],
249369 },
250370 ]
@@ -300,11 +420,12 @@ def generate(version: str) -> dict:
300420
301421 return {
302422 "bomFormat" : "CycloneDX" ,
303- "specVersion" : "1.6 " ,
423+ "specVersion" : "1.7 " ,
304424 "serialNumber" : f"urn:uuid:{ serial } " ,
305425 "version" : 1 ,
306426 "metadata" : {
307427 "timestamp" : now ,
428+ "lifecycles" : [{"phase" : "build" }],
308429 "tools" : [
309430 {
310431 "type" : "application" ,
0 commit comments