[ultra-pre-RFC] Client Certificates for Cargo instead of shared tokens

The current implementation of alternative registries might be useless to you, but there are use cases where they work great: for example they can be used by companies to store their private crates, and there are already commercial products offering them to their customers. Also, even if a feature is "useless" our stability guarantee still apply and we can't break it.

8 Likes

I don't think this claim holds water. I can think of several historical incidents involving compromise of an SSH private key, and none of them would have been mitigated by key expiry, because the attacker used the compromised key immediately after obtaining it. We also have 20+ years of collective experience with TLS, and 40+ years of collective experience with passwords, demonstrating that forced rotation of credentials causes more problems than it solves. Consider the recent incident where Mozilla's signing key expired and everyone's Firefox addons got disabled, for instance.

I would understand your position better if you were talking about revocation, but for this application, you don't need a revocation mechanism built in to the keypair format. Keys can be revoked via the management interface that must exist anyway.

(In this thread you are consistently being dogmatic and inflexible about your design principles and I think that's harming your ability to argue for what you want.)

9 Likes

since certs are managed by the client and only checked by the server, the client can just have 1000-year certs. thankfully cargo won’t disable your ability to build and download packages, and only publishing would be affected.

this is fine because the process would be so streamlined that it’s basically run cargo -> if it errors click the link -> run it again. and on build servers… I mean, you shouldn’t have signing on build servers either, altho ppl do it anyway. but in that case just use 1000-year certs and you’re done!

these aren’t logins. think about being able to have multiple passwords for the same account, each with a different expiration time that you get to pick and choose however you like.

client certs are about user choice. or rather, should be. in practice everything we’ve done with them so far has been a huge mistake because we forced the CA system on them and refused to allow huge expiration. i.e. the server has power over the user. ):

For all intents and purposes, something that lasts 1000 years does not expire. If there's are security reasons for doing so, services should put some sensible upper bound on the expiry.

That being said, time-based invalidation is more of a nuisance than anything else in my experience - I'd much rather be able to invalidate something if I know there's a chance its been compromised, but for it to work indefinitely as long as I think it's valid.

1 Like

expiration is useful in death and hiatus

it’s not useful for properly stored passwords and leaks

as such expiration is useful for if someone attempts to crack your keys instead of you leaking them.

this should be up to the user and the user should choose their own tradeoffs, and all tradeoffs should be available (except key vs token because they have pretty much the exact same workflow but one of them is a few hundred times more secure. read-only DB leak won’t allow you to publish with public key but does with tokens)

Well, except for the custom expiration which is not yet implemented on crates.io you're also describing how tokens work. Custom expiration shouldn't be hard to implement on the codebase, an expires_at nullable database column checked during authentication is probably enough.

I quickly looked at the code and it seems that the tokens are indeed stored in plaintext at the moment (happy to be proven wrong!), and a DB leak would expose all of them. This could be solved by hashing the tokens before storing them.


You raised some good points security wise and we should definitely improve on that front. I think it's best for everyone if we all focus on improving the current implementation rather than throwing it away though. The crates.io team is small and has limited resources, and it's way less difficult to fix the current code than both changing the entire ecosystem in a backward incompatible way and migrate the whole website to a new infrastructure (since Heroku doesn't support client certificates as Justin said earlier).

can’t you ask them to add support?

Ask whom? If you mean asking Heroku for client certificates support I highly doubt they’re going to do that since it means rearchitecting how their routing works.

it just means they need an “Heroku-Client-Certificates” HTTP header.

(“certificates”, plural, because I’m envisioning a future where you can use certs for OAuth, so you’d have a “client cert” and an “access cert”)

The inability to pass TLS auth peer info through proxies is a classical problem and one of the reasons why tokens remain popular for authentication, particular for Internet-facing use cases. This is one of the many reasons why while TLS client certificates are popular for internal service-to-service authentication, tokens dominate federated / client-server use cases.

Note that there are proposals to allow TLS terminating proxies such as the Heroku frontend to pass through token binding information to solve this very problem (although it's just a draft, and an expired one at this point).

I mean, I guess there’s also this stuff:

http://lists.w3.org/Archives/Public/ietf-http-wg/2019JanMar/0164.html

https://cybre.tech/SoniEx2/paste/src/branch/mhttp/mhttp.md

Alternatively, protect the content and not the transport: sign the crate files before upload.

The signature can be verified by application level code on the server side, even on heroku. At this point you no longer care about the transport security and you could even upload over unauthenticated FTP (except that nobody has FTP clients anymore).

3 Likes

add signing keys to crates.io and let it figure things out based on that?

This is a good idea in principle, but has been troublesome for other languages' package repositories. I'd encourage anyone considering this to read Donald Stufft's essay on why signing packages doesn't solve as many problems as you might think it does.

2 Likes

consider signatures as a replacement for access tokens

The use cases are orthogonal and complementary:

  • Tokens authenticate API access
  • Signatures provide end-to-end verifiable data-at-rest authentication of a static artifact

I would love to see a feature allowing crate owners to sign releases in a way that’s end-to-end verifiable and have done some design work on what that might look like on crates.io, however as a matter of pure practicality I think crate signing needs to be opt-in and a separate authentication method is necessary for users who are not managing a signature key for crates.

1 Like

I think you should be able to push signed crates without a token.

pulling them probably needs a token tho, unless you can figure out a way to do that with the same system.

just add signing (public) keys to your profile as if they’re tokens.

Token vs Certificate doesn’t make a difference for my threat model, if both end up in a file, at well-known location, in my home directory.

If someone can steal files from my home dir, I’m screwed. If they can’t, both work fine.

So to me a bigger improvement would be 2FA such as TOTP or U2F (so the attacker can’t use the stolen token or cert), or storage in the system Keychain (so that a vulnerability allowing stealing of files is not enough to obtain the token or cert).

1 Like

if you can sign stuff you can just use yubikeys. same mechanism, different crypto processor.

it’s flexible enough to be safe for everyone. you can pick your exact threat model and not have one forced on you.