From 8bf1be7c9fed66ee52ef8b05d35977061ba368dc Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 21 Jul 2026 22:39:43 +0100 Subject: [PATCH 1/2] 525: add SBOM generation and attestation to CI pipeline --- .github/workflows/build-assets.yml | 8 + .github/workflows/release.yml | 4 + composer.json | 4 +- composer.lock | 431 ++++++++++++++++++++++++++++- 4 files changed, 445 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-assets.yml b/.github/workflows/build-assets.yml index d7319a91..c69e3ace 100644 --- a/.github/workflows/build-assets.yml +++ b/.github/workflows/build-assets.yml @@ -61,6 +61,14 @@ jobs: uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 #v4.1.0 with: subject-path: '${{ github.workspace }}/pie.phar' + - name: Make SBOM + run: composer CycloneDX:make-sbom --output-format=JSON --output-file=sbom.json --omit=dev + - name: Attest the SBOM + if: github.event_name != 'pull_request' && github.event.repository.visibility == 'public' + uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 #v4.1.0 + with: + subject-path: '${{ github.workspace }}/pie.phar' + sbom-path: '${{ github.workspace }}/sbom.json' - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 with: name: pie-${{ github.sha }}.phar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fcadee5c..590ede43 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,6 +67,10 @@ jobs: run: | gh attestation verify pie.phar --repo ${{ github.repository }} ; find executable-pie-binaries -type f -exec gh attestation verify {} --repo ${{ github.repository }} \; + - name: Verify the PHAR's SBOM attestation + env: + GH_TOKEN: ${{ github.token }} + run: gh attestation verify pie.phar --repo ${{ github.repository }} --predicate-type https://cyclonedx.org/bom # Once the PHAR and binaries have been attached to the release, it is # ready for review before publishing it. Note that if immutable releases # are enabled, the tag, pre-release/latest release flag, and all assets diff --git a/composer.json b/composer.json index 4087aef6..60e421bc 100644 --- a/composer.json +++ b/composer.json @@ -45,6 +45,7 @@ "ext-openssl": "*", "behat/behat": "^3.29.0", "bnf/phpstan-psr-container": "^1.1", + "cyclonedx/cyclonedx-php-composer": "^6.2.0", "doctrine/coding-standard": "^14.0.0", "phpstan/phpstan": "^2.2.5", "phpstan/phpstan-phpunit": "^2.0.18", @@ -62,7 +63,8 @@ "preferred-install": "dist", "bump-after-update": true, "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true + "dealerdirect/phpcodesniffer-composer-installer": true, + "cyclonedx/cyclonedx-php-composer": true }, "platform": { "php": "8.1.99" diff --git a/composer.lock b/composer.lock index 999aa8ba..41699ff6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1f6ab4068638ae2fd252920019617e2b", + "content-hash": "bf0db46220d4520b9171cad1c0d8831b", "packages": [ { "name": "composer/ca-bundle", @@ -3018,6 +3018,179 @@ }, "time": "2024-11-19T16:16:59+00:00" }, + { + "name": "cyclonedx/cyclonedx-library", + "version": "v4.1.0", + "source": { + "type": "git", + "url": "https://github.com/CycloneDX/cyclonedx-php-library.git", + "reference": "6a4f249cecf3b4211ad6bd8cee30fca89e0f81e5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CycloneDX/cyclonedx-php-library/zipball/6a4f249cecf3b4211ad6bd8cee30fca89e0f81e5", + "reference": "6a4f249cecf3b4211ad6bd8cee30fca89e0f81e5", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "opis/json-schema": "^2.0", + "php": "^8.1" + }, + "conflict": { + "composer/spdx-licenses": "<1.5" + }, + "require-dev": { + "composer/spdx-licenses": "^1.5", + "ext-simplexml": "*", + "roave/security-advisories": "dev-latest" + }, + "suggest": { + "composer/spdx-licenses": "used in license factory", + "package-url/packageurl-php": "for parsing and crafting PackageURL strings" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.x-dev" + }, + "composer-normalize": { + "indent-size": 4, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "CycloneDX\\Core\\": "src/Core/", + "CycloneDX\\Contrib\\": "src/Contrib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jan Kowalleck", + "email": "jan.kowalleck@gmail.com", + "homepage": "https://github.com/jkowalleck" + } + ], + "description": "Work with CycloneDX documents.", + "homepage": "https://github.com/CycloneDX/cyclonedx-php-library/#readme", + "keywords": [ + "CycloneDX", + "HBOM", + "OBOM", + "SBOM", + "SaaSBOM", + "bill-of-materials", + "bom", + "models", + "normalizer", + "owasp", + "package-url", + "purl", + "serializer", + "software-bill-of-materials", + "spdx", + "validator", + "vdr", + "vex" + ], + "support": { + "docs": "https://cyclonedx-php-library.readthedocs.io", + "issues": "https://github.com/CycloneDX/cyclonedx-php-library/issues", + "source": "https://github.com/CycloneDX/cyclonedx-php-library/" + }, + "funding": [ + { + "url": "https://owasp.org/donate/?reponame=www-project-cyclonedx&title=OWASP+CycloneDX", + "type": "other" + } + ], + "time": "2026-06-04T10:31:45+00:00" + }, + { + "name": "cyclonedx/cyclonedx-php-composer", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/CycloneDX/cyclonedx-php-composer.git", + "reference": "934440a5ef7c3c3cdb58c3c3d389d412630ccbf6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CycloneDX/cyclonedx-php-composer/zipball/934440a5ef7c3c3cdb58c3c3d389d412630ccbf6", + "reference": "934440a5ef7c3c3cdb58c3c3d389d412630ccbf6", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.3", + "composer/spdx-licenses": "^1.5.7", + "cyclonedx/cyclonedx-library": "^4.0", + "package-url/packageurl-php": "^1.0", + "php": "^8.1" + }, + "require-dev": { + "composer/composer": "^2.3.0", + "marc-mabe/php-enum": "^4.6", + "roave/security-advisories": "dev-latest" + }, + "type": "composer-plugin", + "extra": { + "class": "CycloneDX\\Composer\\Plugin", + "branch-alias": { + "dev-master": "6.x-dev" + }, + "composer-normalize": { + "indent-size": 4, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "CycloneDX\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jan Kowalleck", + "email": "jan.kowalleck@gmail.com", + "homepage": "https://github.com/jkowalleck" + } + ], + "description": "Creates CycloneDX Software Bill-of-Materials (SBOM) from PHP Composer projects", + "homepage": "https://github.com/CycloneDX/cyclonedx-php-composer/#readme", + "keywords": [ + "CycloneDX", + "SBOM", + "bill-of-materials", + "bom", + "composer", + "package-url", + "purl", + "software-bill-of-materials", + "spdx" + ], + "support": { + "issues": "https://github.com/CycloneDX/cyclonedx-php-composer/issues", + "source": "https://github.com/CycloneDX/cyclonedx-php-composer/" + }, + "funding": [ + { + "url": "https://owasp.org/donate/?reponame=www-project-cyclonedx&title=OWASP+CycloneDX", + "type": "other" + } + ], + "time": "2026-02-17T13:23:10+00:00" + }, { "name": "dealerdirect/phpcodesniffer-composer-installer", "version": "v1.2.1", @@ -3287,6 +3460,262 @@ }, "time": "2026-07-04T14:30:18+00:00" }, + { + "name": "opis/json-schema", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/opis/json-schema.git", + "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/json-schema/zipball/8458763e0dd0b6baa310e04f1829fc73da4e8c8a", + "reference": "8458763e0dd0b6baa310e04f1829fc73da4e8c8a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "opis/string": "^2.1", + "opis/uri": "^1.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "ext-bcmath": "*", + "ext-intl": "*", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\JsonSchema\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + }, + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + } + ], + "description": "Json Schema Validator for PHP", + "homepage": "https://opis.io/json-schema", + "keywords": [ + "json", + "json-schema", + "schema", + "validation", + "validator" + ], + "support": { + "issues": "https://github.com/opis/json-schema/issues", + "source": "https://github.com/opis/json-schema/tree/2.6.0" + }, + "time": "2025-10-17T12:46:48+00:00" + }, + { + "name": "opis/string", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/opis/string.git", + "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/string/zipball/3e4d2aaff518ac518530b89bb26ed40f4503635e", + "reference": "3e4d2aaff518ac518530b89bb26ed40f4503635e", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "ext-json": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\String\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Multibyte strings as objects", + "homepage": "https://opis.io/string", + "keywords": [ + "multi-byte", + "opis", + "string", + "string manipulation", + "utf-8" + ], + "support": { + "issues": "https://github.com/opis/string/issues", + "source": "https://github.com/opis/string/tree/2.1.0" + }, + "time": "2025-10-17T12:38:41+00:00" + }, + { + "name": "opis/uri", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/opis/uri.git", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opis/uri/zipball/0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "reference": "0f3ca49ab1a5e4a6681c286e0b2cc081b93a7d5a", + "shasum": "" + }, + "require": { + "opis/string": "^2.0", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Opis\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Marius Sarca", + "email": "marius.sarca@gmail.com" + }, + { + "name": "Sorin Sarca", + "email": "sarca_sorin@hotmail.com" + } + ], + "description": "Build, parse and validate URIs and URI-templates", + "homepage": "https://opis.io", + "keywords": [ + "URI Template", + "parse url", + "punycode", + "uri", + "uri components", + "url", + "validate uri" + ], + "support": { + "issues": "https://github.com/opis/uri/issues", + "source": "https://github.com/opis/uri/tree/1.1.0" + }, + "time": "2021-05-22T15:57:08+00:00" + }, + { + "name": "package-url/packageurl-php", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/package-url/packageurl-php.git", + "reference": "32058ad61f0d8b457fa26e7860bbd8b903196d3f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/package-url/packageurl-php/zipball/32058ad61f0d8b457fa26e7860bbd8b903196d3f", + "reference": "32058ad61f0d8b457fa26e7860bbd8b903196d3f", + "shasum": "" + }, + "require": { + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "ext-json": "*", + "phpunit/phpunit": "9.6.16", + "roave/security-advisories": "dev-latest" + }, + "type": "library", + "extra": { + "composer-normalize": { + "indent-size": 4, + "indent-style": "space" + } + }, + "autoload": { + "psr-4": { + "PackageUrl\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Kowalleck", + "email": "jan.kowalleck@gmail.com", + "homepage": "https://github.com/jkowalleck" + } + ], + "description": "Builder and parser based on the package URL (purl) specification.", + "homepage": "https://github.com/package-url/packageurl-php#readme", + "keywords": [ + "package", + "package-url", + "packageurl", + "purl", + "url" + ], + "support": { + "issues": "https://github.com/package-url/packageurl-php/issues", + "source": "https://github.com/package-url/packageurl-php/tree/1.1.2" + }, + "funding": [ + { + "url": "https://github.com/sponsors/jkowalleck", + "type": "github" + } + ], + "time": "2024-02-05T11:20:07+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.4", From 43895f67d6ff8dee4a16372d8cbd25798a1fd0e3 Mon Sep 17 00:00:00 2001 From: James Titcumb Date: Tue, 21 Jul 2026 22:45:28 +0100 Subject: [PATCH 2/2] 525: add SBOM to GH release assets --- .github/workflows/build-assets.yml | 4 ++++ .github/workflows/release.yml | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/build-assets.yml b/.github/workflows/build-assets.yml index c69e3ace..1994976b 100644 --- a/.github/workflows/build-assets.yml +++ b/.github/workflows/build-assets.yml @@ -73,6 +73,10 @@ jobs: with: name: pie-${{ github.sha }}.phar path: pie.phar + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + with: + name: pie-${{ github.sha }}-sbom.json + path: sbom.json build-executable: needs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 590ede43..527e58ee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,6 +61,10 @@ jobs: path: executable-pie-binaries pattern: pie-${{ github.sha }}-*.bin merge-multiple: true + - name: Fetch the PHAR's SBOM from artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c #v8.0.1 + with: + name: pie-${{ github.sha }}-sbom.json - name: Verify the PHAR and binaries env: GH_TOKEN: ${{ github.token }} @@ -81,6 +85,7 @@ jobs: GH_TOKEN: ${{ github.token }} run: | gh release upload "${GITHUB_REF_NAME}" "pie.phar" --clobber ; + gh release upload "${GITHUB_REF_NAME}" "sbom.json" --clobber ; find executable-pie-binaries -type f -exec gh release upload "${GITHUB_REF_NAME}" {} --clobber \; build-and-push-docker-image: