Skip to content

fix(marketplace): artifact names are not checked across PackageSources, and reserved names are checked only by the CLI #4977

Open

Description

@myasnikovdaniil

Summary

Name checks on the server cover only exact PackageSource name, so two sources can end up on one artifact name and one of them gets built from the other's content.

  1. Server checks exact PackageSource name only. collision.PackageSourceName (collision.go L87-L102) fails when PackageSource with same name exists and is not the tap's own. It is called from cozypkg tap and from materializer (tapmaterializer_reconciler.go L144), nothing else is compared.
  2. Reserved names exist only in cozypkg validate. reservedNamePrefixes is {"cozystack.", "community."} (validate.go L123-L129), applied offline and skippable with --allow-reserved-names. Comment there says on-cluster check is the real boundary, but tap-labelled OCIRepository reaches materializer without CLI, and neither materializer nor Tap REST handler has reserved-name check.
  3. Artifact name drops difference between . and -. naming.ArtifactName replaces dots with dashes in all three segments (naming.go), so platform source cozystack.cert-manager and tapped source cozystack-cert-manager with same variant and component give same ExternalArtifact name cozystack-cert-manager-<variant>-<component>. Checks 1 and 2 let it through, PackageSource names differ and dashed form is not reserved prefix. More generally mapping is not injective: acme.web / default / x, acme-web / default / x and acme / web-default / x all give acme-web-default-x. Only artifact-name collision check is inside one PackageSource (validate.go L320-L363).

Impact

I expect source-watcher applies second source over the first without owner check, but I did not read that code or run it, so first step of the fix is to confirm it on a dev stand. Everything above is read in code, nothing reproduced on a cluster.

Suggested fix

  • Reject PackageSource whose normalised artifact names equal another PackageSource's. Injective encoding (hash suffix, or separator that can't appear in names) would remove whole class, but it changes artifact names that ApplicationDefinitions already reference. Do the check where exact-name check already runs (materializer and Tap create), so it holds for labelled OCIRepository that never went through CLI.
  • Enforce reserved names on server in same places and cover dashed form (cozystack-). Decide in same change whether community. stays reserved, prefix was dropped from tap flow in #3940 but CLI still lists it.
  • Extend artifact-name accounting in validate.go beyond one source, at least against platform's own PackageSources.
  • Remove duplicate of name construction in package_reconciler.go L280-L283 and call naming.ArtifactName, the package's own comment says definition must live in one place.
  • Operator already refuses to apply platform PackageSource over tapped one (main.go L801-L812), artifact-name check is the other half of that guard.

Acceptance

  • Tapped source named cozystack-cert-manager is refused while platform ships cozystack.cert-manager with matching variant and component.
  • Labelled OCIRepository created without CLI is refused for same reason.
  • Unit tests in collision and naming for clashing and non-clashing case.

Activity

  1. added
    kind/bugCategorizes issue or PR as related to a bug
    securitySecurity-related issues and features
    priority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next release
    area/platformIssues or PRs related to platform infrastructure (bundle, flux, talos, installer)
    on Oct 20, 2026
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

    area/platformIssues or PRs related to platform infrastructure (bundle, flux, talos, installer)kind/bugCategorizes issue or PR as related to a bugpriority/important-soonMust be staffed and worked on either currently, or very soon, ideally in time for the next releasesecuritySecurity-related issues and featurestriage/acceptedIndicates an issue is ready to be actively worked on

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions