Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 62 additions & 6 deletions .github/workflows/sbom-diff-and-risk-ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
name: sbom-diff-and-risk-ci
run-name: sbom-diff-and-risk ci / ${{ github.event_name }} / ${{ github.ref_name }}

on:
workflow_dispatch:
push:
# Version tags provide a minimal release-build scaffold without changing publishing.
tags:
- "v*"
paths:
- ".github/workflows/sbom-diff-and-risk-ci.yml"
- "tools/sbom-diff-and-risk/**"
Expand All @@ -11,8 +15,12 @@ on:
- ".github/workflows/sbom-diff-and-risk-ci.yml"
- "tools/sbom-diff-and-risk/**"

permissions: {}

env:
SBOM_DIFF_RISK_PYTHON_VERSION: "3.11"
SBOM_DIFF_RISK_DIST_ARTIFACT_NAME: sbom-diff-and-risk-dist
SBOM_DIFF_RISK_RELEASE_TITLE_PREFIX: sbom-diff-and-risk

jobs:
test:
Expand All @@ -24,12 +32,12 @@ jobs:
working-directory: tools/sbom-diff-and-risk
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.11"
python-version: ${{ env.SBOM_DIFF_RISK_PYTHON_VERSION }}

- name: Upgrade pip
run: python -m pip install --upgrade pip
Expand Down Expand Up @@ -70,12 +78,12 @@ jobs:
working-directory: tools/sbom-diff-and-risk
steps:
- name: Check out repository
uses: actions/checkout@v4
uses: actions/checkout@v5

- name: Set up Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: "3.11"
python-version: ${{ env.SBOM_DIFF_RISK_PYTHON_VERSION }}

- name: Upgrade pip
run: python -m pip install --upgrade pip
Expand All @@ -99,3 +107,51 @@ jobs:
uses: actions/attest@v4
with:
subject-path: ${{ github.workspace }}/tools/sbom-diff-and-risk/dist/*

publish-release-assets:
# Publish the exact built wheel/sdist bytes from this run as release assets.
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
needs: build-and-attest
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Download built distribution artifact
uses: actions/download-artifact@v4
with:
name: ${{ env.SBOM_DIFF_RISK_DIST_ARTIFACT_NAME }}
path: release-assets

- name: Publish release assets from CI-built distributions
shell: bash
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ github.ref_name }}
RELEASE_TITLE_PREFIX: ${{ env.SBOM_DIFF_RISK_RELEASE_TITLE_PREFIX }}
run: |
set -euo pipefail
shopt -s nullglob
assets=(release-assets/*.whl release-assets/*.tar.gz)
if [ "${#assets[@]}" -eq 0 ]; then
echo "No release assets found in release-assets/" >&2
exit 1
fi

title="${RELEASE_TITLE_PREFIX} ${RELEASE_TAG}"

if gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Provide repo context before running gh release commands

In publish-release-assets, the step invokes gh release view/create/upload/edit but never checks out the repo and does not pass --repo (or set GH_REPO), so these commands can fail to resolve a target repository in GitHub Actions and abort tag-release publication. GitHub CLI documents GH_REPO as required for commands that otherwise rely on local-repo context; without checkout in this job, tag pushes can fail before assets are uploaded.

Useful? React with 👍 / 👎.

is_draft="$(gh release view "${RELEASE_TAG}" --json isDraft -q .isDraft)"
if [ "${is_draft}" != "true" ]; then
echo "Release ${RELEASE_TAG} already exists and is published; leaving assets unchanged."
exit 0
fi
else
gh release create "${RELEASE_TAG}" \
--draft \
--verify-tag \
--title "${title}" \
--notes "Release assets for ${RELEASE_TAG}. See docs/release-provenance.md for provenance verification guidance."
fi

gh release upload "${RELEASE_TAG}" "${assets[@]}" --clobber
gh release edit "${RELEASE_TAG}" --draft=false --title "${title}"
27 changes: 23 additions & 4 deletions .github/workflows/sbom-diff-and-risk-code-scanning.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
name: sbom-diff-and-risk-code-scanning
run-name: sbom-diff-and-risk code scanning / ${{ github.event_name }} / ${{ github.ref_name }}

on:
workflow_dispatch:
Expand All @@ -7,6 +8,14 @@ on:
- ".github/workflows/sbom-diff-and-risk-code-scanning.yml"
- "tools/sbom-diff-and-risk/**"

permissions: {}

env:
SBOM_DIFF_RISK_PYTHON_VERSION: "3.11"
SBOM_DIFF_RISK_SARIF_ARTIFACT_NAME: sbom-diff-and-risk-sarif
SBOM_DIFF_RISK_SARIF_CATEGORY: sbom-diff-risk/example
SBOM_DIFF_RISK_SARIF_FILE: outputs/report.sarif

jobs:
upload-sarif:
runs-on: ubuntu-latest
Expand All @@ -23,7 +32,10 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
python-version: ${{ env.SBOM_DIFF_RISK_PYTHON_VERSION }}

- name: Upgrade pip
run: python -m pip install --upgrade pip

- name: Install sbom-diff-and-risk
run: python -m pip install -e .[dev]
Expand All @@ -34,10 +46,17 @@ jobs:
python -m sbom_diff_risk.cli compare \
--before examples/sarif_before.json \
--after examples/sarif_after.json \
--out-sarif outputs/report.sarif
--out-sarif ${{ env.SBOM_DIFF_RISK_SARIF_FILE }}

- name: Upload SARIF workflow artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.SBOM_DIFF_RISK_SARIF_ARTIFACT_NAME }}
path: tools/sbom-diff-and-risk/${{ env.SBOM_DIFF_RISK_SARIF_FILE }}
if-no-files-found: error

- name: Upload SARIF to code scanning
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: tools/sbom-diff-and-risk/outputs/report.sarif
category: sbom-diff-risk/example
sarif_file: tools/sbom-diff-and-risk/${{ env.SBOM_DIFF_RISK_SARIF_FILE }}
category: ${{ env.SBOM_DIFF_RISK_SARIF_CATEGORY }}
36 changes: 30 additions & 6 deletions tools/sbom-diff-and-risk/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# sbom-diff-and-risk

v0.3.0 adds opt-in PyPI provenance enrichment, provenance-aware policy and reporting, optional advisory Scorecard signals, and self-provenance verification guidance for workflow-built artifacts.
v0.4 keeps dependency analysis local and deterministic by default while improving how consumers verify `sbom-diff-and-risk` itself through workflow-built artifacts and GitHub Release assets.

`sbom-diff-and-risk` is a local, deterministic CLI for comparing two SBOMs or dependency manifests and producing JSON plus Markdown reports.

It uses conservative heuristics for change intelligence. By default it does not resolve CVEs, does not act as a reputation oracle, and does not perform hidden network enrichment.

## Start Here

This project has two different provenance stories:

1. If you want to verify `sbom-diff-and-risk` itself, start with [docs/verification.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/verification.md).
2. If you want to use `sbom-diff-and-risk` to analyze third-party dependency provenance, start with [Dependency provenance analysis](#dependency-provenance-analysis-opt-in) and [Dependency provenance reporting](#dependency-provenance-reporting).

## Scope

- Normalize two local inputs into a shared component schema.
Expand Down Expand Up @@ -163,7 +170,9 @@ sbom-diff-risk compare \

Offline mode remains the default. No network access occurs unless `--enrich-pypi` or `--enrich-scorecard` is set explicitly.

## Opt-in Provenance Enrichment
## Dependency Provenance Analysis (Opt-in)

This section is about analyzing third-party package provenance signals. It is not about verifying the `sbom-diff-and-risk` tool's own release artifacts.

PyPI provenance and integrity enrichment is explicit and additive in this PR:

Expand All @@ -186,7 +195,7 @@ sbom-diff-risk compare \
--out-json outputs/report-enriched.json
```

## Provenance-Aware Reporting
## Dependency Provenance Reporting

When provenance enrichment is enabled, the reports surface trust signals directly instead of burying them in component evidence:

Expand Down Expand Up @@ -221,17 +230,26 @@ If you want policy gating, make it explicit with a v3 policy such as [policy-sco

Setting `minimum_scorecard_score` alone is advisory metadata for review. It only affects policy outcomes when `scorecard_below_threshold` is configured explicitly in `block_on`, `warn_on`, or `ignore_rules`.

## Self-provenance
## Tool Provenance And Verification

This section is about verifying `sbom-diff-and-risk` itself. If you want the shortest path to the right verification instructions, start with [docs/verification.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/verification.md).

This repository also records provenance for `sbom-diff-and-risk` itself by generating GitHub artifact attestations for the wheel and source distribution produced by the `sbom-diff-and-risk-ci` workflow.

- the attested files are the wheel and source distribution built by `python -m build` from `tools/sbom-diff-and-risk`
- the build files are uploaded together as the `sbom-diff-and-risk-dist` workflow artifact
- version-tag runs also publish those same built files as GitHub Release assets for the matching tag
- only trusted non-PR runs publish the attestation
- consumers can verify provenance with GitHub's attestation tooling after downloading one of those artifacts
- consumers can verify workflow-built artifacts with `gh attestation verify`
- consumers can verify immutable releases and downloaded release assets with `gh release verify` and `gh release verify-asset`
- this complements the tool's analysis of third-party supply-chain inputs, but it does not replace that analysis

See [docs/self-provenance.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/self-provenance.md) for the exact attested filenames, where the evidence appears in GitHub, and a run-by-run verification flow for consumers.
Verification docs:

- [docs/verification.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/verification.md) for the quick decision guide
- [docs/self-provenance.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/self-provenance.md) for workflow-artifact attestation
- [docs/release-provenance.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/release-provenance.md) for release-asset verification and immutable release guidance
- [docs/pypi-trusted-publishing-readiness.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/pypi-trusted-publishing-readiness.md) for PyPI publishing prerequisites and sequencing

## Examples

Expand Down Expand Up @@ -306,8 +324,14 @@ sbom-diff-risk compare \

For GitHub code scanning integration guidance and a minimal upload workflow, see [docs/github-code-scanning.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/github-code-scanning.md).

For the shortest path to the tool-verification docs, start with [docs/verification.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/verification.md).

For details on how this repository attests the tool's own wheel and source distribution artifacts, see [docs/self-provenance.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/self-provenance.md).

For details on how version-tag releases publish those same build outputs as release assets, and how consumers can verify immutable releases with GitHub CLI, see [docs/release-provenance.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/release-provenance.md).

For PyPI Trusted Publishing readiness, prerequisites, and the reasons this repository does not enable PyPI upload yet, see [docs/pypi-trusted-publishing-readiness.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/pypi-trusted-publishing-readiness.md).

## Parser Boundaries

Deterministic local mode intentionally supports a conservative subset of packaging syntax. The detailed matrix lives in [docs/parser-boundaries.md](D:/OneDrive/Code/scientific-computing-toolkit/tools/sbom-diff-and-risk/docs/parser-boundaries.md).
Expand Down
13 changes: 13 additions & 0 deletions tools/sbom-diff-and-risk/docs/github-code-scanning.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ The example workflow in `.github/workflows/sbom-diff-and-risk-code-scanning.yml`
- checks out the repository
- installs Python and the local tool
- runs `sbom-diff-risk compare ... --out-sarif`
- uploads the generated SARIF file as the workflow artifact `sbom-diff-and-risk-sarif`
- uploads the generated SARIF file with `github/codeql-action/upload-sarif`

The example intentionally uses local example inputs and does not depend on secrets or network enrichment.
Expand Down Expand Up @@ -51,6 +52,18 @@ Set a SARIF category when you upload more than one analysis for the same commit

If you upload multiple SARIF files for the same tool and commit without distinct categories, later uploads replace earlier ones. In GitHub Actions, set the `category:` input on `github/codeql-action/upload-sarif`. Outside Actions, use `runAutomationDetails.id` in the SARIF file.

## Manual verification for one workflow run

After merging a change that touches `tools/sbom-diff-and-risk` or the workflow file itself:

1. Open the repository's **Actions** tab.
2. Open a successful `sbom-diff-and-risk-code-scanning` run for the pull request, or trigger it manually with `workflow_dispatch`.
- the visible run name starts with `sbom-diff-and-risk code scanning / <event> / <ref>`
3. Confirm that the `upload-sarif` job completed successfully.
4. Download the `sbom-diff-and-risk-sarif` artifact and confirm it contains `report.sarif`.
5. Open the repository's **Security** tab, then **Code scanning**.
6. Confirm the uploaded analysis appears under the category `sbom-diff-risk/example`.

## What this integration does not cover

- It does not add CVE lookup or advisory enrichment.
Expand Down
Loading
Loading