Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow registry configuration for disabling checksum validation #13858

Open
stefanvanburen opened this issue May 3, 2024 · 5 comments
Open

Allow registry configuration for disabling checksum validation #13858

stefanvanburen opened this issue May 3, 2024 · 5 comments
Labels
A-registries Area: registries C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.

Comments

@stefanvanburen
Copy link

stefanvanburen commented May 3, 2024

Problem

I'm working on a crate registry where I'm able to advertise a set of crate versions that may be generated, but the crates themselves are only lazily generated when they're requested — so I don't have a checksum to publish initially. After the generation occurs, I can publish the checksum, and it is not expected to change.

Currently, cargo will not function if the checksum is not populated — it'll attempt to compare the empty string to the checksum of the downloaded crate, which will fail and stop the installation of the crate. I'd like to not need to pre-generate all possible versions just to populate the version checksums in the index.

Proposed Solution

I'd like the ability to specify, at a registry level, to disable checksum validation altogether. I'd imagine this looking is something like:

# in .cargo/config.toml
[registries]
my-registry = { verify-checksums = "no" }

Where the default value for verify-checksums is "yes".

Alternative solution

An alternative would be the ability to specify only validating a downloaded crate's checksum when a value is set in the registry (somewhat similar to how the Go Module Proxy works, where the initial module download populates the checksum value). I'd imagine this looking is something like:

# in .cargo/config.toml
[registries]
my-registry = { verify-checksums = "if-non-empty" }

Notes

I'm aware that this can introduce security risks (you should only enable this if you trust the registry that you're using), but I've been able to implement a similar lazy generation scheme across a variety of package ecosystems — cargo is the only one (so far) that has strictly required package version checksums in this way.

The alternative proposal is more secure in the sense that the checksum can at least be compared to a stable value once it's known, but still requires trust in the registry.

I wasn't able to find a prior request quite like this, but somewhat related is #10071. It also may allow for solutions to issues like #10939, where a local registry is required to serve a non-existent checksum.

@stefanvanburen stefanvanburen added C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-triage Status: This issue is waiting on initial triage. labels May 3, 2024
@epage epage added the A-registries Area: registries label May 3, 2024
@weihanglo
Copy link
Member

I'm working on a crate registry where I'm able to advertise a set of crate versions that may be generated, but the crates themselves are only lazily generated when they're requested.

Not really related to the issue itself, but I'd like to know more about use cases and rationale behind this lazy generated package registry, if you'd like to share :)

@weihanglo
Copy link
Member

I've been able to implement a similar lazy generation scheme across a variety of package ecosystems — cargo is the only one (so far) that has strictly required package version checksums in this way.

Could you give some references about how other ecosystems handle this?

@weihanglo weihanglo added S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request. and removed S-triage Status: This issue is waiting on initial triage. labels May 7, 2024
@stefanvanburen
Copy link
Author

stefanvanburen commented May 7, 2024

Hey @weihanglo, happy to give more context. I'm working on Generated SDKs at Buf, where we allow users to easily depend on the output of their protobuf files when generated with various language plugins. (You can see that we already support Go, NPM, Maven, Swift and Python.)

The way this works is that we construct a synthetic version that combines information about the version of the files with the version of the plugin, so we have the cross product of (module versions) * (plugin versions) available for download. As you can imagine, as the number of versions of the protobuf files and the number of plugin versions increases, the number of available versions becomes quite large 😅.

The way that we typically deal with this is to only lazily generate the package when it's requested, and then store it for future downloads. This means that we don't have the checksum on hand before the package itself is requested the first time.

Here's a survey of how this works across the ecosystems we support:

Overall, we're looking to find a way to relax the requirement on checksums being populated in the index; we'd prefer to not need to generate crates that no package registry client has actually requested, just so we can populate their checksum in our index.

Let me know if I can provide any more detail on the above, and happy to provide implementation support for this (although my Rust skills are ... rusty 😄).

@stefanvanburen
Copy link
Author

hey @weihanglo, any other details I can provide or anything I can help with? Wanted to make sure this didn't slip off your radar 😃, appreciate you taking a look.

@Eh2406
Copy link
Contributor

Eh2406 commented May 14, 2024

The actual PR Diff is likely to be small. Simply changing a == requirement to a is_none() || ==. Most of the change will be the additional tests. As with most security-related requests the hard part is going to be determining and documenting all of the implications. (Not having consulted the rest of the team) this probably requires an RFC. Mostly to ensure that all the details and there implications are documented and reviewed by the correct people.

Some important questions off the top of my head:

  • What happens if a registry adds or removes the configuration field?
  • What happens if source replacement is involved? (Possibly at the same time as we observe the field changing.)
  • How does this interact with registry signing? (A long desired, but not yet designed, feature.)
  • What happens if registry removes the hash for an existing crate?
  • What happens if a registry changes the contents of a crate without having a hash?

What are the implications of each of those decisions on the security of rust users? Keeping in mind both that a trusted registry might have been compromised or may have a MITM attack, but on the other hand that a registry is fundamentally a RCE-as-a-service. I'm not seeing anything that would be a dealbreaker, just a lot of things that need to be figured out and documented so that we are not surprised by them later on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-registries Area: registries C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.
Projects
None yet
Development

No branches or pull requests

4 participants