What happened to . in @INC

In Perl, module loads have always attempted to look for the module you refer to in the current working directory (not necessarily the script location). It has always been this way in Perl. This goes back to the keyword "do" which precedes "require". When this was originally coded, it was also common to include . in your PATH.

Convention changed somewhere in the 90's. It is now considered a bad practice to include . in your PATH. Most languages also do not attempt to look for . in @INC. During my research earlier this year, I found that of all of the scripted languages, only Ruby used to have . in @INC and it was since removed.

During my tenure at cPanel, I have been the primary person responsible for maintaining the Perl distro that we use both internally and on our customer boxes. What I noticed while customizing the Perl instance for our code base was how aggressively we removed . from @INC so that modules could not be loaded from unintentional locations. It only made sense to consider removing it from @INC by default. So I fired off a short email to p5p to see if they knew of any gotchas. The flood of responses was impressive.

Time went by and other things came up at work. Last November, I managed to get back to looking into the problem. The major issue to overcome was not production code needing modules in a relative path. The problem was that the whole build system (perl Makefile.PL; make test; make install) assumed that the local libraries were present. Just doing perl -I. Makefile.PL wasn't enough because if that script called another perl script, that perl script would not have . in @INC.

I credit my co-worker JD for giving me the idea that I could set an environment variable to perpetuate support for . in @INC through child processes. This concept successfully overcame the problem and I was able to easily build a complete Perl stack simply by setting the environment variable PERL_USE_UNSAFE_INC=1 before build. We also backported @INC fixes to previous versions of our software because we felt this issue was so important.

In February, I opened a ticket with Perl 5 Porters to get them to accept a non-default option to remove . from @INC. Unfortunately, I was beaten to the punch and an exploit was disclosed to Perl 5 Security. TL;DR: There are now known insecurities about having . in @INC.

This weekend I was at the first Perl 5 Porters Hackathon in Amsterdam. With the help of Tux and others, I was able to get a merge which now allows you to build Perl without . in @INC.

If you build Perl with this option, a large portion of CPAN modules won't be able to install unless you first set the environment variable PERL_USE_UNSAFE_INC to 1. Now comes the fun part. Fixing all the CPAN modules to make this more transparent.

In light of the recent security disclosures, many in p5p would like to make 5.26 build without . in @INC come next June.

Leave a comment

About Todd Rinaldo

user-pic I blog about Perl.