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
31 changes: 31 additions & 0 deletions .github/workflows/source-provenance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,37 @@ permissions:
contents: read

jobs:
attest-source-governance:
name: Attest source governance (SLSA Source Track)
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
permissions:
contents: read
attestations: write
id-token: write

steps:
- name: "Harden the runner (Block egress traffic: Only allow calls to allowed endpoints)"
uses: step-security/harden-runner@ab7a9404c0f3da075243ca237b5fac12c98deaa5 # v2.19.3
with:
egress-policy: block
allowed-endpoints: >+
github.com:443
api.github.com:443
uploads.github.com:443
fulcio.sigstore.dev:443
rekor.sigstore.dev:443
tuf-repo-cdn.sigstore.dev:443
*.blob.core.windows.net:443

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Attest source governance (SLSA Source Track)
uses: slsa-framework/slsa-source-corroborator@v0.1.0

attest-source:
name: Generate source provenance
runs-on: ubuntu-latest
Expand Down
16 changes: 8 additions & 8 deletions doc/explanation/threat_model_supply_chain.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ Actors
- External contributor submitting pull requests, or an adversary attempting supply-chain manipulation (malicious PR, action-poisoning, or MITM on CI network traffic). Code review, branch protection, and SHA-pinned Actions are the primary controls at this boundary.

* - Consumer / End User
- Installs dfetch from PyPI (``pip install dfetch``) or from binary installer, then invokes it on a developer workstation or in a CI pipeline. Can verify four complementary attestation types using ``gh attestation verify`` as documented in the release-integrity guide (see C-026, C-039, C-040): SBOM attestation on the PyPI wheel; SBOM, SLSA build provenance, and VSA on binary installers; SLSA build provenance and in-toto test result attestation on the source archive.
- Installs dfetch from PyPI (``pip install dfetch``) or from binary installer, then invokes it on a developer workstation or in a CI pipeline. Can verify five complementary attestation types using ``gh attestation verify`` as documented in the release-integrity guide (see C-026, C-037, C-039, C-040): SBOM attestation on the PyPI wheel; SBOM, SLSA build provenance, and VSA on binary installers; SLSA build provenance, in-toto test result attestation, and SLSA Source Provenance Attestation on the source archive and main-branch commits.


Boundaries
Expand Down Expand Up @@ -319,6 +319,12 @@ Controls
- Tampering
- DFT-28
- Mitigates: ccache and clcache keys in ``build.yml`` include ``${{ github.ref_name }}`` so cache entries written by a pull-request build are scoped to the PR's branch name and cannot be restored by a release-tag build. A malicious fork PR step cannot pre-populate a cache slot that the release workflow will restore, because the release tag name is not reachable from the PR's branch ref. ``.github/workflows/build.yml``
* - C-037
- SLSA Source Provenance Attestation of repository governance controls
- Low
- Repudiation, Spoofing
- DFT-31
- Mitigates: Source Provenance Attestations are published via ``slsa-framework/slsa-source-corroborator`` on every push to ``main``. These attestations prove the specific source-level governance controls applied on each commit: branch protection, mandatory code review, and ancestry enforcement (C-038). Predicate type ``https://slsa.dev/source_provenance/v1`` is signed by GitHub Actions via Sigstore and stored in the GitHub Attestation registry. Consumers can verify using ``gh attestation verify`` with ``--predicate-type https://slsa.dev/source_provenance/v1`` and ``--cert-identity`` pinned to ``source-provenance.yml@refs/heads/main``. ``.github/workflows/source-provenance.yml``
* - C-038
- Ancestry enforcement on dfetch main branch
- Low
Expand All @@ -330,7 +336,7 @@ Controls
- High
- Spoofing, Tampering, Repudiation
- DFT-31, DFT-25
- Mitigates: Every dfetch release ships two complementary Sigstore-signed attestations that together let consumers trace the full source → binary chain. SLSA build provenance (``source-provenance.yml``) on the source archive proves the archive was produced from the official tagged commit by the official CI workflow, recording the exact inputs used at build time. A Verification Summary Attestation (VSA, ``build.yml``) on binary installers records that the source archive was itself attested and verified before the binary was produced, linking source-level trust to the installed package. Both are signed by GitHub Actions via Sigstore and can be verified using ``gh attestation verify`` with ``--predicate-type https://slsa.dev/provenance/v1`` or ``--predicate-type https://slsa.dev/verification_summary/v1`` respectively. This substantially mitigates DFT-31 (consumers now have attestations to verify against) and DFT-25 (forged provenance would fail Sigstore verification). The remaining gap (no formal SLSA Source Level attestation of governance controls) is tracked in C-037. ``doc/howto/verify-integrity.rst``
- Mitigates: Every dfetch release ships two complementary Sigstore-signed attestations that together let consumers trace the full source → binary chain. SLSA build provenance (``source-provenance.yml``) on the source archive proves the archive was produced from the official tagged commit by the official CI workflow, recording the exact inputs used at build time. A Verification Summary Attestation (VSA, ``build.yml``) on binary installers records that the source archive was itself attested and verified before the binary was produced, linking source-level trust to the installed package. Both are signed by GitHub Actions via Sigstore and can be verified using ``gh attestation verify`` with ``--predicate-type https://slsa.dev/provenance/v1`` or ``--predicate-type https://slsa.dev/verification_summary/v1`` respectively. This substantially mitigates DFT-31 (consumers now have attestations to verify against) and DFT-25 (forged provenance would fail Sigstore verification). The formal SLSA Source Level attestation of governance controls is addressed by C-037. ``doc/howto/verify-integrity.rst``
* - C-040
- Test result attestation on source archive
- Medium
Expand Down Expand Up @@ -358,12 +364,6 @@ Gaps
- Tampering
- DFT-10
- Affects: ``pip install .`` and ``pip install --upgrade pip build`` in CI do not use ``--require-hashes``. A compromised PyPI mirror can substitute malicious build tooling.
* - C-037
- No formal SLSA Source Level attestation of repository governance controls
- Low
- Repudiation, Spoofing
- DFT-31
- Affects: dfetch now publishes SLSA build provenance for source archives, VSAs for binary installers (C-039), and in-toto test result attestations (C-040). These close the 'no attestation to verify against' concern: consumers can cryptographically verify the artifact chain. The remaining, narrower gap is that dfetch does not publish formal SLSA Source Provenance Attestations generated by a SLSA Source Generator — attestations that would prove the specific source-level governance controls applied on each commit (branch protection, mandatory code review, ancestry enforcement). C-038 establishes that ancestry enforcement is in place and C-026 documents what consumers can verify; the gap is in machine-readable, verifiable proof of those governance controls rather than the controls themselves. Risk is Low: the missing piece is a formal SLSA Source Level certificate (per the SLSA Source Track spec) rather than the absence of any assurance. Fix: publish Source Provenance Attestations via ``slsa-framework/slsa-source-corroborator`` or equivalent on each push to main.
* - C-025
- No hardware-token MFA for release operations
- High
Expand Down
39 changes: 31 additions & 8 deletions doc/howto/verify-integrity.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,32 @@ Every dfetch release, and every commit merged to ``main``, has cryptographic
attestations signed by GitHub Actions and anchored in
`Sigstore <https://www.sigstore.dev/>`_, all published in the
`attestation registry <https://github.com/dfetch-org/dfetch/attestations>`_.
There are four complementary kinds:
There are five complementary kinds, in pipeline order from source to artifact:

- **Source Provenance Attestation** (SLSA Source Track) — answers *"did this commit
meet governance requirements?"*: proves that branch protection, mandatory code
review, and ancestry enforcement were in place when the commit was merged to
``main``.
- **Test result attestation** (in-toto) — answers *"did the test suite pass?"*:
records that the full CI test suite ran against this exact source archive and every
check passed, before any binary was produced.
- **SLSA build provenance** — answers *"where did this come from?"*: proves the
artifact was produced from the official source commit by the official CI
workflow, and records the exact inputs used at build time.
- **SBOM attestation** (CycloneDX) — answers *"what is inside it?"*: lists every
dependency bundled in the package so you can audit its composition.
- **Verification Summary Attestation (VSA)** — answers *"was the source
independently verified?"*: records that the source archive for this commit was
attested and verified before the binary was produced, linking source-level
trust to the binary package.
- **Test result attestation** (in-toto) — answers *"did the source pass its tests?"*:
records that the full CI test suite ran against this exact source archive and every
check passed, before any binary was produced.
- **Verification Summary Attestation (VSA)** — answers *"was the full chain
verified?"*: records that the source archive was itself attested and verified
before the binary was produced, linking source-level trust to the artifact.

Binary installers have **build provenance, SBOM, and VSA** attestations when source
provenance verification passes (signed by ``build.yml``).
Python packages installed from PyPI have an **SBOM attestation only** (signed by
``python-publish.yml``).
The source archive has a **SLSA build provenance** attestation (signed by
``source-provenance.yml``) and a **test result attestation** (signed by ``test.yml``).
Every commit merged to ``main`` has a **SLSA Source Provenance Attestation** proving
branch governance controls were applied (signed by ``source-provenance.yml``).

To verify, use the `GitHub CLI <https://cli.github.com/>`_. Pass
``--predicate-type`` to target one kind specifically; omit it to accept any.
Expand Down Expand Up @@ -201,6 +206,24 @@ any binary was produced):
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/test.yml@refs/tags/v<version> \
--cert-oidc-issuer https://token.actions.githubusercontent.com

**Source governance — verify SLSA Source Provenance Attestation:**

Every commit merged to ``main`` has a Source Provenance Attestation proving that
branch protection, mandatory code review, and ancestry enforcement were in place
when the commit landed. These attestations are published by
``slsa-framework/slsa-source-corroborator`` and stored in the
`attestation registry <https://github.com/dfetch-org/dfetch/attestations>`_.
Replace ``<sha>`` with the 40-character commit SHA you want to verify:

.. code-block:: bash

$ gh attestation verify \
"git+https://github.com/dfetch-org/dfetch@<sha>" \
--repo dfetch-org/dfetch \
--predicate-type https://slsa.dev/source_provenance/v1 \
--cert-identity https://github.com/dfetch-org/dfetch/.github/workflows/source-provenance.yml@refs/heads/main \
--cert-oidc-issuer https://token.actions.githubusercontent.com

See `GitHub artifact attestations`_ for details.

.. note::
Expand Down
59 changes: 27 additions & 32 deletions security/tm_supply_chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,11 @@ def _make_sc_actors_and_entities(
consumer.description = (
"Installs dfetch from PyPI (``pip install dfetch``) or from binary installer, "
"then invokes it on a developer workstation or in a CI pipeline. "
"Can verify four complementary attestation types using ``gh attestation verify`` as "
"documented in the release-integrity guide (see C-026, C-039, C-040): "
"Can verify five complementary attestation types using ``gh attestation verify`` as "
"documented in the release-integrity guide (see C-026, C-037, C-039, C-040): "
"SBOM attestation on the PyPI wheel; SBOM, SLSA build provenance, and VSA on binary "
"installers; SLSA build provenance and in-toto test result attestation on the source archive."
"installers; SLSA build provenance, in-toto test result attestation, and SLSA Source "
"Provenance Attestation on the source archive and main-branch commits."
)
gh_repository = ExternalEntity("A-01: GitHub Repository")
gh_repository.inBoundary = b_github
Expand Down Expand Up @@ -658,6 +659,28 @@ def build_model() -> TM:
"the PR's branch ref."
),
),
Control(
id="C-037",
name="SLSA Source Provenance Attestation of repository governance controls",
assets=["A-01"],
threats=["DFT-31"],
reference=".github/workflows/source-provenance.yml",
assessment=ControlAssessment(
status="implemented", risk="Low", stride=["Repudiation", "Spoofing"]
),
description=(
"Source Provenance Attestations are published via "
"``slsa-framework/slsa-source-corroborator`` on every push to ``main``. "
"These attestations prove the specific source-level governance controls "
"applied on each commit: branch protection, mandatory code review, and "
"ancestry enforcement (C-038). "
"Predicate type ``https://slsa.dev/source_provenance/v1`` is signed by "
"GitHub Actions via Sigstore and stored in the GitHub Attestation registry. "
"Consumers can verify using ``gh attestation verify`` with "
"``--predicate-type https://slsa.dev/source_provenance/v1`` and "
"``--cert-identity`` pinned to ``source-provenance.yml@refs/heads/main``."
),
),
Control(
id="C-038",
name="Ancestry enforcement on dfetch main branch",
Expand Down Expand Up @@ -701,8 +724,7 @@ def build_model() -> TM:
"or ``--predicate-type https://slsa.dev/verification_summary/v1`` respectively. "
"This substantially mitigates DFT-31 (consumers now have attestations to verify "
"against) and DFT-25 (forged provenance would fail Sigstore verification). "
"The remaining gap (no formal SLSA Source Level attestation of governance "
"controls) is tracked in C-037."
"The formal SLSA Source Level attestation of governance controls is addressed by C-037."
),
),
Control(
Expand Down Expand Up @@ -742,33 +764,6 @@ def build_model() -> TM:
"malicious build tooling."
),
),
Control(
id="C-037",
name="No formal SLSA Source Level attestation of repository governance controls",
assets=["A-01"],
threats=["DFT-31"],
assessment=ControlAssessment(
status="gap", risk="Low", stride=["Repudiation", "Spoofing"]
),
description=(
"dfetch now publishes SLSA build provenance for source archives, VSAs for "
"binary installers (C-039), and in-toto test result attestations (C-040). "
"These close the 'no attestation to verify against' concern: consumers can "
"cryptographically verify the artifact chain. "
"The remaining, narrower gap is that dfetch does not publish formal SLSA "
"Source Provenance Attestations generated by a SLSA Source Generator — "
"attestations that would prove the specific source-level governance controls "
"applied on each commit (branch protection, mandatory code review, ancestry "
"enforcement). "
"C-038 establishes that ancestry enforcement is in place and C-026 documents "
"what consumers can verify; the gap is in machine-readable, verifiable "
"proof of those governance controls rather than the controls themselves. "
"Risk is Low: the missing piece is a formal SLSA Source Level certificate "
"(per the SLSA Source Track spec) rather than the absence of any assurance. "
"Fix: publish Source Provenance Attestations via "
"``slsa-framework/slsa-source-corroborator`` or equivalent on each push to main."
),
),
Control(
id="C-025",
name="No hardware-token MFA for release operations",
Expand Down
Loading