diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 34f9ef8e..c2aad240 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -60,6 +60,9 @@ jobs: # those targets first and only builds the package if they succeed. # Build the sdist and wheel distribution of the package and docs as a zip file. run: make dist + # Audit all currently installed packages for security vulnerabilities. + - name: Audit installed packages + run: make audit - name: Compute package hash if: matrix.os == env.ARTIFACT_OS && matrix.python == env.ARTIFACT_PYTHON id: compute-hash diff --git a/Makefile b/Makefile index d9dc71e7..632cb1ab 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ NEED_VENV := $(or \ $(findstring upgrade,$(MAKECMDGOALS)), \ $(findstring sbom,$(MAKECMDGOALS)), \ $(findstring requirements,$(MAKECMDGOALS)), \ + $(findstring audit,$(MAKECMDGOALS)), \ $(findstring check,$(MAKECMDGOALS)), \ $(findstring test,$(MAKECMDGOALS)), \ $(findstring dist,$(MAKECMDGOALS)), \ @@ -130,6 +131,17 @@ requirements.txt: pyproject.toml echo "" >> requirements.txt cp requirements.txt dist/package-$(PACKAGE_VERSION)-requirements.txt +# Audit the currently installed packages. Skip packages that are installed in +# editable mode (like the one in development here) because they may not have +# a PyPI entry; also print out CVE description and potential fixes if audit +# found an issue. +.PHONY: audit +audit: + if ! $$(python -c "import pip_audit" &> /dev/null); then \ + echo "No package pip_audit installed, upgrade your environment!" && exit 1; \ + fi; + python -m pip_audit --skip-editable --desc on --fix --dry-run + # Run some or all checks over the package code base. .PHONY: check check-code check-bandit check-flake8 check-lint check-mypy check-code: check-bandit check-flake8 check-lint check-mypy diff --git a/README.md b/README.md index ea2f348e..8b88c655 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ Automatic package versioning and tagging, publishing to [PyPI](https://pypi.org/ [OSSF Security Scorecards](https://github.com/ossf/scorecard) is enabled as a GitHub Actions workflow to give the consumers information about the supply-chain security posture of this project, assigning a score of 0–10. We upload the results as a SARIF (Static Analysis Results Interchange Format) artifact after each run and the results can be found at the Security tab of this GitHub project. We also allow publishing the data at [OpenSSF](https://metrics.openssf.org/). We use this data to continuously improve the security posture of this project. Note that this configuration supports the ``main`` (default) branch and requires the repository to be public and not forked. +[pip-audit](https://github.com/pypa/pip-audit) is part of the default Python virtual environment, and can be used to check all installed packages for documented [CVE](https://www.cve.org/) by querying the [Python Packaging Advisory Database](https://github.com/pypa/advisory-database). The `build.yaml` workflow always runs a package audit before the artifacts are being built. + ### Package or application? A _shared package_ or library is intended to be imported by another package or application; an _application_ is a self-contained, standalone, runnable package. Unfortunately, Python’s packaging ecosystem is mostly focused on packaging shared packages (libraries), and packaging Python applications is not as well-supported ([discussion](https://discuss.python.org/t/help-packaging-optional-application-features-using-extras/14074/7)). This template, however, supports both scenarios. diff --git a/pyproject.toml b/pyproject.toml index decceb15..afd2040b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,7 @@ actions = [ dev = [ "flit >=3.2.0,<4.0.0", "mypy >=0.921,<=0.971", + "pip-audit >=2.4.4,<3.0.0", "pylint >=2.9.3,<=2.14.5", "cyclonedx-bom >=3.5.0,<4.0.0", ]