From 89853d76c827c07a8cd0cb38bd1727e96afaadef Mon Sep 17 00:00:00 2001 From: Dominic Hargreaves Date: Wed, 17 May 2017 15:17:42 +0100 Subject: [PATCH] Add more extensive information about @INC changes into perldelta (RT#131304) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This mainly takes existing text written by Dave Mitchell, Kent Fredric, Sawyer X and James E Keenan. [Ævar: I applied this from RT #131304. It had conflicts which I resolved to the best of my ability. The submitted patch removed the "'.' and @INC" section which I rewrote in 90ed3b64f9 ("perldelta: clarify what '.' and @INC is about", 2017-05-16). I resolved the conflict to keep it. Maybe this was the wrong move. We're now mentioning the removal of "." in 3 prominent places, at the top in "Notice", "Core Enhancements", and "Security". Maybe the best move here is to remove the section I wrote, although as noted in my commit I think one redeeming factor it if is the plain language describing the change (i.e. not assuming knowledge of variables like @INC right off the bat), but obviously I'm biased there]. --- pod/perldelta.pod | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 204 insertions(+), 5 deletions(-) diff --git a/pod/perldelta.pod b/pod/perldelta.pod index bd54f15..3937542 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -9,6 +9,24 @@ perldelta - what is new for perl v5.26.0 This document describes the differences between the 5.24.0 release and the 5.26.0 release. +=head1 Notice + +This release includes two updates with widespread effects: + +=over 4 + +=item * C<.> no longer in C<@INC> + +The current modules, and for the execution of scripts. See the section +L< from @INC>> for the full details. + +=item * C may now warn + +C now gives a mandatory warning when it fails to load a file which it +would have loaded had C<.> been in C<@INC>. + +=back + =head1 Core Enhancements =head2 New regular expression modifier C @@ -84,6 +102,11 @@ relative path is a common idiom in test code. If you find that you have C<.> in C<@INC> on a perl built with default settings it's likely that your code is being invoked by a toolchain module of some sort. +=head2 create a safer utf8_hop() called utf8_hop_safe() + +Unlike utf8_hop(), utf8_hop_safe() won't navigate before the beginning or after +the end of the supplied buffer. + =head2 @{^CAPTURE}, %{^CAPTURE}, and %{^CAPTURE_ALL} C<@{^CAPTURE}> exposes the capture buffers of the last match as an @@ -209,11 +232,179 @@ the end of the supplied buffer. =head1 Security -=head2 Remove current dir (C<.>) from C<@INC> +=head2 Removal of the current directory (C<.>) from C<@INC> + +The perl binary includes a default set of paths in C<@INC>. Historically +it has also included the current directory (C<.>) as the final entry, +unless run with taint mode enabled (C). While convenient, this has +security implications: for example, where a script attempts to load an +optional module when its current directory is untrusted (such as F), +it could load and execute code from under that directory. + +Starting with v5.26.0, C<.> is always removed by default, not just under +tainting. This has major implications for installing modules and executing +scripts. + +The following new features have been added to help ameliorate these +issues. + +=over + +=item * C + +There is a new C option, C (enabled +by default) which builds a perl executable without C<.>; unsetting this +option using C<-U> reverts perl to the old behaviour. This may fix your +path issues but will reintroduce all the security concerns, so don't +build a perl executable like this unless you're I confident that +such issues are not a concern in your environment. + +=item * C<$PERL_USE_UNSAFE_INC> + +There is a new environment variable recognised by the perl interpreter. +If this variable has the value C<1> when the perl interpreter starts up, +then C<.> will be automatically appended to C<@INC> (except under tainting). + +This allows you restore the old perl interpreter behaviour on a +case-by-case basis. But note that this intended to be a temporary crutch, +and this feature will likely be removed in some future perl version. +It is currently set by the C utility and C to +ease installation of CPAN modules which have not been updated handle the +lack of dot. Once again, don't use this unless you are sure that this +will not reintroduce any security concerns. + +=item * A new mandatory warning issued by C. + +While it is well-known that C and C use C<@INC> to search +for the file to load, many people don't realise that C also +searches C<@INC> if the file is a relative path. With the removal of C<.>, +a simple C will fail to read in and execute C from +the current directory. Since this is commonly expected behaviour, a new +mandatory warning is now issued whenever C fails to load a file which +it otherwise would have found if dot had been in C<@INC>. + +=back + +Here are some things script and module authors may need to do to make +their software work in the new regime. + +=over + +=item * Script authors + +If the issue is within your own code (rather than within included +modules), then you have two main options. Firstly, if you are confident +that your script will only be run within a trusted directory (under which +you expect to find trusted files and modules), then add C<.> back into the +path; e.g.: + + BEGIN { + my $dir = "/some/trusted/directory"; + chdir $dir or die "Can't chdir to $dir: $!\n"; + # safe now + push @INC, '.'; + } + use "Foo::Bar"; # may load /some/trusted/directory/Foo/Bar.pm + do "config.pl"; # may load /some/trusted/directory/config.pl + +On the other hand, if your script is intended to be run from within +untrusted directories (such as F), then your script suddenly failing +to load files may be indicative of a security issue. You most likely want +to replace any relative paths with full paths; for example, + + do ".foo_config.pl" + +might become + + do "$ENV{HOME}/.foo_config.pl" + +If you are absolutely certain that you want your script to load and +execute a file from the current directory, then use a C<./> prefix; for +example: + + do "./.foo_config.pl" + +=item * Installing and using CPAN modules + +If you install a CPAN module using an automatic tool like C, then +this tool will itself set the C environment variable +while building and testing the module, which may be sufficient to install +a distribution which hasn't been updated to be dot-aware. If you want to +install such a module manually, then you'll need to replace the +traditional invocation: -For security reasons, C<@INC> no longer contains the default directory -(C<.>). See L in the L section for -details. + perl Makefile.PL && make && make test && make install + +with something like + + (export PERL_USE_UNSAFE_INC=1; \ + perl Makefile.PL && make && make test && make install) + +Note that this only helps build and install an unfixed module. It's +possible for the tests to pass (since they were run under +C), but for the module itself to fail to perform +correctly in production. In this case you may have to temporarily modify +your script until such time as fixed version of the module is released. +For example: + + use Foo::Bar; + { + local @INC = (@INC, '.'); + # assuming read_config() needs '.' in @INC + $config = Foo::Bar->read_config(); + } + +This is only rarely expected to be necessary. Again, if doing this, +assess the resultant risks first. + +=item * Module Authors + +If you maintain a CPAN distribution, it may need updating to run in +a dotless environment. Although C and other such tools will +currently set the C during module build, this is +temporary workaround for the set of modules which rely on C<.> being in +C<@INC> for installation and testing, and this may mask deeper issues. It +could result in a module which passes tests and installs, but which +fails at run time. + +During build, test and install, it will normally be the case that any perl +processes will be executing directly within the root directory of the +untarred distribution, or a known subdirectory of that, such as F. It +may well be that F or F will attempt to include +local modules and configuration files using their direct relative +filenames, which will now fail. + +However, as described above, automatic tools like F will (for now) +set the C environment variable, which introduces +dot during build. + +This makes it likely that your existing build and test code will work, but +this may mask issues with your code which only manifest when used after +install. It is prudent to try and run your build process with that +variable explicitly disabled: + (export PERL_USE_UNSAFE_INC=0; \ + perl Makefile.PL && make && make test && make install) + +This is more likely to show up any potential problems with your module's +build process, or even with the module itself. Fixing such issues will +ensure both that your module can again be installed manually, and that +it will still build once the C crutch goes away. + +When fixing issues in tests due to the removal of dot from C<@INC>, +reinsertion of dot into C<@INC> should be performed with caution, for this +too may suppress real errors in your runtime code. You are encouraged +wherever possible to apply the aforementioned approaches with explicit +absolute/relative paths, or relocate your needed files into a subdirectory +and insert that subdirectory into C<@INC> instead. + +If your runtime code has problems under the dotless C<@INC>, then the comments +above on how to fix for script authors will mostly apply here too. Bear in +mind though that it is considered bad form for a module to globally add dot to +C<@INC>, since it introduces both a security risk and hides issues of +accidentally requiring dot in C<@INC>, as explained above. + +=back +>>>>>>> Add more extensive information about @INC changes into perldelta (RT#131304) =head2 "Escaped" colons and relative paths in PATH @@ -1388,6 +1579,14 @@ L is no longer supported. Its use will be fatal in Perl 5.28|per (D deprecated) The special variable C<${^ENCODING}>, formerly used to implement the C pragma, is no longer supported as of Perl 5.26.0. +=item * + +Since C<.> is now removed from C<@INC> by default, C will now trigger +a warning recommending to fix the C statement: + +L + =back =head2 Changes to Existing Diagnostics @@ -1667,7 +1866,7 @@ tests for perlbug. [perl #128020] =item * -C<-Ddefault_inc_excludes_dot> has been turned on as default. +C<-Ddefault_inc_excludes_dot> has been turned on by default. =item * -- 1.8.3.1