One of the most important tasks of the distribution packager is to ensure that the software shipped to our users is free of security vulnerabilities. While finding and fixing the vulnerable code is usually considered upstream’s responsibility, the packager needs to ensure that all these fixes reach the end users ASAP. With the aid of central package management and dynamic linking, the Linux distributions have pretty much perfected the deployment of security fixes. Ideally, fixing a vulnerable dependency is as simple as patching a single shared library via the distribution’s automated update system.
Of course, this works only if the package in question is actually following good security practices. Over the years, many Linux distributions (at the very least, Debian, Fedora and Gentoo) have been fighting these bad practices with some success. However, today the times have changed. Today, for every 10 packages fixed, a completely new ecosystem emerges with the bad security practices at its central point. Go, Rust and to some extent Python are just a few examples of programming languages that have integrated the bad security practices into the very fabric of their existence, and recreated the same old problems in entirely new ways.
This post explains the issue packagers run into very well – and it sure does look like these newer platforms are not very good citizens. I know this isn’t related, but this gives me the same feelings and reservations as Flatpak, Snap, and similar tools.
As both a developer and Linux user I see there are pros and cons in both approaches. However, as the article is in the packager side of things I’m going to point out a few things in the opposite side. Linux package managers are really C/C++ package managers. They were designed to do that well in an era where no C package managers existed. New languages use their own package managers, which are cross-platform, easier to use, and provide a better workflow, so I think this will prevail and they will be the source of truth in the code. When the new languages arrived (starting with Ruby), most distros didn’t change its policy or explored new ways to adapt to this paradigm shift and now I think it is too late.
Also, they talk about pinning, which they say is bad. I don’t think so. I think that if a program can’t be secure if it doesn’t have a maintainer that at least change the pinned version. Otherwise, you’re just keeping zombie programs which may seem secure at first but not really. Pinning is good because it gives us reproducibility. In fact distros also want reproducibility, it’s just that they want to pin versions in their package manager, not in the upstream program. But developers want reproducibility in upstream, because it also works on other distros and OSs!
Although, the general argument of “dynamic linking is better because we can upgrade the libs without waiting for upstream” is a valid point, it is not a silver bullet because security updates that need breaking APIs/ABIs are a thing and then you still need to wait for upstream (or do a patch).