CEP XXXX: add recipe source attestation validation - #168
Conversation
| ### Publisher Identity Grammar | ||
|
|
||
| A publisher identity is a string of the form: | ||
|
|
||
| ```text | ||
| <provider>:<owner>/<repo>[@<ref>] | ||
| ``` | ||
|
|
||
| | Component | Meaning | | ||
| | ---------- | -------------------------------------------------------------------------------------- | | ||
| | `provider` | The identity provider. This CEP defines `github` and `gitlab`. Others MAY be added. | | ||
| | `owner` | The owner / organization on that provider. MUST NOT be empty. | | ||
| | `repo` | The repository on that provider. MUST NOT be empty. | | ||
| | `ref` | Optional ref constraint (e.g. `refs/tags/v1.0`). Reserved; see **Future Work** below. | |
There was a problem hiding this comment.
What about using some subset of PURLs here?
| A publisher identity is a string of the form: | ||
|
|
||
| ```text | ||
| <provider>:<owner>/<repo>[@<ref>] |
There was a problem hiding this comment.
I think this is too restrictive. For example, on PyPI, packages uploaded with attestations signed by Google Cloud have subjects that are emails, and not owner/repo:
Subject Alternative Name (critical):
email:
- 919436158236-compute@developer.gserviceaccount.com
There was a problem hiding this comment.
Do you think something like provider:<identifier> would work where the tool, or the CEP, should define a list of supported provider & identifier pairs? Or should we turn this into a true dictionary supporting all OID fields and match on those? Do you know of any prior art for this?
There was a problem hiding this comment.
I wonder if we should support this shorthand form to begin with. It adds complexity by having multiple ways of representing the same identity, and by having different rules on how to parse the shorthand versions (i.e gihub's <owner>/<repo>[@<ref>] vs whatever we come up with the Google Cloud identity).
If we decide to go with it, we should make the matching depend on the issuer. For example, the paragraph that says:
An
identityvalue that is a URL (starts withhttps://) is matched
against URI SANs using repository-boundary prefix matching
we shouldn't do this in general, since there's no guarantee that a subject that contains a URL is referring to a repository. Rather, we can specify it for known issuers where we know it to be the case (github, gitlab), but otherwise we should do exact matching.
There was a problem hiding this comment.
(the above also applies to the explicit mapping form)
| | `github` | `https://github.com/<owner>/<repo>` | `https://token.actions.githubusercontent.com` | | ||
| | `gitlab` | `https://gitlab.com/<owner>/<repo>` | `https://gitlab.com` | |
There was a problem hiding this comment.
With the upcoming PyPI support for self-hosted GitLab and GitHub instances, there will be attestations that are technically from github and gitlab, but will have different OIDC issuers. Something to keep in mind here, with regards to naming the providers
| The bundle URL is determined as follows, in order: | ||
|
|
||
| 1. If `bundle_url` is set in the recipe, the builder MUST use that URL. | ||
| 2. Otherwise, if the source URL host is `pypi.io` or |
There was a problem hiding this comment.
why .io instead of .org?
| 3. Otherwise, the builder MUST fail with an error reporting that no | ||
| `bundle_url` is set and one cannot be auto-derived. |
There was a problem hiding this comment.
Otherwise, the builders MUST fail
this is in contradiction with the statement below:
Builders MAY recognize additional auto-derived hosts
If builders may recognize additional auto-derived hosts, they will not fail for those hosts, even if the bundle_url is not set in the recipe (1) and the source URL host is not pypi (2).
There was a problem hiding this comment.
maybe it makes sense to say "builders SHOULD fail" instead?
| ### Predicate Semantics Are Out of Scope | ||
|
|
||
| This CEP does not define, restrict, or interpret the predicate types | ||
| that appear in the in-toto statement. In particular: |
There was a problem hiding this comment.
why not lock the predicate type too? The builders don't need to "interpret it", but they could check if it matches the type specified in the lockfile.
My thinking here is that in this CEP (as it's currently written), the verification process checks that a given artifact has a valid signature from an identity specified in the lockfile. But since these signatures have semantics attached (specified by their predicate type), accepting any signature from that identity as valid might be too much.
So, locking the predicate type, we can ensure during veriication that the semantics of the signature have not changed since they were locked, without actually interpreting them.
| source: | ||
| url: https://files.pythonhosted.org/packages/ab/cd/flask-3.1.1.tar.gz | ||
| sha256: "6489f1..." | ||
| attestation: |
There was a problem hiding this comment.
currently, this CEP only allows for one attestation url/sounce per source. One thing to consider is if in the future we might want to have multiple attestations sources (such as PyPI and GitHub) per source
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
- Rename cep-xxxx-source-attestations.md to cep-XXXX.md to satisfy the
cep-filenames pre-commit hook
- Add an explicit {identity, issuer} mapping form for publishers, so
non-repository SANs (e.g. Google Cloud email identities) and
self-hosted GitHub/GitLab instances can be expressed
- Add optional predicate_type to pin the in-toto predicate type
- Allow bundle_url to be a list to support multiple attestation sources
- Add pypi.org to the auto-derivation hosts and explain the pypi.io alias
- Close the auto-derivation list to resolve the MUST-fail vs
MAY-recognize contradiction
- Add a note on why (identity, issuer) pairs are used instead of PURLs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Require sha256 when attestation is present; note schema is additive - Define which URL drives auto-derivation for mirror lists - Specify project/version parsing per PEP 625 / wheel filename format - Builders MUST reject the reserved @ref suffix instead of ignoring it - Allow repo paths with slashes (GitLab subgroups) in shorthands - State case-sensitivity rules for identity and issuer matching - Rework verification into explicit filter steps: subject mismatches in pooled responses are excluded, not fatal; empty set fails the build - Reference the Sigstore Client Specification for bundle verification - Add a Security Considerations section (threat model, unsigned recipe caveat, bundle transport, network dependence) and an offline verification / bundle vendoring item to Future Work Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Verified attestation bundles are stored under info/recipe/attestations/ next to the rendered recipe, with a `verified` index (path, sha256, predicate_type, san, issuer) in the rendered recipe's attestation mapping. The built package thus keeps a machine-checkable link back to its upstream source publisher and can be re-verified offline; combined with a CEP 27 publish attestation this forms a chain from package to source producer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adding a CEP to validate the source section against know sigstore providers.
Checklist for submitter
cep-0000.mdnamedcep-XXXX.mdin the root level.CEP XX: Amend XYZ.## Changelogsection right above the final "Copyright" section with an item that uses syntaxYYYY-MM-DD: Brief explanation of changes.Checklist for CEP approvals
${greatest-number-in-main} + 1.cep-XXXX.mdfile has been renamed accordingly.# CEP XXXX -header has been edited accordingly.pre-commitchecks are passing.