Skip to content

Plugins have no catalog-declared provenance (parity gap with skills) #6643

Description

@samuv

Problem

Skills can carry provenance constraints on their registry entry (regtypes.Skill.Provenance, RFC THV-0080 follow-up #6310, verifier support in #6420). On true first use of a skill resolved from a catalog, skillsvc.verifyOCIInstall enforces the catalog-declared signer_identity / cert_issuer / repository_uri / repository_ref / runner_environment via verifier.NewCatalogExpectation, and refuses to install under a --public-key when the catalog declares a certificate identity.

Plugins have none of this. toolhive-core/registry/types/plugins_types.go has no Provenance field, plugins.InstallOptions has no CatalogProvenance, and pluginsvc.verifyOCIInstall presents only a lock expectation (NewLockExpectation(expected), nil on TOFU). The resolveKeyAnchor comment in pkg/plugins/pluginsvc/verify.go records this as the one deliberate divergence from skills.

With #6442 closed, this is the last trust-model asymmetry between the two surfaces. It matters more for plugins than for skills: a plugin contributes hooks and MCP servers to the client that loads it, so a first install that trusts whatever identity it observes is the larger blast radius.

Proposed scope

  1. toolhive-core: add Provenance *Provenance to the plugin registry entry type, reusing the existing certificate-shaped regtypes.Provenance (needs a core release and a go.mod bump here).
  2. plugins.InstallOptions.CatalogProvenance (internal, json:"-"), hydrated by the registry-resolving install path.
  3. pluginsvc.verifyOCIInstall / verifyGitInstall: on true first use (no lock entry), build the expectation with verifier.NewCatalogExpectation(normalizeCatalogProvenance(...)), reject unsupported constraints (sigstore_url, attestation) with 422 as validateCatalogProvenance does, and classify failures via a classifyCatalogVerifyError mirror.
  4. resolveKeyAnchor gains the catalog arm: a supplied --public-key against a catalog entry that declares a certificate identity is a 403, exactly as on skills.
  5. Lock precedence is unchanged: any existing lock entry, including a legacy one with no trust state, wins over the catalog.
  6. Tests mirroring skillsvc's catalog tests; arch doc update in 14-plugins-system.md#trust-model.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestneeds-triageIssue needs initial triage by a maintainersecurityskillsSkills lifecycle management

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions