Skip to content

[RFC] Proper Repository Identities #99

Open

Description

@cyphar

At the moment we only identify repositories by their user-facing names, which will become problematic once we want to start dealing with composability (repository links #73) and providing information about repositories to other parties (such as for systemd-report purposes) because repository names are fundamentally a local-only concept with no real way of validating them.

For links it would be much better to only instantiate one client and only do a single refresh per repository, as well as potentially making it easier to handle problems like auth, and for systemd-report consumers it will be incredibly useful to be able to categorise repositories using globally unique identifiers.


The only really obvious choice is to use a cryptographic hash of 1.root.json, because:

  1. It is transport-agnostic.
  2. Conceptually it defines the initial repository identity. (We already implicitly treat the signing key set as an identity in Quarry, especially on the publishing side.)
  3. It doesn't require any extensions to TUF.
  4. It is not something a malicious repository can manipulate directly without a pre-image attack (other ideas like generating a UUID and putting it in the 1.root.json suffer from malicious repositories being able to publish the same identifier).

Once we do the <meta> stuff for self-describing repositories we will likely want to be able to include the identity hash in the <meta> tag.

However, there are some issues with this proposal:

  1. We need to now store 1.root.json on the client (and transmit it in cases like cross-repo links) so that it can independently derive the identifier. But that is not enough -- a malicious repository could provide an N.root.json that is not actually signed with a valid chain from 1.root.json to impersonate a repository. So we also need to emulate root.json upgrades up to the current N.root.json on first fetch when figuring out the repository identity to make sure that the signature chain is really valid. For root_trust = { type = "bundled", ... } we probably should change the structure so that we keep all historical root.jsons to avoid post-key-compromise attacks.
  2. The ideas for using prefix-based matching for AuthN/AuthZ providers (as mentioned in tufclient: authenticate repo requests as this machine #82 (comment)) is kind of dead in the water. I guess we would need to instead restrict it based on which domains we are contacting...?
  3. We probably should hash the canonicalised JSON rather than just using the original bytes so that we don't end up with fragile setups.
  4. There is now an incentive for an attacker to compromise the initial 1.root.json keys even after rotation, since a fully broken 1.root.json might allow you to impersonate that repository... Maybe this is a serious enough issue to warrant a different design?

Activity

  1. pothos commented on Nov 9, 2026

    @pothos
    Member

    Requiring that different repos use different root keys means disallowing as policy instead of convention. Isn't this too strict and could lead to subtle issues?
    I wonder if a UUID would help or if a fixed free form name that's not mentioning the domain would be good enough?

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions