Skip to content

Trusted publishing: record the workflow run, not only the ref, in the version provenance #2116

Closed

Description

@netomi

Follow-up to #2114, which started recording the OIDC identity behind a trusted-published version.

Where this stands

extension_version.published_provenance now holds the claims the provider asserted at the token exchange, copied there at publish time so they outlive the token (deleted as it is used) and the registration (revocable). For GitHub that is:

{"sub": "repo:octo-org/octo-repo:ref:refs/tags/v1.2.0",
 "repository": "octo-org/octo-repo", "repository_id": "74",
 "repository_owner": "octo-org", "repository_owner_id": "65",
 "workflow_ref": "octo-org/octo-repo/.github/workflows/publish.yml@refs/tags/v1.2.0",
 "runner_environment": "github-hosted"}

That answers "which repository and which workflow file, on which ref". It does not answer "which run".

What is missing

Only the claims needed for matching are extracted, and provenance wants more than matching does:

GitHub (GitHubTrustedPublishingProviderSupport.extractClaims)

  • run_id — the individual workflow run. Without it the trail stops at the ref, and a ref can be built many times.
  • sha — the commit the run was for.
  • job_workflow_ref — the workflow actually executing, which differs from workflow_ref when a reusable workflow is called. workflow_ref is the entry point; for "what really ran" you want both.

GitLab (GitLabTrustedPublishingProvider.extractClaims)

  • pipeline_id and job_id — the equivalents of run_id.
  • sha.

Suggested shape

Add them with mayClaim rather than mustClaim. They are recorded, never matched against, so a provider that omits one cannot break an exchange that works today — matches() compares a fixed set of keys and is unaffected by extra entries in the map. No schema change: published_provenance is jsonb.

Worth checking each claim against the provider's current documentation before adding it, since providers have changed claim sets with little warning, and confirming that none of them carries anything that should not be stored indefinitely.

Deliberately not in scope

Surfacing the provenance through the API or the UI. There is no plan for that yet, and it needs its own decision about who should see it — a repository id and workflow ref are public information for a public repository, but publishing them as part of the extension API is a product choice, not a mechanical one. The data being captured and queryable in the database is what the forensic question ("a token leaked — what did it publish, and from where?") actually needs, and that works today.

Activity

  1. added
    enhancementRequest for new or improved functionality
    priority:mediumImportant work, but not time-sensitive
    on Sep 30, 2026
  2. netomi commented on Sep 30, 2026

    @netomi
    ContributorAuthor

    @cstamas can you also take a look here and see if we can include that information?

  3. added a commit that references this issue on Oct 5, 2026
    3f97c42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementRequest for new or improved functionalitypriority:mediumImportant work, but not time-sensitive

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions