CEP about serving sigstore attestations in Conda repositories#142
CEP about serving sigstore attestations in Conda repositories#142wolfv wants to merge 5 commits intoconda:mainfrom
Conversation
|
|
||
| This proposal is fully backwards compatible: | ||
|
|
||
| 1. **Existing channels**: No changes required; clients will receive `404` for `.sigs` endpoints |
There was a problem hiding this comment.
Is this correct? In the section HTTP Status Codes above we specify:
|
404 Not Found| The package does not exist (distinct from "no attestations") |(...) Channels MUST return
404 Not Foundonly when the underlying package does not exist.
Won't new clients who request the .sigs file from an old/existing channel receive 404 and interpret it as "the package does not exist", when instead it should be "no attestations available for that package"?
There was a problem hiding this comment.
this thread can be resolved
|
|
||
| 3. **Works with existing infrastructure**: The sidecar file approach integrates naturally with static file hosting, CDNs, and mirrors. | ||
|
|
||
| 4. **Follows ecosystem conventions**: Similar approaches are used by PyPI ([Integrity API][PyPI Integrity]), npm ([provenance attestations][npm provenance]), and RubyGems. |
There was a problem hiding this comment.
There was a problem hiding this comment.
this thread can be resolved
| ] | ||
| ``` | ||
|
|
||
| Each element in the array MUST be a valid [Sigstore Bundle] as defined by the Sigstore specification. The bundle format supports multiple versions; implementations SHOULD support at least bundle versions v0.2 and v0.3. |
There was a problem hiding this comment.
I don't know if we should specify bundle versions here. This CEP defines the how to serve attestations (format, location) so that clients can access them. But IMHO, the bundle itself should be a black box to this CEP, other than "each element must be a valid sigstore bundle" I don't think we should go into internals (which are covered by CEP 27)
There was a problem hiding this comment.
this thread can be resolved
| | Status Code | Meaning | | ||
| |-------------|---------| | ||
| | `200 OK` | Attestations returned successfully (may be empty array) | | ||
| | `404 Not Found` | The package does not exist (distinct from "no attestations") | |
There was a problem hiding this comment.
Adding more context from my older comment about this being backwards compatible:
I think 404 should have the meaning "the package does not exist AND/OR the channel does not support attestations".
Otherwise (new) clients communicating with (old) channels could try to retrieve the .sigs file, see 404, and interpret "the package does not exist", where the reality is that the channel does not support yet this CEP
There was a problem hiding this comment.
this thread can be resolved
| A package MAY have multiple attestations from different sources. Common scenarios include: | ||
|
|
||
| | Source | Purpose | | ||
| |--------|---------| | ||
| | Build system (e.g., GitHub Actions) | Proves the package was built from specific source code | | ||
| | Channel operator | Proves the channel accepted and published the package | | ||
| | Third-party auditor | Proves the package passed security review | |
There was a problem hiding this comment.
I would remove the "common scenarios" here, or maybe reword it as a list of examples of potential future usecases.
There was a problem hiding this comment.
this has not been addressed yet
| 1. Fetch and cache `.sigs` files alongside packages | ||
| 2. Serve cached attestations without modification |
There was a problem hiding this comment.
Can attestations for a file be uploaded post-facto? If not, might that be a future feature? (like the example above, where a third party auditor might review and upload and attestation after the artifact is publicly available)
If so, this section should account for how mirrors should update changed .sigs files. Is there a way for mirrors (or any client) to detect such changes?
There was a problem hiding this comment.
As we discussed in Brussels we want to add the SHA256 of the signatures file to the repodata which would make it possible for the mirrors to detect changes.
There was a problem hiding this comment.
this thread can be resolved
|
|
||
| Clients implementing attestation verification SHOULD follow this workflow: | ||
|
|
||
| 1. **Download package** from the channel (or use the SHA256 sum from the repodata.json) |
There was a problem hiding this comment.
or use the SHA256 sum from the repodata.json
What's the usecase for this? The client should always hash the package itself for verification. If, as a first step, it only uses the hash from the repodata.json to verify the attestation then before installing it should also check that the downloaded file matches that hash. Is that the case now?
There was a problem hiding this comment.
this thread can be resolved
| 3. **Verify each attestation** according to the client's trust policy: | ||
| - Verify the Sigstore bundle signature | ||
| - Verify the certificate chain to Fulcio root | ||
| - Verify the transparency log inclusion proof | ||
| - Verify the in-toto subject matches the downloaded package |
There was a problem hiding this comment.
I would not put this here, I would just refer to the verification process specified in CEP 27
There was a problem hiding this comment.
this thread can be resolved
| | Setting | Values | Behavior | | ||
| |---------|--------|----------| | ||
| | `enabled` | `true`/`false` | Enable or disable attestation fetching and verification | | ||
| | `require` | `error` | Fail if attestations are missing or invalid | | ||
| | | `warn` | Log warning but continue if attestations are missing or invalid | | ||
| | | `ignore` | Silently continue (still verify if attestations exist) | | ||
| | `trusted_identities` | List of patterns | Only accept attestations from matching Sigstore identities | |
There was a problem hiding this comment.
is this practical? I could see the usecase for a private channel where all artifacts are uploaded by the same trusted identity, but in the general usecase there will be one identity per package, so it doesn't make sense to list them all here (rather than relying on a lockfile with identities). I don't think we should require this of the clients, instead we might want to require the clients supporting identities in lockfiles.
There was a problem hiding this comment.
Your proposal would be to do some kind of TOFU from the lockfile? Ie. warn / error when an identity changes?
I think for a lot of channels, the publishers are much more homogenous vs. PyPI. E.g. one could at least choose the Github organization with wildcard, or even the repository for an entire channel (e.g. see the rust-forge: https://github.com/wolfv/rust-forge)
There was a problem hiding this comment.
this thread can be resolved
| ### Offline and Air-gapped Environments | ||
|
|
||
| For offline verification, clients MAY cache `.sigs` files alongside packages in local repositories | ||
| The Sigstore bundle format is self-contained and supports offline verification once the Sigstore trust root is available locally. |
There was a problem hiding this comment.
Maybe we should mention here that the trust root should be updated periodically, since part of its security guarantees come from the fact that target/keys can be revoked
There was a problem hiding this comment.
this thread can be resolved
| The security of this scheme depends on: | ||
|
|
||
| 1. **Sigstore infrastructure**: Fulcio CA, Rekor transparency log, and their availability | ||
| 2. **Identity binding**: OIDC providers correctly authenticating signing identities | ||
| 3. **Client trust policy**: Correctly configured trusted identities | ||
| 4. **TLS security**: Secure transport when fetching attestations | ||
|
|
||
| ### Threat Mitigations | ||
|
|
||
| | Threat | Mitigation | | ||
| |--------|------------| | ||
| | Forged attestations | Sigstore signatures are cryptographically verified against Fulcio certificates | | ||
| | Tampered attestations | Rekor transparency log provides tamper evidence | | ||
| | Replay attacks | In-toto subject binds attestation to specific artifact hash | | ||
| | Removed attestations | Rekor log entries are permanent; monitors can detect removal | | ||
| | Compromised signing identity | Transparency log enables detection; trust policy limits blast radius | | ||
|
|
||
| ### Limitations | ||
|
|
||
| This scheme does NOT protect against: | ||
|
|
||
| 1. Legitimate signers publishing malicious packages | ||
| 2. Compromise of the Sigstore infrastructure itself | ||
| 3. Incorrect client trust policies | ||
| 4. Attacks before attestation was added to the package |
There was a problem hiding this comment.
I'm not sure we should rehash the security model here (which should be covered by CEP 27).
There was a problem hiding this comment.
this thread can be resolved
evankanderson
left a comment
There was a problem hiding this comment.
I swung by, since this got posted to the OpenSSF #general channel, and I was curious. Feel free to disregard.
|
|
||
| 1. **Enables client verification**: Clients can fetch attestations alongside packages and verify them before installation. | ||
|
|
||
| 2. **Supports multiple attestations**: A single package may have multiple attestations (e.g., from the build system, from the channel on upload, from third-party auditors). |
There was a problem hiding this comment.
While this CEP describes the endpoint as "RESTful", it seems like it may be a read-only endpoint?
If you want to support additional attestations from third-parties, you'll need to figure out access control for users "vouching" for other packages. That seems like a diversion from the main goal of this CEP, so it might be worth calling out third-party auditors as a future capability that you don't want to prevent.
There was a problem hiding this comment.
While this CEP describes the endpoint as "RESTful", it seems like it may be a read-only endpoint?
These are not in contradiction, right?
If you want to support additional attestations from third-parties, you'll need to figure out access control for users "vouching" for other packages. That seems like a diversion from the main goal of this CEP, so it might be worth calling out third-party auditors as a future capability that you don't want to prevent.
Not necessarily? A third party could generate attestations, and a channel admin could upload them to their respective packages, without giving access to the third party. This section is characterizing the distribution mechanism, the "attestations from third-party auditors" is just an example of a type of attestation that may exist.
| "attestations": "37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570" | ||
| } | ||
| ``` |
There was a problem hiding this comment.
I'm assuming this is because of the discussion here: https://github.com/conda/ceps/pull/142/changes#r2816839339
It might be worth a sentence here to suggest the rationale:
| "attestations": "37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570" | |
| } | |
| ``` | |
| "attestations": "37517e5f3dc66819f61f5a7bb8ace1921282415f10551d2defa5c3eb0985b570" | |
| } | |
| \``` | |
| The signatures hash enables mirrors to detect and re-fetch signature bundles as they are added to the repo. |
(GitHub suggestions can't include the close-block, so I had to escape it. 😢 )
|
|
||
| Each attestation in the response MUST comply with [CEP 27]. Specifically: | ||
|
|
||
| 1. The in-toto statement's `subject[0].name` MUST match the artifact filename. |
There was a problem hiding this comment.
Does this need to be subject[0].name? I'm imagining that I might have a CI process which produces an attestation for all the artifacts produced in a single attestation, so I have N+1 outputs, rather than 2N outputs. Should 1. and 2. be changed to "One of the attestation subjects MUST match as follows: (a) subject[N].name MUST match the artifact filename AND (b) `subject[N].digest.sha256 MUST match the SHA256 hash of the artifact"?
There was a problem hiding this comment.
The reason for this is that having one attestation per artifact makes things simpler from a verification POV, and also prevents certain footguns (more context here)
| | `require` | `error` | Fail if attestations are missing or invalid | | ||
| | | `warn` | Log warning but continue if attestations are missing or invalid | | ||
| | | `ignore` | Silently continue (still verify if attestations exist) | |
There was a problem hiding this comment.
Is there a default value for require (or the other settings)? In the example, require is omitted for the "foobar" repository.
There was a problem hiding this comment.
I vote for making the 3 fields mandatory, with no default values
|
|
||
| 1. **Download package** from the channel | ||
| 2. **Fetch attestations** from `<package_url>.sigs` | ||
| 3. **Verify each attestation** against the configuration. |
There was a problem hiding this comment.
make explicit that the verification process is defined in CEP-27
| For offline verification, clients MAY cache `.sigs` files alongside packages in local repositories. | ||
| The Sigstore bundle format is self-contained and supports offline verification once the Sigstore trust root is available locally. | ||
|
|
||
| Note: clients MUST periodically update the sigstore trust root to ensure no keys were revoked. |
There was a problem hiding this comment.
the reason is more general, it's to ensure the client doesn't miss any trust root changes (which could be key revocation, but also new keys added)
|
|
||
| This proposal is fully backwards compatible: | ||
|
|
||
| 1. **Existing channels**: No changes required; clients will receive `404` for `.sigs` endpoints |
There was a problem hiding this comment.
this thread can be resolved
|
|
||
| 3. **Works with existing infrastructure**: The sidecar file approach integrates naturally with static file hosting, CDNs, and mirrors. | ||
|
|
||
| 4. **Follows ecosystem conventions**: Similar approaches are used by PyPI ([Integrity API][PyPI Integrity]), npm ([provenance attestations][npm provenance]), and RubyGems. |
There was a problem hiding this comment.
this thread can be resolved
| ] | ||
| ``` | ||
|
|
||
| Each element in the array MUST be a valid [Sigstore Bundle] as defined by the Sigstore specification. The bundle format supports multiple versions; implementations SHOULD support at least bundle versions v0.2 and v0.3. |
There was a problem hiding this comment.
this thread can be resolved
|
|
||
| Clients implementing attestation verification SHOULD follow this workflow: | ||
|
|
||
| 1. **Download package** from the channel (or use the SHA256 sum from the repodata.json) |
There was a problem hiding this comment.
this thread can be resolved
| 3. **Verify each attestation** according to the client's trust policy: | ||
| - Verify the Sigstore bundle signature | ||
| - Verify the certificate chain to Fulcio root | ||
| - Verify the transparency log inclusion proof | ||
| - Verify the in-toto subject matches the downloaded package |
There was a problem hiding this comment.
this thread can be resolved
| | Setting | Values | Behavior | | ||
| |---------|--------|----------| | ||
| | `enabled` | `true`/`false` | Enable or disable attestation fetching and verification | | ||
| | `require` | `error` | Fail if attestations are missing or invalid | | ||
| | | `warn` | Log warning but continue if attestations are missing or invalid | | ||
| | | `ignore` | Silently continue (still verify if attestations exist) | | ||
| | `trusted_identities` | List of patterns | Only accept attestations from matching Sigstore identities | |
There was a problem hiding this comment.
this thread can be resolved
| ### Offline and Air-gapped Environments | ||
|
|
||
| For offline verification, clients MAY cache `.sigs` files alongside packages in local repositories | ||
| The Sigstore bundle format is self-contained and supports offline verification once the Sigstore trust root is available locally. |
There was a problem hiding this comment.
this thread can be resolved
| The security of this scheme depends on: | ||
|
|
||
| 1. **Sigstore infrastructure**: Fulcio CA, Rekor transparency log, and their availability | ||
| 2. **Identity binding**: OIDC providers correctly authenticating signing identities | ||
| 3. **Client trust policy**: Correctly configured trusted identities | ||
| 4. **TLS security**: Secure transport when fetching attestations | ||
|
|
||
| ### Threat Mitigations | ||
|
|
||
| | Threat | Mitigation | | ||
| |--------|------------| | ||
| | Forged attestations | Sigstore signatures are cryptographically verified against Fulcio certificates | | ||
| | Tampered attestations | Rekor transparency log provides tamper evidence | | ||
| | Replay attacks | In-toto subject binds attestation to specific artifact hash | | ||
| | Removed attestations | Rekor log entries are permanent; monitors can detect removal | | ||
| | Compromised signing identity | Transparency log enables detection; trust policy limits blast radius | | ||
|
|
||
| ### Limitations | ||
|
|
||
| This scheme does NOT protect against: | ||
|
|
||
| 1. Legitimate signers publishing malicious packages | ||
| 2. Compromise of the Sigstore infrastructure itself | ||
| 3. Incorrect client trust policies | ||
| 4. Attacks before attestation was added to the package |
There was a problem hiding this comment.
this thread can be resolved
| | --------------- | ------------------------------------------------------------ | | ||
| | `200 OK` | Attestations returned successfully (may be empty array) | | ||
|
|
||
| Channels that support attestations MUST always return `200 OK` with an empty array `[]`, even when the package does not exist. |
There was a problem hiding this comment.
My previous comment was about the ambiguity of defining a 404 error on the .sigs endpoint as "this package does not exist", when channels that don't implement this CEP would return 404 on the .sigs endpoint for every package.
I think we should return 404 when the package does not exist, but define the meaning of 404 as:
- For channels implementing this CEP, 404 means the package does not exist
- For channels not implementing this CEP,
.sigsalways returns 404
and make it clear that clients should not use the .sigs endpoint to determine if a package exists or not
This CEP adds specifications how to serve sigstore attestations in Conda repositories.
A preview implementation is available on beta.prefix.dev under the following URL:
https://beta.prefix.dev/wolf-channel/linux-64/signed-package-1.2.1-hb0f4dca_0.conda.v0.sigs