Skip to content

docs: Add supply-chain security section#5812

Merged
Hofer-Julian merged 18 commits intoprefix-dev:mainfrom
pavelzw:docs-supply-chain-security
Apr 8, 2026
Merged

docs: Add supply-chain security section#5812
Hofer-Julian merged 18 commits intoprefix-dev:mainfrom
pavelzw:docs-supply-chain-security

Conversation

@pavelzw
Copy link
Copy Markdown
Collaborator

@pavelzw pavelzw commented Apr 2, 2026

Description

depends on #5786

I haven't played much with the sigstore stuff yet. Feel free to extend it.

How Has This Been Tested?

AI Disclosure

  • This PR contains AI-generated content.
    • I have tested any AI-generated content in my PR.
    • I take responsibility for any AI-generated content in my PR.

Tools: codex

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added sufficient tests to cover my changes.
  • I have verified that changes that would impact the JSON schema have been made in schema/model.py.

Comment thread docs/security.md Outdated

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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, syft currently just generates a cpe, but not a purl, so for grype to match anything, I think you have to configure it to use cpes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

And very confusingly, syft will generate SBOM entries based on conda metadata if you are running it on a file system location as your example shows, but it will not do this by default if you run it on a container image that contains a conda environment. Internally, we settled on just always passing --select-catalogers=+conda-meta-cataloger,+cargo-auditable-binary-cataloger to syft to make sure we are never surprised

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread docs/security.md Outdated

## 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).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

mentioned grype in the default recommended workflow: 5b1aff4 (this PR)

Comment thread docs/security.md Outdated
!!! 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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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 npm audit fix be possible?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

at the moment not yet.
currently it's not trivial to link a conda package to a package in the pypi ecosystem and there is no CVE numbering authority (not sure whether this is the right terminology) yet for conda-forge. @wolfv would like to have this but not sure when this will be the case.

once conda/ceps#63 is done, i think we could implement a first version of this though.

Comment thread docs/security.md
For example:

```bash
pixi publish --to https://prefix.dev/<channel-name> --generate-attestation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@wolfv could you elaborate here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The 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

Comment thread docs/security.md Outdated
- 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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread docs/security.md Outdated
pavelzw and others added 2 commits April 2, 2026 22:44
Co-authored-by: Andreas Albert <103571926+AndreasAlbertQC@users.noreply.github.com>
Comment thread docs/security.md Outdated
Comment thread docs/security.md Outdated

**How to implement it**

If you publish packages that others consume, generate attestations in CI by default and document how your consumers should verify them.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be neat to document here how I can retrieve and verify an attestation on prefix.dev. In OCI registries, discovery of attestations is handled through the referrers API, i.e. there is a dedicated part of the OCI distribution spec that makes it easy to find attestations for a given artifact programmatically. Is there a similar mechanism here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

you can view it on prefix.dev directly, example: https://prefix.dev/channels/github-releases/packages/actionlint

image

my assumption is that programmatic verification is not yet implemented in pixi. once conda/ceps#142 lands, i would expect that we will get some sort of entrypoint for this - either through pixi extensions like pixi-browse (i'm planning to add it anyway to pixi-browse once available) or directly as a pixi subcommand

maybe @wolfv can elaborate here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, I don't think we do anything with this from within Pixi at this moment

Comment thread docs/security.md
pixi publish --to https://prefix.dev/<channel-name> --generate-attestation
```

When using the lower-level upload command for prefix.dev, Pixi can also upload an existing attestation or generate one during CI:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

How does the upload an existing attestation part work?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

pixi upload --attestation <attestation>. not sure what this does exactly, though. probably best if we actually have a whole page for attestations explaining how exactly it works.

Comment thread docs/security.md Outdated

**How it works**

Overrides let you force dependency requirements during resolution so the solver can select a safe version even if upstream packages have not caught up yet.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Might be good to point out that adding an override might break package functionality. In the best case, the package maintainers release a patch version of whatever minor you are on, so the risk is small, but I think the realistic scenario is that often there will just be a patch of the latest major/minor, meaning the override can introduce breaking changes. To TLDR for users is: don't trust overrides blindly

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@pavelzw pavelzw requested a review from AndreasAlbertQC April 4, 2026 15:10
Comment thread docs/security.md
Comment on lines +252 to +265
```bash
gh attestation verify my-package-0.1.0-h123_0.conda \
--owner my-org \
--predicate-type "https://schemas.conda.org/attestations-publish-1.schema.json"
```

Or with `cosign`:

```bash
cosign verify-blob \
--certificate-identity-regexp "https://github.com/my-org/.*" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
my-package-0.1.0-h123_0.conda
```
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Afaiu Rattler-Build publish --generate-attestation doesn't publish those to GitHub's attestation registry and thus also leads to gh attestation verify failing. In my tests in https://github.com/pavelzw/skill-forge, those attestations were only available on sigstore.dev

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, I think that is correct. I am not an expert with attestations, but if you think that would be good addition, I would appreciate an issue for this

Copy link
Copy Markdown
Contributor

@Hofer-Julian Hofer-Julian left a comment

Choose a reason for hiding this comment

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

Thank you, Pavel!

I left a few comments

Comment thread docs/security.md Outdated
Comment thread docs/security.md Outdated

## 1. Make Dependency Resolution Reproducible

**What it is**
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Apart from it feeling pretty AI-ish, I find the "what it is", "what it helps against" and "how it works" pattern very difficult to read. In this specific section it's especially bad since the interesting part "keep pixi.lock in version control" is only mentioned in the very last sentence.

I feel like having one consistent block of prose after each subsection here would make this nicer.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment thread docs/security.md Outdated
Comment thread docs/security.md Outdated
Comment thread docs/security.md Outdated
Comment thread docs/security.md

If you use `direnv`, be aware that `watch_file pixi.lock` improves convenience but also lowers the friction for activation-time code execution after dependency changes. Re-introduce an approval step on lock file changes as soon as your `direnv` version supports it.

## 5. Scan The Installed Environment Directly
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

After reading this, I still struggle to understand how this works and against what it does or does not protect. I also think it mixes responsibilities between "how it works" and "how to implement"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

tried to improve it in 22827fd (this PR)

Comment thread docs/security.md
For example:

```bash
pixi publish --to https://prefix.dev/<channel-name> --generate-attestation
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

Comment thread docs/security.md
pixi publish --to https://prefix.dev/<channel-name> --generate-attestation
```

When using the lower-level upload command for prefix.dev, Pixi can also upload an existing attestation or generate one during CI:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What do you mean with "lower-level" here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

tbh i still haven't fully grasped the difference between pixi upload and pixi publish. to me, it seems that pixi upload uploads only a single file while pixi publish does the whole higher-level flow, namely build everything, generate attestations, login to prefix.dev using oidc, upload package + attestations

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah that is a fair summary.

I also checked and pixi publish indeed doesn't set github attestations

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The 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

Comment thread docs/security.md
Comment on lines +252 to +265
```bash
gh attestation verify my-package-0.1.0-h123_0.conda \
--owner my-org \
--predicate-type "https://schemas.conda.org/attestations-publish-1.schema.json"
```

Or with `cosign`:

```bash
cosign verify-blob \
--certificate-identity-regexp "https://github.com/my-org/.*" \
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
my-package-0.1.0-h123_0.conda
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, I think that is correct. I am not an expert with attestations, but if you think that would be good addition, I would appreciate an issue for this

Comment thread docs/security.md Outdated

**How to implement it**

If you publish packages that others consume, generate attestations in CI by default and document how your consumers should verify them.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yes, I don't think we do anything with this from within Pixi at this moment

pavelzw and others added 5 commits April 7, 2026 15:38
Co-authored-by: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com>
Co-authored-by: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com>
Co-authored-by: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com>
Co-authored-by: Hofer-Julian <30049909+Hofer-Julian@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@Hofer-Julian Hofer-Julian left a comment

Choose a reason for hiding this comment

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

Much better, thank you for all your work Pavel 🫶

@Hofer-Julian Hofer-Julian merged commit 0cf9c8c into prefix-dev:main Apr 8, 2026
40 checks passed
@pavelzw pavelzw deleted the docs-supply-chain-security branch April 8, 2026 07:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants