1. 25

  2. 6

    I guess they should have made it work something like serde = { version = "1.0", features = ['derive'], rename_to = "serde1" } rather than serde1 = { version = "1.0", features = ['derive'], package = "serde" } to make the backwards compatibility safer.

    This is a great vulnerability. Version transitions are always hard to reason about.

    1. 3

      Unfortunately that would make invalid toml:

      Defining a key multiple times is invalid.

      1. 3

        Ah, I see—I didn’t realize there was a valid case for having the same package name multiple times. From one of the links, some use-cases:

        • Depend on multiple versions of a crate
        • Depend on crates with the same name from different registries

        Edit: Two other thoughts:

        • JVM build tools generally seem to avoid this problem by expressing dependencies as lists
        • It really bothers me that dependencies aren’t namespaced by registry. (This is a problem in JVM land too.) If I add a registry or repository to my project files, I generally only want to take certain, specific packages from it.
        1. 1

          But you cannot have multiple direct dependencies on a single crate anyway, so would this be a problem? (Multiple indirect/one direct and 1+ indirect is valid though.)

          1. 1

            I’m not sure what you mean by “direct” and “indirect”, but to expand @saturn’s example, this syntax allows you to depend on:

            serde = { version = "1.0", package = "serde" }
            serde09 = { version = "0.9", package = "serde" }

            but with their alternative proposed syntax you’d write that as:

            serde = { version = "1.0", rename_to = "serde" }
            serde = { version = "0.9", rename_to = "serde09" }

            but that wouldn’t be valid toml because you’d be reusing the top-level key serde.

            1. 1

              Oh, interesting, I always thought that the first example does not work. But it only does not work with the same version (e.g. for different feature sets), which fails with

              error: the crate `blah v0.1.0 (/foo/bar/blah)` depends on crate `serde v1.0.101` multiple times with different names
      2. 2

        I’ve noticed this a coupe of weeks ago, but mentally filed it under “crates-io already has a squatting problem” and didn’t think of reporting it.

        1. 2

          I wonder what would be a good anti-squatting approach. Keep track of requests for packages that aren’t there (hmm, caches would interfere) and then alert if someone creates one with that name? And then what, edit distance stuff?

          1. 5

            I mean github doesn’t have a problem because packages are user/package . It seems that would have been better than what crates.io does imo.

            1. 6

              Original rationale for not using namespacing:


              1. 1

                Interesting to read, don’t agree with it, but thank you for linking.

                1. 2

                  The discussion comes up every now and then to the point where everyone gets annoyed. That’s obviously a bit unfair to people that don’t have the history.

                  Not that I don’t see the point (and it’s fine to raise it), but mostly because the discussion does not move forward and every argument was there already.

                  I do, btw. not agree that the GH model solves many things, there’s an additional bit of info you need: whether a repos is a fork or an orginal, etc. It also has problems, as it uses that namespace as the only way to differentiate, GitLab, with it’s habit of using teams and tags, is much better in that regard, IMHO.

                  1. 1

                    I specifically meant to stop name squatting and impersonation in the parent comment, there are tradeoffs sure.

            2. 1

              In this particular case crates-io could have blocked/reserved renamed crate names. Someone has grabbed getrandom_package already (the juiciest target — name used in the top rand crate). Unfortunately, crates-io doesn’t want to get involved in crate ownership disputes/squatting/spam (I get why — it’s a slippery slope & huge resource drain on “customer support”, but I’d prefer them to at least show some teeth in the most obvious cases).

              For squatting in general there’s no good solution. Some people called for GitHub-like namespacing, but that a) moves the goalpost from grabbing good crate names to grabbing good usernames, b) popular crates are by users with bizarre usernames you wouldn’t remember, c) is a huge question mark what to do with existing 30000 crates, without ending up with some 2-tiered/legacy system.

              The closest one that I could think of was allowing people to reserve name prefixes, such as tokio-*. That is backwards compatible with existing Cargo and Rust syntax.

              1. 2

                You can grab a good username, but you can’t steal a name from an existing account.

                On crates.io I can just take hyper2, on github I can’t take hyperium/hyper2 . To me that is a pretty big difference.

                1. 1

                  Spitball idea that no one wants: Add a “checksum” to package names. You might typo “foobar” as “foobaz”, but you won’t typo “foobar-2js” as “foobaz-z1h”. :-P

                  1. 2

                    We should just name every package a GUID, that way no one will confuse them!

                    1. 2

                      The 2 is not a typo, it is a successor version. Similar to how sqlite is actually sqlite3. I’m not sure how your checksum idea would help at all.

                      1. 1

                        Ah, yeah, wouldn’t help with successor versions, that’s a good point.

              2. 1

                An implementation of a tiered namespace wouldn’t be too hard to implement. You just use double-underscore in the crate name as a name separator, which could be translated to / as sugar in Cargo if you want. Crate names remain valid Rust identifiers and Everything Just Works. There’s no real legacy problem ‘cause there’s a grand total of one crate that has __ in its name, and existing crates just live in their own top-level namespace separate from user namespaces. A proof of concept wouldn’t even be hard, ’cause you just reject crates from user foo that titled foo__cratename.