From c7c114acc33f1b20b20299aafac41ff9614e26d3 Mon Sep 17 00:00:00 2001 From: Fabio Caccamo Date: Sun, 5 Apr 2026 16:45:13 +0200 Subject: [PATCH 1/5] Update GitHub Actions to latest versions. --- .github/workflows/pre-commit-autoupdate.yml | 2 +- .github/workflows/test-package.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pre-commit-autoupdate.yml b/.github/workflows/pre-commit-autoupdate.yml index 211ef052..7ba4e657 100644 --- a/.github/workflows/pre-commit-autoupdate.yml +++ b/.github/workflows/pre-commit-autoupdate.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-python@v6 with: python-version: '3.x' - - uses: browniebroke/pre-commit-autoupdate-action@main + - uses: browniebroke/pre-commit-autoupdate-action@v1 - uses: peter-evans/create-pull-request@v8 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index 4893cf4d..b5d87aed 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -49,7 +49,7 @@ jobs: coverage xml -o ./coverage.xml - name: Upload coverage to Codecov - uses: codecov/codecov-action@v5 + uses: codecov/codecov-action@v6 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: false From d2789db7e004b6cdebfdc4c1f1db915e5c9a3308 Mon Sep 17 00:00:00 2001 From: Fabio Caccamo Date: Sun, 5 Apr 2026 16:45:48 +0200 Subject: [PATCH 2/5] Add SBOM and license report generation to release workflow. --- .github/workflows/create-release.yml | 63 ++++++++++++++++++++++------ .gitignore | 5 +++ requirements-release.txt | 3 ++ 3 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 requirements-release.txt diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 006b0bcb..11331fb9 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -8,14 +8,54 @@ on: jobs: build: runs-on: ubuntu-latest - # environment: release + # environment: release # uncomment to require manual approval before publishing to PyPI (recommended for extra protection) permissions: - id-token: write + contents: write # needed to upload SBOM files as release assets via `gh release upload` + id-token: write # needed for PyPI Trusted Publishing (OIDC) via pypa/gh-action-pypi-publish steps: - name: Checkout uses: actions/checkout@v6 + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: '3.x' + cache: 'pip' + + - name: Upgrade pip + run: pip install pip --upgrade + + - name: Install requirements + run: | + pip install -r requirements.txt -r requirements-release.txt + pip install ".[all]" + + - name: Build package + run: python -m build + + - name: Generate SBOM + run: | + cyclonedx-py environment \ + --pyproject pyproject.toml \ + --mc-type library \ + --of JSON \ + -o sbom.cyclonedx.json + cyclonedx-py environment \ + --pyproject pyproject.toml \ + --mc-type library \ + --of XML \ + -o sbom.cyclonedx.xml + + - name: Generate license report + run: | + pip-licenses \ + --ignore-packages build cyclonedx-bom cyclonedx-py pip-licenses \ + --with-authors --with-urls --format=csv --output-file=licenses.csv + pip-licenses \ + --ignore-packages build cyclonedx-bom cyclonedx-py pip-licenses \ + --with-authors --with-urls --format=markdown --output-file=licenses.md + - name: Extract release notes id: extract-release-notes uses: ffurrer2/extract-release-notes@v3 @@ -26,17 +66,16 @@ jobs: body: ${{ steps.extract-release-notes.outputs.release_notes }} token: ${{ secrets.WORKFLOWS_CREATE_RELEASE_TOKEN }} - - name: Set up Python - uses: actions/setup-python@v6 - with: - python-version: '3.x' - cache: 'pip' - - - name: Build Package + - name: Upload release assets run: | - pip install pip --upgrade - pip install build - python -m build + gh release upload ${{ github.ref_name }} \ + sbom.cyclonedx.json \ + sbom.cyclonedx.xml \ + licenses.csv \ + licenses.md \ + --clobber + env: + GH_TOKEN: ${{ secrets.WORKFLOWS_CREATE_RELEASE_TOKEN }} - name: Publish on PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.gitignore b/.gitignore index f113ccb4..fc864d2e 100644 --- a/.gitignore +++ b/.gitignore @@ -125,3 +125,8 @@ dmypy.json # custom TODO.txt test-coverage.sh + +# generated at release time, not committed +sbom.cyclonedx.* +licenses.csv +licenses.md diff --git a/requirements-release.txt b/requirements-release.txt new file mode 100644 index 00000000..575462a3 --- /dev/null +++ b/requirements-release.txt @@ -0,0 +1,3 @@ +build == 1.4.* +cyclonedx-bom == 7.3.* +pip-licenses == 5.5.* From ca870ef3db901503160c1150546eb8c6b97a805f Mon Sep 17 00:00:00 2001 From: Fabio Caccamo Date: Sun, 5 Apr 2026 16:46:25 +0200 Subject: [PATCH 3/5] Add OpenSSF Scorecard workflow. --- .github/workflows/scorecard.yml | 37 +++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 00000000..5003aec1 --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,37 @@ +name: OpenSSF Scorecard + +on: + push: + branches: [main] + schedule: + - cron: '0 8 * * 6' # every Saturday at 08:00 UTC + workflow_dispatch: + +permissions: read-all + +jobs: + scorecard: + runs-on: ubuntu-latest + permissions: + security-events: write # needed to upload SARIF results to GitHub Security tab + id-token: write # needed for Scorecard's OIDC token + contents: read + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + persist-credentials: false + + - name: Run Scorecard + uses: ossf/scorecard-action@v2 + with: + results_file: scorecard-results.sarif + results_format: sarif + publish_results: true + + - name: Upload results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: scorecard-results.sarif + category: scorecard From fd8d550245644280b1df68c1dd68f1d5d87e61c7 Mon Sep 17 00:00:00 2001 From: Fabio Caccamo Date: Sun, 5 Apr 2026 16:48:12 +0200 Subject: [PATCH 4/5] Add "Security" section to `README` and improve `SECURITY.md`. --- README.md | 11 +++++++++++ SECURITY.md | 14 +++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e918418d..8530c1ed 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,9 @@ [![](https://img.shields.io/scrutinizer/quality/g/fabiocaccamo/python-benedict?logo=scrutinizer)](https://scrutinizer-ci.com/g/fabiocaccamo/python-benedict/?branch=main) [![](https://img.shields.io/badge/code%20style-black-000000.svg?logo=python&logoColor=black)](https://github.com/psf/black) [![](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) +[![](https://img.shields.io/badge/security-policy-blue?logo=github)](https://github.com/fabiocaccamo/python-benedict/blob/main/SECURITY.md) +[![](https://img.shields.io/badge/SBOM-CycloneDX-blue?logo=dependabot)](https://github.com/fabiocaccamo/python-benedict/releases/latest) +[![](https://api.securityscorecards.dev/projects/github.com/fabiocaccamo/python-benedict/badge)](https://scorecard.dev/viewer/?uri=github.com/fabiocaccamo/python-benedict) # python-benedict python-benedict is a dict subclass with **keylist/keypath/keyattr** support, **I/O** shortcuts (`base64`, `cli`, `csv`, `html`, `ini`, `json`, `pickle`, `plist`, `query-string`, `toml`, `xls`, `xml`, `yaml`) and many **utilities**... for humans, obviously. @@ -44,6 +47,7 @@ python-benedict is a dict subclass with **keylist/keypath/keyattr** support, **I - [I/O methods](#io-methods) - [Parse methods](#parse-methods) - [Testing](#testing) +- [Security](#security) - [License](#license) ## Installation @@ -1030,6 +1034,13 @@ tox python -m unittest ``` +## Security + +- **SBOM** — a Software Bill of Materials in [CycloneDX](https://cyclonedx.org/) format (JSON and XML) is generated and published as a release asset on every release. You can download it from the [Releases](https://github.com/fabiocaccamo/python-benedict/releases/latest) page. +- **Trusted Publishing** — packages are published to PyPI via [OIDC Trusted Publishing](https://docs.pypi.org/trusted-publishers/), without long-lived secrets. +- **OpenSSF Scorecard** — the repository is evaluated weekly against the [OpenSSF Scorecard](https://scorecard.dev/viewer/?uri=github.com/fabiocaccamo/python-benedict) checks; results are visible in the GitHub Security tab. +- **Reporting** — to report a vulnerability, please follow the [Security Policy](SECURITY.md). + ## License Released under [MIT License](LICENSE.txt). diff --git a/SECURITY.md b/SECURITY.md index e6b4772c..6e13845a 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,13 +2,21 @@ ## Supported Versions -Keep this library updated to the latest version. +Only the latest stable release receives security fixes. | Version | Supported | | ------- | ------------------ | | latest | :white_check_mark: | -| oldest | :x: | +| older | :x: | ## Reporting a Vulnerability -Open an issue. +**Please do not open a public GitHub issue for security vulnerabilities.** + +Use GitHub's private [Report a vulnerability](https://github.com/fabiocaccamo/python-benedict/security/advisories/new) feature. You will receive a response within 7 days, and a fix will be released as soon as possible depending on severity. + +## Supply Chain Security + +- **SBOM** — a Software Bill of Materials in [CycloneDX](https://cyclonedx.org/) format (JSON and XML) is attached to every [release](https://github.com/fabiocaccamo/python-benedict/releases/latest) as `sbom.cyclonedx.json` / `sbom.cyclonedx.xml`. +- **License report** — a full dependency license inventory (`licenses.csv` / `licenses.md`) is also attached to every release. +- **Trusted Publishing** — packages are published to PyPI via [OIDC Trusted Publishing](https://docs.pypi.org/trusted-publishers/), without storing long-lived API tokens. From da6c83903d632c65ad15c4c8f0382e0fdfcabc57 Mon Sep 17 00:00:00 2001 From: Fabio Caccamo Date: Sun, 5 Apr 2026 17:05:38 +0200 Subject: [PATCH 5/5] Use `python -m pip` instead of `pip` in workflows. --- .github/workflows/create-release.yml | 6 +++--- .github/workflows/test-package.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 11331fb9..83113839 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -24,12 +24,12 @@ jobs: cache: 'pip' - name: Upgrade pip - run: pip install pip --upgrade + run: python -m pip install --upgrade pip - name: Install requirements run: | - pip install -r requirements.txt -r requirements-release.txt - pip install ".[all]" + python -m pip install -r requirements.txt -r requirements-release.txt + python -m pip install ".[all]" - name: Build package run: python -m build diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml index b5d87aed..f1914d44 100644 --- a/.github/workflows/test-package.yml +++ b/.github/workflows/test-package.yml @@ -34,8 +34,8 @@ jobs: - name: Install requirements run: | python -m pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-test.txt + python -m pip install -r requirements.txt + python -m pip install -r requirements-test.txt - name: Run pre-commit run: |