From bdbeef2cd4b7ad5c17e69f38127e98ee9eeae597 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Tue, 19 Nov 2024 08:13:45 -0600 Subject: [PATCH 1/8] PEP 9999: SBOMs draft --- peps/pep-9999.rst | 321 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 peps/pep-9999.rst diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst new file mode 100644 index 00000000000..5a28cf8d018 --- /dev/null +++ b/peps/pep-9999.rst @@ -0,0 +1,321 @@ +PEP: 9999 +Title: Improving measurability for Python packages with Software Bill-of-Materials +Author: Seth Larson +Sponsor: Brett Cannon +PEP-Delegate: Brett Cannon +Discussions-To: https://discuss.python.org/t/70261 +Status: Draft +Type: Standards Track +Topic: Packaging +Created: 15-Nov-2024 + +Abstract +======== + +Software Bill-of-Materials (SBOM) are a technology-and-ecosystem-agnostic +method for describing software composition, provenance, licensing, and more. +SBOMs are used as inputs for software composition analysis (SCA) tools, +such as scanners for vulnerabilities and licenses, and have been gaining +traction in global software regulations and frameworks. + +This PEP proposes using SBOM documents included in Python packages as a +means to improve software measurability for Python packages. + +Motivation +========== + +Measurability and Phantom Dependencies +-------------------------------------- + +Python packages are particularly affected by the "`phantom dependency`_" problem, +where software components that aren't written in Python are included in Python packages +for many reasons, such as ease of installation and compatibility with standards: + +* Python serves scientific, data, web, and machine-learning use-cases which use compiled or non-Python languages like Rust, C, C++, Fortran, JavaScript, and others. +* The Python wheel format is preferred by users due to the ease-of-installation. No code is executed during the installation step, only extracting the archive. +* The Python wheel format requires bundling shared compiled libraries without a method to encode metadata about these libraries. +* Packages related to Python packaging sometimes need to solve the "bootstrapping" problem, + so include pure Python projects inside their source code. + +These software components can't be described using Python package metadata and thus +are likely to be missed by software composition analysis (SCA) software which can mean +vulnerable software components aren't reported accurately. + +.. _phantom dependency: https://www.endorlabs.com/learn/dependency-resolution-in-python-beware-the-phantom-dependency + +Regulations +----------- + +SBOMs are required by recent software security regulations, like the `Secure Software Development Framework`_ (SSDF) +and the `Cyber Resilience Act`_ (CRA). Due to their inclusion in these regulations, the demand for SBOM documents of open source projects is expected to be high. +One goal is to minimize the demands on open source project maintainers by enabling +open source users that need SBOMs to self-serve using existing tooling. + +Another goal is to enable contributions from users who need SBOMs to annotate projects they depend on with SBOM information. +Today there is no mechanism to propagate the results of those contributions for a Python package so there is no incentive +for users to contribute this type of work. + +.. _Cyber Resilience Act: https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act +.. _Secure Software Development Framework: https://csrc.nist.gov/Projects/ssdf + +Rationale +========= + +Using SBOM standards instead of core metadata fields +---------------------------------------------------- + +Attempting to add every field offered by SBOM standards into Python package core metadata +would result in an explosion of new core metadata fields, including the need to keep up-to-date as +SBOM standards continue to evolve to suit new needs in that space. + +Instead, this proposal delegates SBOM-specific metadata to SBOM documents that are included in Python packages +and adds a new Python core metadata field for discoverability of included SBOM documents. + +This standard also doesn't aim to replace Python core metadata with SBOMs, instead +focusing on the SBOM information being supplemental to core metadata. +Included SBOMs only contain information about dependencies included in the package archive +or information about the top-level software in the package that can't be encoded into core metadata +but is relevant for the SBOM use-case ("software identifiers", "purpose", "support level", etc). + +Zero-or-more SBOM documents per package +--------------------------------------- + +Rather than requiring at most one included SBOM document per Python package, this PEP proposes +that one or more SBOM documents may be included in a Python package. This means that code +attempting to annotate a Python package with SBOM data may do so without being concerned +about corrupting data already contained within other SBOM documents. This decision +also means this PEP is capable of supporting multiple SBOM standards without favoring one, +instead deferring support to SBOM consuming tools. + +Specification +============= + +The changes necessary to implement this PEP include: + +* Additions to :ref:`Core Metadata <9999-spec-core-metadata>`, as defined in the `specification `_. +* Additions to the author-provided :ref:`project source metadata <9999-spec-source-metadata>`, as defined in the `specification `_. +* :ref:`Additions <9999-spec-project-formats>`_ to the source distribution (sdist), built distribution (wheel), and installed project specifications. + +In addition to the above, an informational PEP will be created for tools +consuming included SBOM documents and other Python package metadata to +generate complete SBOM documents for Python packages. + +Core Metadata +------------- + +Add ``Sbom-File`` field +~~~~~~~~~~~~~~~~~~~~~~~ + +The ``Sbom-File`` is an optional Core Metadata field. Each instance +contains a string representation of the path of an SBOM document. +The path is located within the project source tree, relative to the project +root directory. It is a multi-use field that MAY appear zero or more times +and each instance lists the path to one such file. Files specified under this field + +As specified by this PEP, its value is also that file's path relative to the root +SBOM directory in both installed projects and the standardized Distribution Package types. + +If a ``Sbom-File`` is listed in a Source Distribution or Built Distribution's Core metadata: + +* That file MUST be included in the distribution archive at the specified path relative to the root license directory. +* That file MUST be installed with the project at that same relative path. +* Inside the root SBOM directory, packaging tools MUST reproduce the directory structure under which the source files are located relative to the project root. +* Path delimiters MUST be the forward slash character (``\/``), and parent directory indicators (``..``) MUST NOT be used. +* SBOM document contents MUST be UTF-8 encoded JSON according to :rfc:`8259`. +* SBOM document contents MUST use an SBOM standard, and for better interoperability + SHOULD be a well-known SBOM standard such as CycloneDX or SPDX. +* The "primary" component being described in included SBOM documents MUST be the Python package. + This is achieved in CycloneDX using the ``metadata.component`` field and in SPDX using the ``DESCRIBES`` + relationship. +* SBOM documents MUST include metadata for the timestamp when the SBOM document was created. + This information helps consuming tools understand the order that multiple SBOM documents were created + to untangle conflicts between various stages building the Python package. +* SBOM documents SHOULD include metadata describing the tool creating the SBOM document. + This information helps users find which tool needs to be fixed in the case of defects. + +For all newly-uploaded distribution archives that include one or more ``Sbom-File`` fields in their Core Metadata +and declare a ``Metadata-Version`` of ``2.5`` or higher, PyPI SHOULD validate that all specified files are present +in the distribution archives, are valid UTF-8 encoded JSON, and for well-known SBOM standards provide the minimum +required fields by those standards and this PEP. + +Project source metadata +----------------------- + +This PEP specifies changes to the project's source metadata under a ``[project]`` table in the ``pyproject.toml`` file. + +Add ``sbom-files`` key +~~~~~~~~~~~~~~~~~~~~~~ + +A new ``sbom-files`` key is added to the ``[project]`` table for specifying paths in the project source tree +relative to ``pyproject.toml`` to file(s) containing SBOMs to be distributed with the package. This key corresponds +to the ``Sbom-File`` fields in the Core Metadata. + +Its value is an array of strings which MUST contain valid glob patterns, as specified below: + +* Alphanumeric characters, underscores (``_``), hyphens (``-``) and dots (``.``) MUST be matched verbatim. +* Special glob characters: ``*``, ``?``, ``**`` and character ranges: ``[]`` containing only the verbatim matched characters MUST be supported. Within ``[...]``, the hyphen indicates a locale-agnostic range (e.g. a-z, order based on Unicode code points). Hyphens at the start or end are matched literally. +* Path delimiters MUST be the forward slash character (``/``). Patterns are relative to the directory containing pyproject.toml, therefore the leading slash character MUST NOT be used. +* Parent directory indicators (``..``) MUST NOT be used. + +Any characters or character sequences not covered by this specification are invalid. Projects MUST NOT use such values. Tools consuming this field SHOULD reject invalid values with an error. + +Tools MUST assume that SBOM file content is valid UTF-8 encoded JSON, and SHOULD validate this an raise an error if it is not. + +Literal paths (`e.g. ``bom.cdx.json``) are treated as valid globs which means they can also be defined. + +Build tools: + +* MUST treat each value as a glob pattern, and MUST raise an error if the pattern contains invalid glob syntax. +* MUST include all files matched by a listed pattern in all distribution archives. +* MUST list each matched file path under a ``Sbom-File`` field in the Core Metadata. +* MUST raise an error if any individual user-specified pattern does not match at least one file. + +If the ``sbom-files`` key is present and is set to a value of an empty array, then tools MUST NOT include +any SBOM files and MUST NOT raise an error. + +Examples of valid SBOM files declarations: + +.. code-block:: toml + + [project] + sbom-files = ["bom.json"] + + [project] + sbom-files = ["sboms/openssl.cdx.json", "licenses/openssl.spdx.json"] + + [project] + sbom-files = ["sboms/*"] + + [project] + sbom-files = [] + +Examples of invalid SBOM files declarations: + +.. code-block:: toml + + [project] + sbom-files = ["..\bom.json"] + +Reason: ``..`` must not be used. ``\\`` is an invalid path delimited, ``\/`` must be used. + +.. code-block:: toml + + [project] + sbom-files = ["bom{.json*"] + +Reason: "bom{.json" is not a valid glob. + +SBOM files in project formats +----------------------------- + +A few additions will be made to the existing specifications. + +:term:`Project source tree`\s + Per :ref:`639-spec-source-metadata` section, the + `Declaring Project Metadata specification `__ + will be updated to reflect that SBOM file paths MUST be relative to the + project root directory; i.e. the directory containing the ``pyproject.toml`` + (or equivalently, other legacy project configuration, + e.g. ``setup.py``, ``setup.cfg``, etc). + +:term:`Source distributions (sdists) ` + + The sdist specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater, + the sdist MUST contain any SBOM files specified by the ``Sbom-File`` field in the ``PKG-INFO`` at their + respective paths relative to the sdist (containing the ``pyproject.toml`` and the ``PKG-INFO`` Core Metadata). + +:term:`Built distribution`\s (:term:`wheel`\s) + + The wheel specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater + and one or more ``Sbom-File`` fields are specified, the ``.dist-info`` directory MUST contain a ``sboms`` + subdirectory, which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file at + their respective paths relative to the ``sboms`` directory. + +:term:`Installed project`\s + + The Recording Installed Projects specification will be updated to reflect that if the ``Metadata-Version`` is + ``2.5`` or greater and one or more ``Sbom-File`` fields is specified, the ``.dist-info`` directory MUST contain + a ``sboms`` subdirectory which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file + at their respective paths relative to the ``sboms`` directory, and that any files in this directory MUST be + copied from wheels by install tools. + +Backwards Compatibility +======================= + +There are no backwards compatibility concerns for this PEP. + +The changes to Python package core metadata and ``pyproject.toml`` are +only additive, this PEP doesn't change the behavior of any existing fields. + +Tools which are processing Python packages can use the ``Sbom-File`` core +metadata field to clearly delineate between packages which include SBOM +documents that implement this PEP (and thus have more requirements) and +packages which include SBOM documents before this PEP was authored. + +Security Implications +===================== + +Because SBOM documents can encode information about the original system +where a Python package is built (for example, the operating system name and +version, more rarely the names of paths) this information has the potential +to "leak" through the Python package to installers. If this information is sensitive, +then that could represent a security risk. + +TODO(More security implications, phantom dependencies) + +How to Teach This +================= + +Most Python packages don't contain code from other software components and thus are already +measurable by SCA tools without the need of SBOM documents. + +TODO(Add section on informational PEP for SBOM tools) + +Reference Implementation +======================== + +[Link to any existing implementation and details about its state, e.g. proof-of-concept.] + +TODO(Add reference impls) + +Rejected Ideas +============== + +Why not require a single SBOM standard? +--------------------------------------- + +Most discussion and development around SBOMs today focuses on two SBOM standards: +CycloneDX and SPDX. There is no clear "winner" between these two standards, +both standards are frequently used by projects and software ecosystems. + +Because both standards are frequently used, tools for consuming and processing +SBOM documents commonly need to support both standards. This means that this PEP +is not constrained to select a single SBOM standard by its consumers and thus +can allow tools creating SBOM documents for inclusion in Python packages to +choose which SBOM standard works best for their use-case. + +Open Issues +=========== + +Conditional project source SBOM files +------------------------------------- + +How can a project specify an SBOM file that is conditional? + +Footnotes +========= + +[A collection of footnotes cited in the PEP, and a place to list non-inline hyperlink targets.] + +Acknowledgements +================ + +* Karolina Surma for authoring and seeing :pep:`639` to acceptance, of which much of the design + for specifying files in project source metadata, core metadata, and project formats is based on. + + +Copyright +========= + +This document is placed in the public domain or under the +CC0-1.0-Universal license, whichever is more permissive. From 6cf0953b8b515f433f6796ea26359510fca8f45a Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Tue, 26 Nov 2024 11:33:02 -0600 Subject: [PATCH 2/8] Add references, how to teach, and security considerations --- peps/pep-9999.rst | 358 ++++++++++++++++++++++++++++++---------------- 1 file changed, 231 insertions(+), 127 deletions(-) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index 5a28cf8d018..a28e0e6752e 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -1,5 +1,5 @@ PEP: 9999 -Title: Improving measurability for Python packages with Software Bill-of-Materials +Title: Improving measurability of Python packages with Software Bill-of-Materials Author: Seth Larson Sponsor: Brett Cannon PEP-Delegate: Brett Cannon @@ -13,7 +13,7 @@ Abstract ======== Software Bill-of-Materials (SBOM) are a technology-and-ecosystem-agnostic -method for describing software composition, provenance, licensing, and more. +method for describing software composition, provenance, heritage, and more. SBOMs are used as inputs for software composition analysis (SCA) tools, such as scanners for vulnerabilities and licenses, and have been gaining traction in global software regulations and frameworks. @@ -21,39 +21,50 @@ traction in global software regulations and frameworks. This PEP proposes using SBOM documents included in Python packages as a means to improve software measurability for Python packages. +The changes will update the +`Core Metadata specification `__ to version 2.5. + Motivation ========== Measurability and Phantom Dependencies -------------------------------------- -Python packages are particularly affected by the "`phantom dependency`_" problem, -where software components that aren't written in Python are included in Python packages -for many reasons, such as ease of installation and compatibility with standards: - -* Python serves scientific, data, web, and machine-learning use-cases which use compiled or non-Python languages like Rust, C, C++, Fortran, JavaScript, and others. -* The Python wheel format is preferred by users due to the ease-of-installation. No code is executed during the installation step, only extracting the archive. -* The Python wheel format requires bundling shared compiled libraries without a method to encode metadata about these libraries. -* Packages related to Python packaging sometimes need to solve the "bootstrapping" problem, - so include pure Python projects inside their source code. - -These software components can't be described using Python package metadata and thus -are likely to be missed by software composition analysis (SCA) software which can mean -vulnerable software components aren't reported accurately. - -.. _phantom dependency: https://www.endorlabs.com/learn/dependency-resolution-in-python-beware-the-phantom-dependency +Python packages are particularly affected by the "`phantom dependency`_" +problem, where software components that aren't written in Python are included +in Python packages for many reasons, such as ease of installation and +compatibility with standards: + +* Python serves scientific, data, web, and machine-learning use-cases which + use compiled or non-Python languages like Rust, C, C++, Fortran, JavaScript, + and others. +* The Python wheel format is preferred by users due to the ease-of-installation. + No code is executed during the installation step, only extracting the archive. +* The Python wheel format requires bundling shared compiled libraries without + a method to encode metadata about these libraries. +* Packages related to Python packaging sometimes need to solve the + "bootstrapping" problem, so include pure Python projects inside their + source code. + +These software components can't be described using Python package metadata and +thus are likely to be missed by software composition analysis (SCA) software +which can mean vulnerable software components aren't reported accurately. Regulations ----------- -SBOMs are required by recent software security regulations, like the `Secure Software Development Framework`_ (SSDF) -and the `Cyber Resilience Act`_ (CRA). Due to their inclusion in these regulations, the demand for SBOM documents of open source projects is expected to be high. -One goal is to minimize the demands on open source project maintainers by enabling -open source users that need SBOMs to self-serve using existing tooling. +SBOMs are required by recent software security regulations, like the +`Secure Software Development Framework`_ (SSDF) and the +`Cyber Resilience Act`_ (CRA). Due to their inclusion in these regulations, +the demand for SBOM documents of open source projects is expected to be high. +One goal is to minimize the demands on open source project maintainers by +enabling open source users that need SBOMs to self-serve using existing +tooling. -Another goal is to enable contributions from users who need SBOMs to annotate projects they depend on with SBOM information. -Today there is no mechanism to propagate the results of those contributions for a Python package so there is no incentive -for users to contribute this type of work. +Another goal is to enable contributions from users who need SBOMs to annotate +projects they depend on with SBOM information. Today there is no mechanism to +propagate the results of those contributions for a Python package so there is +no incentive for users to contribute this type of work. .. _Cyber Resilience Act: https://digital-strategy.ec.europa.eu/en/policies/cyber-resilience-act .. _Secure Software Development Framework: https://csrc.nist.gov/Projects/ssdf @@ -61,117 +72,166 @@ for users to contribute this type of work. Rationale ========= -Using SBOM standards instead of core metadata fields +Using SBOM standards instead of Core Metadata fields ---------------------------------------------------- -Attempting to add every field offered by SBOM standards into Python package core metadata -would result in an explosion of new core metadata fields, including the need to keep up-to-date as -SBOM standards continue to evolve to suit new needs in that space. +Attempting to add every field offered by SBOM standards into Python package +Core Metadata would result in an explosion of new Core Metadata fields, +including the need to keep up-to-date as SBOM standards continue to evolve +to suit new needs in that space. -Instead, this proposal delegates SBOM-specific metadata to SBOM documents that are included in Python packages -and adds a new Python core metadata field for discoverability of included SBOM documents. +Instead, this proposal delegates SBOM-specific metadata to SBOM documents that +are included in Python packages and adds a new Core Metadata field for +discoverability of included SBOM documents. -This standard also doesn't aim to replace Python core metadata with SBOMs, instead -focusing on the SBOM information being supplemental to core metadata. -Included SBOMs only contain information about dependencies included in the package archive -or information about the top-level software in the package that can't be encoded into core metadata -but is relevant for the SBOM use-case ("software identifiers", "purpose", "support level", etc). +This standard also doesn't aim to replace Core Metadata with SBOMs, +instead focusing on the SBOM information being supplemental to Core Metadata. +Included SBOMs only contain information about dependencies included in the +package archive or information about the top-level software in the package that +can't be encoded into Core Metadata but is relevant for the SBOM use-case +("software identifiers", "purpose", "support level", etc). Zero-or-more SBOM documents per package --------------------------------------- -Rather than requiring at most one included SBOM document per Python package, this PEP proposes -that one or more SBOM documents may be included in a Python package. This means that code -attempting to annotate a Python package with SBOM data may do so without being concerned -about corrupting data already contained within other SBOM documents. This decision -also means this PEP is capable of supporting multiple SBOM standards without favoring one, -instead deferring support to SBOM consuming tools. +Rather than requiring at most one included SBOM document per Python package, +this PEP proposes that one or more SBOM documents may be included in a Python +package. This means that code attempting to annotate a Python package with SBOM +data may do so without being concerned about corrupting data already contained +within other SBOM documents. + +This decision also means this PEP is capable of supporting multiple SBOM +standards without favoring one, instead deferring support to SBOM consuming +tools. This decision also means that the merging of SBOM documents never needs +to be handled by Python tools, instead deferring this to SBOM consuming tools +who are better placed to handle cross-standard conversions. + +.. _9999-spec: Specification ============= The changes necessary to implement this PEP include: -* Additions to :ref:`Core Metadata <9999-spec-core-metadata>`, as defined in the `specification `_. -* Additions to the author-provided :ref:`project source metadata <9999-spec-source-metadata>`, as defined in the `specification `_. -* :ref:`Additions <9999-spec-project-formats>`_ to the source distribution (sdist), built distribution (wheel), and installed project specifications. +* Additions to `Core Metadata <9999-spec-core-metadata>`_, as defined in the + `Core Metadata specification `__. +* Additions to the author-provided + `project source metadata <9999-spec-source-metadata>`_, as defined in the + `pyproject.toml specification `__. +* `Additions <9999-spec-project-formats>`_ to the source distribution (sdist), + built distribution (wheel), and installed project specifications. In addition to the above, an informational PEP will be created for tools consuming included SBOM documents and other Python package metadata to generate complete SBOM documents for Python packages. +.. _9999-spec-core-metadata: + Core Metadata ------------- Add ``Sbom-File`` field ~~~~~~~~~~~~~~~~~~~~~~~ -The ``Sbom-File`` is an optional Core Metadata field. Each instance -contains a string representation of the path of an SBOM document. -The path is located within the project source tree, relative to the project -root directory. It is a multi-use field that MAY appear zero or more times -and each instance lists the path to one such file. Files specified under this field - -As specified by this PEP, its value is also that file's path relative to the root -SBOM directory in both installed projects and the standardized Distribution Package types. - -If a ``Sbom-File`` is listed in a Source Distribution or Built Distribution's Core metadata: - -* That file MUST be included in the distribution archive at the specified path relative to the root license directory. -* That file MUST be installed with the project at that same relative path. -* Inside the root SBOM directory, packaging tools MUST reproduce the directory structure under which the source files are located relative to the project root. -* Path delimiters MUST be the forward slash character (``\/``), and parent directory indicators (``..``) MUST NOT be used. +The ``Sbom-File`` is an optional Core Metadata field. Each instance contains a +string representation of the path of an SBOM document. The path is located +within the project source tree, relative to the project root directory. It is a +multi-use field that MAY appear zero or more times and each instance lists the +path to one such file. Files specified under this field are SBOM documents +that are distributed with the package. + +As `specified by this PEP <#9999-spec-project-formats>`__, its value is also +that file's path relative to the root SBOM directory in both installed projects +and the standardized Distribution Package types. + +If a ``Sbom-File`` is listed in a +:term:`Source Distribution ` or +:term:`Built Distribution`'s Core Metadata: + +* That file MUST be included in the :term:`distribution archive` at the + specified path relative to the root license directory. +* That file MUST be installed with the :term:`project` at that same relative + path. +* Inside the root SBOM directory, packaging tools MUST reproduce the directory + structure under which the source files are located relative to the project + root. +* Path delimiters MUST be the forward slash character (``/``), and parent + directory indicators (``..``) MUST NOT be used. * SBOM document contents MUST be UTF-8 encoded JSON according to :rfc:`8259`. -* SBOM document contents MUST use an SBOM standard, and for better interoperability - SHOULD be a well-known SBOM standard such as CycloneDX or SPDX. -* The "primary" component being described in included SBOM documents MUST be the Python package. - This is achieved in CycloneDX using the ``metadata.component`` field and in SPDX using the ``DESCRIBES`` - relationship. -* SBOM documents MUST include metadata for the timestamp when the SBOM document was created. - This information helps consuming tools understand the order that multiple SBOM documents were created - to untangle conflicts between various stages building the Python package. -* SBOM documents SHOULD include metadata describing the tool creating the SBOM document. - This information helps users find which tool needs to be fixed in the case of defects. - -For all newly-uploaded distribution archives that include one or more ``Sbom-File`` fields in their Core Metadata -and declare a ``Metadata-Version`` of ``2.5`` or higher, PyPI SHOULD validate that all specified files are present -in the distribution archives, are valid UTF-8 encoded JSON, and for well-known SBOM standards provide the minimum -required fields by those standards and this PEP. +* SBOM document contents MUST use an SBOM standard, and for better + interoperability SHOULD be a well-known SBOM standard such as + `CycloneDX `_ or `SPDX `_. +* The "primary" component being described in included SBOM documents MUST be the + Python package. This is achieved in CycloneDX using the ``metadata.component`` + field and in SPDX using the ``DESCRIBES`` relationship. +* SBOM documents MUST include metadata for the timestamp when the SBOM document + was created. This information helps consuming tools understand the order that + multiple SBOM documents were created to untangle conflicts between various + stages building the Python package. +* SBOM documents SHOULD include metadata describing the tool creating the SBOM + document. This information helps users find which tool needs to be fixed in + the case of defects. + +For all newly-uploaded distribution archives that include one or more +``Sbom-File`` fields in their Core Metadata and declare a ``Metadata-Version`` +of ``2.5`` or higher, PyPI SHOULD validate that all specified files are present +in the distribution archives, are valid UTF-8 encoded JSON, and for well-known +SBOM standards provide the minimum required fields by those standards and this +PEP. + +.. _9999-spec-project-source-metadata: Project source metadata ----------------------- -This PEP specifies changes to the project's source metadata under a ``[project]`` table in the ``pyproject.toml`` file. +This PEP specifies changes to the project's source metadata under a +``[project]`` table in the ``pyproject.toml`` file. Add ``sbom-files`` key ~~~~~~~~~~~~~~~~~~~~~~ -A new ``sbom-files`` key is added to the ``[project]`` table for specifying paths in the project source tree -relative to ``pyproject.toml`` to file(s) containing SBOMs to be distributed with the package. This key corresponds -to the ``Sbom-File`` fields in the Core Metadata. - -Its value is an array of strings which MUST contain valid glob patterns, as specified below: - -* Alphanumeric characters, underscores (``_``), hyphens (``-``) and dots (``.``) MUST be matched verbatim. -* Special glob characters: ``*``, ``?``, ``**`` and character ranges: ``[]`` containing only the verbatim matched characters MUST be supported. Within ``[...]``, the hyphen indicates a locale-agnostic range (e.g. a-z, order based on Unicode code points). Hyphens at the start or end are matched literally. -* Path delimiters MUST be the forward slash character (``/``). Patterns are relative to the directory containing pyproject.toml, therefore the leading slash character MUST NOT be used. +A new ``sbom-files`` key is added to the ``[project]`` table for specifying +paths in the project source tree relative to ``pyproject.toml`` to file(s) +containing SBOMs to be distributed with the package. This key corresponds to the +``Sbom-File`` fields in the Core Metadata. + +Its value is an array of strings which MUST contain valid glob patterns, as +specified below: + +* Alphanumeric characters, underscores (``_``), hyphens (``-``) and dots (``.``) + MUST be matched verbatim. +* Special glob characters: ``*``, ``?``, ``**`` and character ranges: ``[]`` + containing only the verbatim matched characters MUST be supported. Within + ``[...]``, the hyphen indicates a locale-agnostic range (e.g. a-z, order based + on Unicode code points). Hyphens at the start or end are matched literally. +* Path delimiters MUST be the forward slash character (``/``). Patterns are + relative to the directory containing ``pyproject.toml``, therefore the leading + slash character MUST NOT be used. * Parent directory indicators (``..``) MUST NOT be used. -Any characters or character sequences not covered by this specification are invalid. Projects MUST NOT use such values. Tools consuming this field SHOULD reject invalid values with an error. +Any characters or character sequences not covered by this specification are +invalid. Projects MUST NOT use such values. Tools consuming this field SHOULD +reject invalid values with an error. -Tools MUST assume that SBOM file content is valid UTF-8 encoded JSON, and SHOULD validate this an raise an error if it is not. +Tools MUST assume that SBOM file content is valid UTF-8 encoded JSON, and SHOULD +validate this an raise an error for invalid formats and encodings. -Literal paths (`e.g. ``bom.cdx.json``) are treated as valid globs which means they can also be defined. +Literal paths (e.g. ``bom.cdx.json``) are treated as valid globs which means +they can also be defined. Build tools: -* MUST treat each value as a glob pattern, and MUST raise an error if the pattern contains invalid glob syntax. -* MUST include all files matched by a listed pattern in all distribution archives. -* MUST list each matched file path under a ``Sbom-File`` field in the Core Metadata. -* MUST raise an error if any individual user-specified pattern does not match at least one file. +* MUST treat each value as a glob pattern, and MUST raise an error if the + pattern contains invalid glob syntax. +* MUST include all files matched by a listed pattern in all distribution + archives. +* MUST list each matched file path under a ``Sbom-File`` field in the + Core Metadata. +* MUST raise an error if any individual user-specified pattern does not match + at least one file. -If the ``sbom-files`` key is present and is set to a value of an empty array, then tools MUST NOT include -any SBOM files and MUST NOT raise an error. +If the ``sbom-files`` key is present and is set to a value of an empty array, +then tools MUST NOT include any SBOM files and MUST NOT raise an error. Examples of valid SBOM files declarations: @@ -196,7 +256,8 @@ Examples of invalid SBOM files declarations: [project] sbom-files = ["..\bom.json"] -Reason: ``..`` must not be used. ``\\`` is an invalid path delimited, ``\/`` must be used. +Reason: ``..`` must not be used. ``\\`` is an invalid path delimited, ``/`` +must be used. .. code-block:: toml @@ -205,6 +266,8 @@ Reason: ``..`` must not be used. ``\\`` is an invalid path delimited, ``\/`` mus Reason: "bom{.json" is not a valid glob. +.. _9999-spec-project-formats: + SBOM files in project formats ----------------------------- @@ -220,31 +283,37 @@ A few additions will be made to the existing specifications. :term:`Source distributions (sdists) ` - The sdist specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater, - the sdist MUST contain any SBOM files specified by the ``Sbom-File`` field in the ``PKG-INFO`` at their - respective paths relative to the sdist (containing the ``pyproject.toml`` and the ``PKG-INFO`` Core Metadata). + The sdist specification will be updated to reflect that if the + ``Metadata-Version`` is ``2.5`` or greater, the sdist MUST contain any SBOM + files specified by the ``Sbom-File`` field in the ``PKG-INFO`` at their + respective paths relative to the sdist (containing the ``pyproject.toml`` and + the ``PKG-INFO`` Core Metadata). :term:`Built distribution`\s (:term:`wheel`\s) - The wheel specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater - and one or more ``Sbom-File`` fields are specified, the ``.dist-info`` directory MUST contain a ``sboms`` - subdirectory, which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file at - their respective paths relative to the ``sboms`` directory. + The wheel specification will be updated to reflect that if the + ``Metadata-Version`` is ``2.5`` or greater and one or more ``Sbom-File`` + fields are specified, the ``.dist-info`` directory MUST contain a ``sboms`` + subdirectory, which MUST contain the files listed in the ``Sbom-File`` fields + in the ``METADATA`` file at their respective paths relative to the ``sboms`` + directory. :term:`Installed project`\s - The Recording Installed Projects specification will be updated to reflect that if the ``Metadata-Version`` is - ``2.5`` or greater and one or more ``Sbom-File`` fields is specified, the ``.dist-info`` directory MUST contain - a ``sboms`` subdirectory which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file - at their respective paths relative to the ``sboms`` directory, and that any files in this directory MUST be - copied from wheels by install tools. + The Recording Installed Projects specification will be updated to reflect that + if the ``Metadata-Version`` is ``2.5`` or greater and one or more + ``Sbom-File`` fields is specified, the ``.dist-info`` directory MUST contain + a ``sboms`` subdirectory which MUST contain the files listed in the + ``Sbom-File`` fields in the ``METADATA`` file at their respective paths + relative to the ``sboms`` directory, and that any files in this directory MUST + be copied from wheels by install tools. Backwards Compatibility ======================= There are no backwards compatibility concerns for this PEP. -The changes to Python package core metadata and ``pyproject.toml`` are +The changes to Python package Core Metadata and ``pyproject.toml`` are only additive, this PEP doesn't change the behavior of any existing fields. Tools which are processing Python packages can use the ``Sbom-File`` core @@ -255,28 +324,48 @@ packages which include SBOM documents before this PEP was authored. Security Implications ===================== +SBOM documents are only as useful as the information encoded in them. +If an SBOM document contains incorrect information then this can result in +incorrect downstream analysis by SCA tools. For this reason, it's important +for tools including SBOM data into Python packages to be confident in the +information they are recording. SBOMs are capable of recording "known unknowns" +in addition to known data. This practice is recommended when not certain about +the data being recorded to allow for further analysis by users. + Because SBOM documents can encode information about the original system where a Python package is built (for example, the operating system name and -version, more rarely the names of paths) this information has the potential -to "leak" through the Python package to installers. If this information is sensitive, -then that could represent a security risk. - -TODO(More security implications, phantom dependencies) +version, less commonly the names of paths). This information has the potential +to "leak" through the Python package to installers via SBOMs. If this +information is sensitive, then that could represent a security risk. How to Teach This ================= -Most Python packages don't contain code from other software components and thus are already -measurable by SCA tools without the need of SBOM documents. +Most typical users of Python and Python packages won't need to know the details +of this standard. The details of this standard are most important to either +maintainers of Python packages and developers of SCA tools such as +SBOM generation tools and vulnerability scanners. -TODO(Add section on informational PEP for SBOM tools) +Most Python packages don't contain code from other software components and thus +are already measurable by SCA tools without the need of this standard or +additional SBOM documents. Pure-Python packages are about `~90% `__ +of popular packages on PyPI. + +For projects that do contain other software components, documentation will be +added to the Python Packaging User Guide for how to specify and maintain +SBOM documents for Python packages in source code. + +A follow-up informational PEP will be authored to describe how to transform +Python packaging metadata, including the mechanism described in this PEP, +into a SBOM document describing Python packages. Reference Implementation ======================== -[Link to any existing implementation and details about its state, e.g. proof-of-concept.] - -TODO(Add reference impls) +* `Auditwheel fork `_ + which generates CycloneDX SBOM documents to include in wheels describing + bundled shared library files. These SBOM documents worked as expected for the + Syft and Grype SBOM and vulnerability scanners. Rejected Ideas ============== @@ -284,9 +373,10 @@ Rejected Ideas Why not require a single SBOM standard? --------------------------------------- -Most discussion and development around SBOMs today focuses on two SBOM standards: -CycloneDX and SPDX. There is no clear "winner" between these two standards, -both standards are frequently used by projects and software ecosystems. +Most discussion and development around SBOMs today focuses on two SBOM +standards: `CycloneDX `_ and `SPDX `_. There is no clear +"winner" between these two standards, both standards are frequently used by +projects and software ecosystems. Because both standards are frequently used, tools for consuming and processing SBOM documents commonly need to support both standards. This means that this PEP @@ -302,17 +392,31 @@ Conditional project source SBOM files How can a project specify an SBOM file that is conditional? -Footnotes -========= +References +========== + +* `Visualizing the Python package SBOM data flow `_. + This is a graphic that shows how this PEP fits into the bigger picture of + Python packaging's SBOM data story. -[A collection of footnotes cited in the PEP, and a place to list non-inline hyperlink targets.] +* `Adding SBOMs to Python wheels with auditwheel `_. + This was some early results from a fork of auditwheel to add SBOM data to a + wheel and then use an SBOM generation tool Syft to detect the SBOM in the + installed package. + +.. _phantom dependency: https://www.endorlabs.com/learn/dependency-resolution-in-python-beware-the-phantom-dependency +.. _coremetadataspec: https://packaging.python.org/specifications/core-metadata +.. _pyprojecttoml: https://packaging.python.org/en/latest/specifications/pyproject-toml/ +.. _spdx: https://spdx.dev/use/specifications/ +.. _cyclonedx: https://cyclonedx.org/specification/overview/ +.. _pypi-data: https://github.com/sethmlarson/pypi-data Acknowledgements ================ -* Karolina Surma for authoring and seeing :pep:`639` to acceptance, of which much of the design - for specifying files in project source metadata, core metadata, and project formats is based on. - +* Thanks to Karolina Surma for authoring and leading :pep:`639` to acceptance. + This PEP copies the specification from :pep:`639` for specifying files in + project source metadata, Core Metadata, and project formats is based on. Copyright ========= From f258376aa01b4546a1524397777d1effca35cf37 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Tue, 26 Nov 2024 12:38:34 -0600 Subject: [PATCH 3/8] Add example in phantom dependencies section --- peps/pep-9999.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/peps/pep-9999.rst b/peps/pep-9999.rst index a28e0e6752e..69daefd0e9a 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-9999.rst @@ -50,6 +50,13 @@ These software components can't be described using Python package metadata and thus are likely to be missed by software composition analysis (SCA) software which can mean vulnerable software components aren't reported accurately. +`For example `__, +the Python package Pillow includes 16 shared object libraries in the wheel that +were bundled by auditwheel as a part of the build. None of those shared object +libraries are detected when using common SCA tools like Syft and Grype. +If an SBOM document is included annotating all the included shared libraries +then SCA tools can identify the included software reliably. + Regulations ----------- From 50877378e614bbde4f98cf8a4982bd6d8d0b54b6 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Thu, 2 Jan 2025 15:39:29 -0600 Subject: [PATCH 4/8] PEP 770: Improving measurability of Python packages with Software Bill-of-Materials --- peps/{pep-9999.rst => pep-770.rst} | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) rename peps/{pep-9999.rst => pep-770.rst} (96%) diff --git a/peps/pep-9999.rst b/peps/pep-770.rst similarity index 96% rename from peps/pep-9999.rst rename to peps/pep-770.rst index 69daefd0e9a..7a9e9be3c0d 100644 --- a/peps/pep-9999.rst +++ b/peps/pep-770.rst @@ -1,4 +1,4 @@ -PEP: 9999 +PEP: 770 Title: Improving measurability of Python packages with Software Bill-of-Materials Author: Seth Larson Sponsor: Brett Cannon @@ -113,26 +113,26 @@ tools. This decision also means that the merging of SBOM documents never needs to be handled by Python tools, instead deferring this to SBOM consuming tools who are better placed to handle cross-standard conversions. -.. _9999-spec: +.. _770-spec: Specification ============= The changes necessary to implement this PEP include: -* Additions to `Core Metadata <9999-spec-core-metadata>`_, as defined in the +* Additions to `Core Metadata <770-spec-core-metadata>`_, as defined in the `Core Metadata specification `__. * Additions to the author-provided - `project source metadata <9999-spec-source-metadata>`_, as defined in the + `project source metadata <770-spec-source-metadata>`_, as defined in the `pyproject.toml specification `__. -* `Additions <9999-spec-project-formats>`_ to the source distribution (sdist), +* `Additions <770-spec-project-formats>`_ to the source distribution (sdist), built distribution (wheel), and installed project specifications. In addition to the above, an informational PEP will be created for tools consuming included SBOM documents and other Python package metadata to generate complete SBOM documents for Python packages. -.. _9999-spec-core-metadata: +.. _770-spec-core-metadata: Core Metadata ------------- @@ -147,7 +147,7 @@ multi-use field that MAY appear zero or more times and each instance lists the path to one such file. Files specified under this field are SBOM documents that are distributed with the package. -As `specified by this PEP <#9999-spec-project-formats>`__, its value is also +As `specified by this PEP <#770-spec-project-formats>`__, its value is also that file's path relative to the root SBOM directory in both installed projects and the standardized Distribution Package types. @@ -161,7 +161,8 @@ If a ``Sbom-File`` is listed in a path. * Inside the root SBOM directory, packaging tools MUST reproduce the directory structure under which the source files are located relative to the project - root. + root. The root SBOM directory is + `specified in a later section <#770-spec-project-formats>`__. * Path delimiters MUST be the forward slash character (``/``), and parent directory indicators (``..``) MUST NOT be used. * SBOM document contents MUST be UTF-8 encoded JSON according to :rfc:`8259`. @@ -186,7 +187,7 @@ in the distribution archives, are valid UTF-8 encoded JSON, and for well-known SBOM standards provide the minimum required fields by those standards and this PEP. -.. _9999-spec-project-source-metadata: +.. _770-spec-project-source-metadata: Project source metadata ----------------------- @@ -273,7 +274,7 @@ must be used. Reason: "bom{.json" is not a valid glob. -.. _9999-spec-project-formats: +.. _770-spec-project-formats: SBOM files in project formats ----------------------------- @@ -397,7 +398,7 @@ Open Issues Conditional project source SBOM files ------------------------------------- -How can a project specify an SBOM file that is conditional? +How can a project specify an SBOM file that is conditional? Under what circumstances would an SBOM document be conditional? References ========== From a7ff20c85bc99c78a9a08ff296d758d2f25aea81 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Thu, 2 Jan 2025 15:42:55 -0600 Subject: [PATCH 5/8] Add codeowners --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index fa38b768e7e..0c276d86b81 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -641,6 +641,7 @@ peps/pep-0760.rst @pablogsal @brettcannon peps/pep-0761.rst @sethmlarson @hugovk peps/pep-0762.rst @pablogsal @ambv @lysnikolaou @emilyemorehouse peps/pep-0763.rst @dstufft +peps/pep-0770.rst @sethmlarson @brettcannon # ... peps/pep-0777.rst @warsaw # ... From e0e93b38199083dc11b2ec6382b93c549857016e Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Fri, 3 Jan 2025 10:48:42 -0600 Subject: [PATCH 6/8] Apply suggestions from code review Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-770.rst | 57 +++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/peps/pep-770.rst b/peps/pep-770.rst index 7a9e9be3c0d..e9234752776 100644 --- a/peps/pep-770.rst +++ b/peps/pep-770.rst @@ -7,12 +7,12 @@ Discussions-To: https://discuss.python.org/t/70261 Status: Draft Type: Standards Track Topic: Packaging -Created: 15-Nov-2024 +Created: 02-Jan-2025 Abstract ======== -Software Bill-of-Materials (SBOM) are a technology-and-ecosystem-agnostic +Software Bill-of-Materials (SBOM) is a technology-and-ecosystem-agnostic method for describing software composition, provenance, heritage, and more. SBOMs are used as inputs for software composition analysis (SCA) tools, such as scanners for vulnerabilities and licenses, and have been gaining @@ -120,12 +120,12 @@ Specification The changes necessary to implement this PEP include: -* Additions to `Core Metadata <770-spec-core-metadata>`_, as defined in the - `Core Metadata specification `__. +* Additions to `Core Metadata <770-spec-core-metadata_>`_, as defined in the + `Core Metadata specification `__. * Additions to the author-provided - `project source metadata <770-spec-source-metadata>`_, as defined in the + `project source metadata <770-spec-project-source-metadata_>`_, as defined in the `pyproject.toml specification `__. -* `Additions <770-spec-project-formats>`_ to the source distribution (sdist), +* `Additions <770-spec-project-formats_>`_ to the source distribution (sdist), built distribution (wheel), and installed project specifications. In addition to the above, an informational PEP will be created for tools @@ -151,7 +151,7 @@ As `specified by this PEP <#770-spec-project-formats>`__, its value is also that file's path relative to the root SBOM directory in both installed projects and the standardized Distribution Package types. -If a ``Sbom-File`` is listed in a +If an ``Sbom-File`` is listed in a :term:`Source Distribution ` or :term:`Built Distribution`'s Core Metadata: @@ -168,7 +168,7 @@ If a ``Sbom-File`` is listed in a * SBOM document contents MUST be UTF-8 encoded JSON according to :rfc:`8259`. * SBOM document contents MUST use an SBOM standard, and for better interoperability SHOULD be a well-known SBOM standard such as - `CycloneDX `_ or `SPDX `_. + `CycloneDX `_ or `SPDX `_. * The "primary" component being described in included SBOM documents MUST be the Python package. This is achieved in CycloneDX using the ``metadata.component`` field and in SPDX using the ``DESCRIBES`` relationship. @@ -233,7 +233,7 @@ Build tools: pattern contains invalid glob syntax. * MUST include all files matched by a listed pattern in all distribution archives. -* MUST list each matched file path under a ``Sbom-File`` field in the +* MUST list each matched file path under an ``Sbom-File`` field in the Core Metadata. * MUST raise an error if any individual user-specified pattern does not match at least one file. @@ -272,7 +272,7 @@ must be used. [project] sbom-files = ["bom{.json*"] -Reason: "bom{.json" is not a valid glob. +Reason: ``bom{.json`` is not a valid glob. .. _770-spec-project-formats: @@ -281,7 +281,7 @@ SBOM files in project formats A few additions will be made to the existing specifications. -:term:`Project source tree`\s +:term:`Project source trees ` Per :ref:`639-spec-source-metadata` section, the `Declaring Project Metadata specification `__ will be updated to reflect that SBOM file paths MUST be relative to the @@ -290,28 +290,25 @@ A few additions will be made to the existing specifications. e.g. ``setup.py``, ``setup.cfg``, etc). :term:`Source distributions (sdists) ` - The sdist specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater, the sdist MUST contain any SBOM files specified by the ``Sbom-File`` field in the ``PKG-INFO`` at their respective paths relative to the sdist (containing the ``pyproject.toml`` and the ``PKG-INFO`` Core Metadata). -:term:`Built distribution`\s (:term:`wheel`\s) - +:term:`Built distributions ` (:term:`wheels `) The wheel specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater and one or more ``Sbom-File`` - fields are specified, the ``.dist-info`` directory MUST contain a ``sboms`` + fields are specified, the ``.dist-info`` directory MUST contain an ``sboms`` subdirectory, which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file at their respective paths relative to the ``sboms`` directory. -:term:`Installed project`\s - +:term:`Installed projects ` The Recording Installed Projects specification will be updated to reflect that if the ``Metadata-Version`` is ``2.5`` or greater and one or more ``Sbom-File`` fields is specified, the ``.dist-info`` directory MUST contain - a ``sboms`` subdirectory which MUST contain the files listed in the + an ``sboms`` subdirectory which MUST contain the files listed in the ``Sbom-File`` fields in the ``METADATA`` file at their respective paths relative to the ``sboms`` directory, and that any files in this directory MUST be copied from wheels by install tools. @@ -356,7 +353,7 @@ SBOM generation tools and vulnerability scanners. Most Python packages don't contain code from other software components and thus are already measurable by SCA tools without the need of this standard or -additional SBOM documents. Pure-Python packages are about `~90% `__ +additional SBOM documents. Pure-Python packages are about `~90% `__ of popular packages on PyPI. For projects that do contain other software components, documentation will be @@ -365,15 +362,15 @@ SBOM documents for Python packages in source code. A follow-up informational PEP will be authored to describe how to transform Python packaging metadata, including the mechanism described in this PEP, -into a SBOM document describing Python packages. +into an SBOM document describing Python packages. Reference Implementation ======================== -* `Auditwheel fork `_ - which generates CycloneDX SBOM documents to include in wheels describing - bundled shared library files. These SBOM documents worked as expected for the - Syft and Grype SBOM and vulnerability scanners. +`Auditwheel fork `_ +which generates CycloneDX SBOM documents to include in wheels describing +bundled shared library files. These SBOM documents worked as expected for the +Syft and Grype SBOM and vulnerability scanners. Rejected Ideas ============== @@ -382,7 +379,7 @@ Why not require a single SBOM standard? --------------------------------------- Most discussion and development around SBOMs today focuses on two SBOM -standards: `CycloneDX `_ and `SPDX `_. There is no clear +standards: `CycloneDX `_ and `SPDX `_. There is no clear "winner" between these two standards, both standards are frequently used by projects and software ecosystems. @@ -415,16 +412,16 @@ References .. _phantom dependency: https://www.endorlabs.com/learn/dependency-resolution-in-python-beware-the-phantom-dependency .. _coremetadataspec: https://packaging.python.org/specifications/core-metadata .. _pyprojecttoml: https://packaging.python.org/en/latest/specifications/pyproject-toml/ -.. _spdx: https://spdx.dev/use/specifications/ -.. _cyclonedx: https://cyclonedx.org/specification/overview/ +.. _spdxspec: https://spdx.dev/use/specifications/ +.. _cyclonedxspec: https://cyclonedx.org/specification/overview/ .. _pypi-data: https://github.com/sethmlarson/pypi-data Acknowledgements ================ -* Thanks to Karolina Surma for authoring and leading :pep:`639` to acceptance. - This PEP copies the specification from :pep:`639` for specifying files in - project source metadata, Core Metadata, and project formats is based on. +Thanks to Karolina Surma for authoring and leading :pep:`639` to acceptance. +This PEP copies the specification from :pep:`!639` for specifying files in +project source metadata, Core Metadata, and project formats is based on. Copyright ========= From a86ea4f2d6100dcb77a0553c287b87f7c992d229 Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Fri, 3 Jan 2025 10:49:03 -0600 Subject: [PATCH 7/8] Add 0 prefix to filename --- peps/{pep-770.rst => pep-0770.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename peps/{pep-770.rst => pep-0770.rst} (100%) diff --git a/peps/pep-770.rst b/peps/pep-0770.rst similarity index 100% rename from peps/pep-770.rst rename to peps/pep-0770.rst From cd4808a57c9cec32eee0974408a8554bf515d5cb Mon Sep 17 00:00:00 2001 From: Seth Michael Larson Date: Fri, 3 Jan 2025 12:40:20 -0600 Subject: [PATCH 8/8] ! Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com> --- peps/pep-0770.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peps/pep-0770.rst b/peps/pep-0770.rst index e9234752776..8f451c14ab5 100644 --- a/peps/pep-0770.rst +++ b/peps/pep-0770.rst @@ -420,7 +420,7 @@ Acknowledgements ================ Thanks to Karolina Surma for authoring and leading :pep:`639` to acceptance. -This PEP copies the specification from :pep:`!639` for specifying files in +This PEP copies the specification from :pep:`639` for specifying files in project source metadata, Core Metadata, and project formats is based on. Copyright