Clojars: Verified Group Names

In light of the recent announcement of a method to inject libraries into internal builds by shadowing internal names (aka ‘Dependency Confusion’), we have decided to take steps to make Clojars more secure. Clojars will soon require that all new libraries have a verified group name, and that group name needs to be reverse-domain-based. This will help protect against Clojars being used in [shadowing and typo-squatting attacks]
Verified Group Names (Clojars Wiki)

I wanted to make sure everyone here had seen this important announcement about a key part of our Clojure ecosystem. First off, for existing libraries in existing groups on clojars.org, there is no change needed at all. If you have already published a library to Clojars, you will be able to continue releasing new versions of that library, using the same group. Nothing needs to change.

The TL;DR of all this is that after April, 18th (2021) you will not be able to publish any new libraries into existing groups that have not been verified and you will not be able to create new groups that cannot be verified – that are not reverse domain names.

Clojars has always allowed users to publish libraries into org.clojars.<username> (and net.clojars.<username> as I recently found out). The former is assumed to be for non-canonical forks of other libraries and for “sandbox” versions of libraries (test releases, etc) and the latter is assumed to be for full public releases of libraries for users who don’t have (or don’t want) a more elaborate reverse domain name group.

As part of the upcoming changes, Clojars will auto verify com.github.<username> and io.github.<username> groups based on authenticating via GitHub when you login on Clojars, and will soon add verification of com.gitlab.<username> and io.gitlab.<username> groups based on authenticating via GitLab. I would expect many of us who have been publishing libraries under a generic username will switch to one of these, depending on where we host our projects.

In addition, anyone who is responsible for a domain name can apply to get a group name verified that is the reverse of that domain (the process is documented in the wiki page linked above but typically you open an issue at Clojars, on the administration repo, and they’ll have you add TXT record to your DNS or something similar).

As part of supporting this effort, I have made some changes to both depstar and clj-new to encourage folks creating new projects to adopt group names that match the Verified Group Names policy:

  • If you use the :group-id option with depstar to update the <groupId> field in your pom.xml and it doesn’t look like a reverse domain name, you’ll get a warning (but it will go ahead and do it anyway).
  • When you create a new project with clj-new, it will do its best to set the <groupId> field in the generated pom.xml file to an appropriate group name.

clj-new has always tried to encourage you to create projects with a qualified name, such as myname/myproj – where myname is, say, your GitHub username or your Clojars username – and now it will create a <groupId>, by default, that is net.clojars.myname. For casual usage, that will suffice: users can publish libraries easily under their Clojars username. If you create a project with a qualified name like com.github.myusername/myproj, it will treat it as if you used myusername/myproj but create a <groupId> of com.github.myusername (and assume you are using GitHub for hosting, as it has done in the past). It will recognize io.github.myusername as being equivalent (but use a <groupId> of io.github.myusername). Similarly for folks on GitLab, with a qualified name of com.gitlab.myusername/myproj or io.gitlab.myusername/myproj. clj-new also tries to do the right thing with qualified names like com.acme/myproj (but you’ll likely need to adjust the :scm-user property via the :env option).

Today I released clj-new 1.1.264 under both the com.github.seancorfield group and the seancorfield group. I released depstar 2.0.193 under both the com.github.seancorfield group and the seancorfield group yesterday. I intend to double-publish all of my libraries for a while under both the existing group – which will not be verified – and under this new group which will be auto-verified, and will switch all my libraries to com.github.seancorfield in due course.

No one else needs to follow my lead, of course, but I hope that the Clojure community will take this attempt to improve security seriously and will give some conscious thought to their choice of group IDs in future.

12 Likes

will switch all my libraries to com.github.seancorfield

Just out of curiosity. As you own corfield.org, wouldn’t it make more sense to use org.corfield. This way you’re independent of github and if github shuts down in 10 years or you want to change hoster the namespace stays the same.

1 Like

Toby Crawley, one of the Clojars maintainers, asked me the same question. There are two reasons:

  1. If GitHub shuts down, I’ll have to host the source of the library somewhere else so the :git/url that folks use would have to change, and I like that the qualified library name and Git coordinates are similar: com.github.seancorfield/mylibrary {:git/url "https://github.com/seancorfield/mylibrary" :sha "..."} – this tells people where to find the library (based on the qualified library name) and in the other direction how to refer to the library (based on where it is hosted).
  2. I also see more similarity between the seancorfield/mylibrary, that things have been published under previously, and com.github.seancorfield/mylibrary than I do with org.corfield/mylibrary – and seancorfield is a lot more unique than just corfield (for a while there was a firm of lawyers in Australia with the corfield.com domain which seemed to confuse both people trying to contact them and people trying to contact me – and although some of my family live in Australia, we are completely unrelated to those lawyers).

And a third reason is that if I’m public about this change it might encourage others who host Clojure libraries to make a similar change and it wouldn’t be dependent on them owning a domain of their own: everyone who hosts a library on GitHub can use a verified group name of com.github.<username>.

2 Likes

while I have to respect the efforts of making Clojars more secure via verified group ids… being a ClojureScript(or JavaScript/TypeScript) user who barely touch Java, I do found myself confused(mostly unfamiliar) about the conventions about “reverse domain names”.

The basic idea behind it is so that if Company A releases a library called my-excellent-foobar and Individual B also releases a library called my-excellent-foobar, the library coordinates should be distinct so that users can include either one or both of them:

  • com.companya/my-excellent-foobar
  • com.github.individualb/my-excellent-foobar

And of course in Clojure we need the namespaces to not conflict either, which is why we generally encourage stuff like:

  • src/com/companya/foo_bar.cljcom.companya.foo-bar
  • src/individualb/foo_bar.cljindividualb.foo-bar

(although reverse domain naming could be adopted for the latter as well)

Thanks Sean, for surfacing this announcement here and for explaining it. I understood it better when I was able to read your examples of what you had done.

1 Like

I’ve also just updated the depstar README to explain my deployment process in case that helps others.

3 Likes

This is great news! I’m really stoked about this change.

Does Clojars also requires GPG/PGP signatures of uploaded artifacts?

For others interested, Maven Central has a good article that explains why they have the requirements they have for publishing libraries, Clojars is adopting a similar groupId requirement so it can give some context (though I don’t think it requires all the rest)

https://central.sonatype.org/pages/requirements.html

A long time ago, Clojars had a two-tiered approach to publishing libraries: signed and unsigned. If you signed your library, you could “promote” it to the verified tier (I forget what it was actually called); if you didn’t sign your library, it could only live on the “regular” tier.

The reality was that almost no one signed their libraries and eventually they decided to remove all that machinery since it was a maintenance overhead and wasn’t worth the complexity.

So, no, Clojars has never required signing artifacts as far as I know. Leiningen’s author was very strongly in favor of encryption and signatures which is why Leiningen defaults to that and you have to do the dance to turn it off. Boot did not sign artifacts by default (part of why I switched to Boot was easier deployment from multiple machines because the whole GPG thing was a giant PITA on Windows!).

@slipset 's deps-deploy supports artifact signing (a recent addition) if you want to do that for CLI-based deployments (the default is to not sign the artifact so you have to opt-in).

I have mixed feelings about the change, as I deploy a lot of projects under cider and nrepl and down the road there are bound to be even more projects there. So, if I can’t verify cider and nrepl the new projects are going to have different group ids for no good reason IMO. I get the point, but I don’t understand why the legitimate owners of the existing group ids can’t continue to use them as they did before (instead now it’s limitted only to existing packages). More on the subject - First alpha · Issue #6 · clojure-emacs/enrich-classpath · GitHub