There is a recent event where a Node.js developer decided to unpublish all of his 250 or so modules on npmjs.org (including some very popular modules, causing large breakage) following a corporate takedown notice for one of his modules. The ensuing HN discussion thread highlights a security issue where a malicious author could upload a malicious update to a previously existing (but then unpublished) module. I'm wondering how such issue is handled in the Perl (CPAN) community.
If someone unpublishes his module (i.e. deletes the release tarball from PAUSE), at least there's an extra step where he must also give up his primary maintainer/co-maintainer status to allow others to upload to the same package name. Well, that's not entirely correct. PAUSE allows any author to upload distribution which contains modules that occupy the same namespace as existing ones, it's just that the modules won't be indexed if the version number is older than existing indexed one or if there is insufficient permission. But once the original author makes the namespace available again, it's back to free for all: any other PAUSE author (malicious or not) can theoretically upload to the same namespace and spread malware or compromise users' systems via module update. It's easy to register a PAUSE account.
PAUSE creates a CHECKSUMS file in author's directory, listing each release file along with its last modified time, size, MD5 and SHA256 checksums. The CHECKSUMS file is then signed by PAUSE. A CPAN client can be instructed (e.g. --verify in cpanm) to check the signature of the CHECKSUMS file.
A couple of issues: 1) signature verification is not enabled by default in CPAN client (at least in cpanm); 2) most (all?) CPAN mirrors are ftp/http and not https, so during the first installation where the client does not have PAUSE's public key yet, a MITM attack can spoof the CHECKSUMS file as well as the release tarballs without the client being able to detect it. These issues can be fixed in the client: enable --verify by default and bundle the PAUSE public key.
Additionally, an author can also sign his distribution using a framework like Module::Signature. This will create a SIGNATURE file in the top-level directory of the distribution which contains the checksums of the files in the distribution. The SIGNATURE is then signed using the author's PGP key. This protects the distribution from being tampered by the server (in this case, PAUSE).
A CPAN client can then be instructed (also --verify in cpanm) to check this signature file. The 'cpansign' CLI tool distributed along with Module::Signature can also be used for this purpose. The same issue also exists: verify is not enabled by default. And another issue, code signing by author is not mandatory and as far as I know, only a small percentage of authors do this. And yet another issue, at least when I tried it, tool like 'cpansign' is not strict by default: when it fails to retrieve the required PGP public key, it stills reports "==> Signature verified OK! <=".
A more paranoid CPAN client can also be setup to only accept a predefined set of authors' keys. This can mitigate the issue of another previously unknown PAUSE author trying to push an update to existing module.
Client system can also protect against regular update breakage by setting up a private DarkPAN repository where each module update is first tested then pushed to this repository. Client machines then update their Perl modules from this private repository and not directly from a CPAN mirror.
Conclusion: there are mechanisms already in place in the CPAN infrastructure to prevent the abovementioned security issue. But the problem is they are not enabled by default.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: What if someone liberated his Perl modules?
by Corion (Patriarch) on Mar 23, 2016 at 10:01 UTC | |
|
Re: What if someone liberated his Perl modules?
by Tanktalus (Canon) on Mar 25, 2016 at 20:17 UTC | |
|
Re: What if someone deleted his Perl modules? (cpan/pause unauthorized)
by Anonymous Monk on Mar 23, 2016 at 09:13 UTC | |
by perlancar (Hermit) on Mar 23, 2016 at 12:42 UTC | |
by Anonymous Monk on Mar 24, 2016 at 07:37 UTC | |
by perlancar (Hermit) on Mar 24, 2016 at 12:02 UTC |