Skip to content

CEP XXXX: add recipe source attestation validation#168

Open
wolfv wants to merge 3 commits into
conda:mainfrom
wolfv:recipe-source-attestations
Open

CEP XXXX: add recipe source attestation validation#168
wolfv wants to merge 3 commits into
conda:mainfrom
wolfv:recipe-source-attestations

Conversation

@wolfv
Copy link
Copy Markdown
Contributor

@wolfv wolfv commented May 20, 2026

Adding a CEP to validate the source section against know sigstore providers.

Checklist for submitter

  • I am submitting a new CEP: Put your title here.
    • I am using the CEP template by creating a copy cep-0000.md named cep-XXXX.md in the root level.
  • I am submitting modifications to CEP XX.
    • The PR title reflects the CEP I'm modifying: CEP XX: Amend XYZ.
    • I updated the "Updated" date.
    • I added the link of this PR to the Discussions row.
    • I added or extended the ## Changelog section right above the final "Copyright" section with an item that uses syntax YYYY-MM-DD: Brief explanation of changes.
  • Something else: (add your description here).

Checklist for CEP approvals

  • The vote period has ended and the vote has passed the necessary quorum and approval thresholds.
  • A new CEP number has been minted. Usually, this is ${greatest-number-in-main} + 1.
  • The cep-XXXX.md file has been renamed accordingly.
  • The # CEP XXXX - header has been edited accordingly.
  • The CEP status in the table has been changed to approved.
  • The last modification date in the table has been updated accordingly.
  • The table in the README has been updated with the new CEP entry.
  • The pre-commit checks are passing.

Comment thread cep-xxxx-source-attestations.md Outdated
Comment thread cep-xxxx-source-attestations.md Outdated
Comment on lines +90 to +103
### 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. |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What about using some subset of PURLs here?

A publisher identity is a string of the form:

```text
<provider>:<owner>/<repo>[@<ref>]
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 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

src

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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?

Comment on lines +111 to +112
| `github` | `https://github.com/<owner>/<repo>` | `https://token.actions.githubusercontent.com` |
| `gitlab` | `https://gitlab.com/<owner>/<repo>` | `https://gitlab.com` |
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.

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

why .io instead of .org?

Comment on lines +133 to +134
3. Otherwise, the builder MUST fail with an error reporting that no
`bundle_url` is set and one cannot be auto-derived.
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.

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

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.

maybe it makes sense to say "builders SHOULD fail" instead?

Comment on lines +199 to +202
### 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:
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.

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

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

wolfv and others added 2 commits May 28, 2026 08:30
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
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