-
Notifications
You must be signed in to change notification settings - Fork 533
docs: Add supply-chain security section #5812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
367e1a3
47cacca
e6e65ff
93ef2eb
06cb6be
55505bc
5b1aff4
1548c3a
8ffdf6a
cb21346
373622b
bd33853
e5c0695
96f831a
fbab6bd
eb88b65
20b8d27
22827fd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,140 @@ | ||
| # Supply Chain Security | ||
|
|
||
| Pixi helps reduce supply chain risk in a few different ways: | ||
|
|
||
| - it resolves environments into a lock file, so installs are based on explicit artifacts instead of whatever happens to be newest at install time; | ||
| - it can exclude recently published packages with [`exclude-newer`](reference/pixi_manifest.md#exclude-newer-optional); | ||
| - it lets you react to advisories by constraining or overriding affected dependencies; | ||
| - it supports generating and uploading Sigstore attestations when publishing to prefix.dev. | ||
|
|
||
| At the same time, Pixi does not try to be a full vulnerability scanner for conda environments. Today, our preferred way to inspect a Pixi-managed environment for CVE analysis is to generate an SBOM from the installed environment with [Syft](https://github.com/anchore/syft). | ||
|
|
||
| ## Reproducible Dependency Resolution | ||
|
|
||
| The first layer of supply chain security is reproducibility. | ||
|
|
||
| Pixi records the resolved environment in `pixi.lock`, including the exact package artifacts that were selected. That gives you a stable review surface in code review and makes unexpected dependency changes visible when the lock file changes. | ||
|
|
||
| To review lock file changes between commits in a human-readable way, you can use [`pixi-diff`](integration/extensions/pixi_diff.md) directly or integrate the output into CI with [`pixi-diff-to-markdown`](integration/ci/updates_github_actions.md). | ||
|
|
||
| Using the following command, you can generate a readable overview of what changed between an older lock file and your current one: | ||
|
|
||
| ```bash | ||
| # bash / zsh | ||
| pixi diff --before <(git show HEAD~20:pixi.lock) --after pixi.lock | pixi diff-to-markdown | ||
|
|
||
| # fish | ||
| pixi diff --before (git show HEAD~20:pixi.lock | psub) --after pixi.lock | pixi diff-to-markdown | ||
| ``` | ||
|
|
||
| ## Delaying Fresh Uploads With `exclude-newer` | ||
|
|
||
| One practical defense against compromised package releases is to avoid resolving against packages uploaded very recently. | ||
|
|
||
| For security-focused setups, relative durations are usually the most practical configuration. A common pattern is to keep a delay for public channels, while allowing trusted internal channels or specific emergency fixes through immediately. See [`exclude-newer`](reference/pixi_manifest.md#exclude-newer-optional) for the supported manifest field: | ||
|
|
||
| ```toml | ||
| [workspace] | ||
| name = "my-workspace" | ||
| channels = [ | ||
| "conda-forge", | ||
| # get most recent versions of packages you control | ||
| { channel = "https://prefix.dev/my-internal-channel", exclude-newer = "0d" }, | ||
| ] | ||
| exclude-newer = "14d" | ||
| platforms = ["linux-64", "osx-arm64", "win-64"] | ||
|
|
||
| [dependencies] | ||
| # CVE-XXXX-YYYY: allow the fresh fixed build immediately | ||
| python = { version = "3.12.*", exclude-newer = "0d" } | ||
|
|
||
| [constraints] | ||
| # CVE-XXXX-YYYY: allow the fresh fixed build immediately | ||
| openssl = { exclude-newer = "0d" } | ||
| ``` | ||
|
|
||
| In that example: | ||
|
|
||
| - all packages are delayed by 14 days by default; | ||
| - packages from the internal channel are not delayed; | ||
| - `openssl` and `python` are allowed through immediately, even if the fixed build is fresh. | ||
|
|
||
| This is useful when you want a conservative trust window for public ecosystems, but still need to selectively force-include trusted or urgent fixes for a channel or dependency. | ||
|
|
||
| !!! tip "CEP for `upload_timestamp` in repodata" | ||
| There is also an in-progress proposal, [conda/ceps#154](https://github.com/conda/ceps/pull/154), to include upload timestamps in `repodata.json`. If adopted, that would let tools consume channel-provided upload times directly and harden this workflow against spoofed timestamp entries from conda-forge itself. | ||
|
|
||
| ## Responding To Vulnerability Advisories Using Dependency Overrides | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suspect few people will ever do this manually. Would some equivalent of
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at the moment not yet. once conda/ceps#63 is done, i think we could implement a first version of this though. |
||
|
|
||
| When a CVE affects one of your dependencies, there the best way to respond is to update your dependency to a non-vulnerable version. | ||
| In those cases, you might need to decrease the package-specific `exclude-newer` as mentioned above. | ||
|
|
||
| It can happen that another dependency has an upper bound preventing pixi from solving this environment with the updated dependency. | ||
| To mitigate this, you can override certain dependencies using [`dependency-overrides`](advanced/override.md). | ||
|
|
||
| !!!note "PyPi-only for now" | ||
| We are planning to support a similar feature like this for Conda packages as well. For more information, see [pixi#4891](https://github.com/prefix-dev/pixi/issues/4891). | ||
|
|
||
| ```toml | ||
| [pypi-options.dependency-overrides] | ||
| # force all packages to depend on urllib3 >=2.2.2 | ||
| urllib3 = ">=2.2.2" | ||
| ``` | ||
|
|
||
| These controls are complementary to `exclude-newer`: `exclude-newer` reduces exposure to newly uploaded artifacts, while constraints and overrides help you respond once a vulnerable version is already known. | ||
|
|
||
| ## SBOM Generation Today | ||
|
|
||
| To analyze a Pixi-managed conda environment for vulnerabilities today, our preferred workflow is to generate an SBOM from the installed environment with [Syft](https://github.com/anchore/syft). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless you want to archive the SBOM or share it with someone else (e.g. a client who uses a pixi environment created by you), I think you can skip the SBOM step here and go straight to grype
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mentioned grype in the default recommended workflow: |
||
|
|
||
| For a default workspace environment, that usually means scanning the environment directory directly: | ||
|
|
||
| ```bash | ||
| syft .pixi/envs/default | ||
| ``` | ||
|
|
||
| This matters because scanning the installed environment captures what is actually present on disk, not just what was requested in the manifest. | ||
|
|
||
| Syft is especially useful as the inventory step in that process: it catalogs the installed software and produces an SBOM that can then be fed into the rest of your vulnerability workflow. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure into how much detail we want to go here, but going syft -> CycloneDX -> vulnerability scanner is probably not optimal bc information is lost there. When I tested this, I found that syft -> CycloneDX -> grype gets different results than syft -> syft format sbom -> grype. It's further worth mentioning that for conda packages,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And very confusingly,
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| For Rust packages on conda-forge, building with `cargo-auditable` remains the current recommendation because it makes those shadow dependencies visible to downstream scanning tools. See the conda-forge [Rust packaging guide](https://conda-forge.org/docs/maintainer/example_recipes/rust) or the [conda-forge agent skill](https://prefix.dev/channels/skill-forge/packages/agent-skill-conda-forge) for the recommended recipe pattern. | ||
|
|
||
| ## Package Signing And Attestations | ||
|
|
||
| Pixi already supports Sigstore-based attestations when publishing packages to [prefix.dev](https://prefix.dev). | ||
|
|
||
| For example: | ||
|
|
||
| ```bash | ||
| pixi publish --to https://prefix.dev/<channel-name> --generate-attestation | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be good to comment on how this works for private channels. Is the public good sigstore instance used? In that case, users should be well informed that some metadata of their build will be public.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wolfv could you elaborate here?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just discussed with @wolfv. It works also for private channels, but the GitHub repo must be public. As mentioned here, we plan to charge for this feature in the future for everyone but public, open-source channels: https://prefix.dev/blog/securing-the-conda-package-supply-chain-with-sigstore And yes, indeed, that metadata would be public
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think it would be great if there was the possibility to have private attestation metadata as well but this is definitely out of scope for this PR |
||
| ``` | ||
|
|
||
| When using the lower-level upload command for prefix.dev, Pixi can also upload an existing attestation or generate one during CI: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How does the
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean with "lower-level" here?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbh i still haven't fully grasped the difference between
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that is a fair summary. I also checked and
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. some things are still a bit rough around the edges around uploading attestations: conda/rattler#2313 |
||
|
|
||
| ```bash | ||
| pixi upload prefix --channel <channel-name> --generate-attestation dist/*.conda | ||
| ``` | ||
|
|
||
| One example of a channel that already uses package signing extensively is the [github-releases](https://prefix.dev/channels/github-releases) channel on prefix.dev (GitHub: [hunger/octoconda](https://github.com/hunger/octoconda)). | ||
|
|
||
| !!!note "" | ||
| We are actively working on adding package signing to conda-forge, the most popular Conda channel. | ||
|
|
||
| !!!tip "" | ||
| This is part of the broader conda ecosystem work to standardize attestation and signing. The current attestation work is captured in [CEP 27](https://conda.org/learn/ceps/cep-0027/), and broader package signing and Sigstore-serving work is still evolving in the ecosystem. We are also working on a proposal for serving this information on prefix.dev in [conda/ceps#142](https://github.com/conda/ceps/pull/142). | ||
|
|
||
| ## Work In Progress | ||
|
|
||
| Cross-ecosystem vulnerability matching for conda packages is still improving. | ||
|
|
||
| We are currently working on a PURL-related Conda Enhancement Proposal, [conda/ceps#63](https://github.com/conda/ceps/pull/63), that will make it easier to match conda-installed software against CVEs that are tracked in other ecosystems like PyPi. | ||
| Today, generating an SBOM from the already-installed environment with tools like Syft is still the most practical workaround for that gap. | ||
|
|
||
| For a broader view of the conda ecosystem work around regulatory readiness, SBOMs, CVE mapping, and auditable Rust binaries, see QuantCo's post, [Making the conda(-forge) ecosystem ready for cybersecurity regulations](https://tech.quantco.com/blog/conda-regulation-support). | ||
|
|
||
| Until that work is standardized and widely implemented, the safest approach is: | ||
|
|
||
| - keep lock files under review; | ||
| - use `exclude-newer` where a delayed trust window makes sense; | ||
| - update your dependencies when advisories land; | ||
| - generate an SBOM from the installed environments with Syft as part of your security review workflow. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Especially in this condensed version, I think it would be more fruitful to tell people to scan for vulns than to advise generating an SBOM. SBOM by itself does not tell you much.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
Uh oh!
There was an error while loading. Please reload this page.