in reply to Re: Using relative paths with taint mode
in thread Using relative paths with taint mode

As of Perl 5.26, the current directory isn't in @INC any more, regardless of taint mode

So, I am getting the point that taint, and later versions of Perl are trying to make it difficult to use relative paths for modules!

This raises a different question...
Where should the modules be located?

If there was just one 'version' or environment of the website then it would be easy to just put them somewhere above the website root in the filesystem. I do this with modules that are common to all my websites. But there are always 2 and sometimes 3 different environments for every website. Production, test and sometimes development.

/home/myusername/somewebsite/prod/cgi-bin/Site/ /home/myusername/somewebsite/test/cgi-bin/Site/ /home/myusername/somewebsite/dev/cgi-bin/Site/

Having the modules in a relative path allows them to be logically separated in each of the environments and to be developed and tested before being released into production.

Is the solution to locate the modules above the website root with a different subfolder for each environment?

/home/myusername/somewebsite/prod/cgi-bin/ /home/myusername/somewebsite/test/cgi-bin/ /home/myusername/somewebsite/dev/cgi-bin/ /home/myusername/somewebsite/perlmodules/prod/ /home/myusername/somewebsite/perlmodules/test/ /home/myusername/somewebsite/perlmodules/dev/

I tried this for template files on the first site I created using Template. It was a bit messy to maintain so instead, for future projects, I have stored the templates in under the webroot but protected from HTTP access by putting an index.html file in the directory which sends the user to the homepage.

Is there a better way to handle this issue - what is the accepted norm for locating Perl modules on a webserver where there are multiple sites and multiple environments within each site?

Replies are listed 'Best First'.
Re^3: Using relative paths with taint mode
by hippo (Archbishop) on Jun 20, 2021 at 14:43 UTC
    So, I am getting the point that taint, and later versions of Perl are trying to make it difficult to use relative paths for modules!

    My reading of it is that they are trying to make it more difficult to use relative paths for modules accidentally. It it still trivially easy to use taint mode with relative paths on purpose. I do this frequently.

    Is the solution to locate the modules above the website root with a different subfolder for each environment?

    My solution is not to run dev, test and prod on the same machine. If you don't have multiple machines (why ever not?) then use multiple paths like this:

    /var/www/devsite/lib /var/www/testsite/lib /var/www/prodsite/lib

    This keeps the relative path the same across all three sites. Then all you need to do to use your modules is either:

    use lib '../lib'; # explicit, hard-coded relative path.

    or to save counting multiple ../../../ -

    use lib "$ENV{DOCUMENT_ROOT}/../lib" =~ m#^(/var/www/[a-z]+site/html/. +./lib)$#; # path relative to docroot

    and you're done. Simple, effective, secure.


    🦛

Re^3: Using relative paths with taint mode
by haj (Vicar) on Jun 20, 2021 at 15:07 UTC
    So, I am getting the point that taint, and later versions of Perl are trying to make it difficult to use relative paths for modules!

    You may put it like that. It turned out that too many people get it wrong and catch security holes, so making it difficult (but not impossible) gives people a chance to ponder over other approaches.

    If a website has more than one environment, then you need a plan anyway (again, nothing to do with taint mode) how you deploy and maintain the files in your different environments. There are many solutions for that, but I'd go for something like this:

    /home/myusername/somewebsite/prod/cgi-bin /home/myusername/somewebsite/prod/lib /home/myusername/somewebsite/prod/templates
    with the same subdirectories for dev and test. So each environment has its own base directory, but below that they all have the same structure. Then it is indeed possible to use FindBin to detect which environment you're actually in (assuming you don't run a persistent interpreter like mod_perl).

    my ($prefix,$website,$environment,$basedir); BEGIN { $prefix = '/home/myusername'; $website = 'somewebsite'; use FindBin qw($RealBin); if ($RealBin =~ m!$prefix/$website/(dev|test|prod)/cgi-bin!) { $environment = $1; # This is now untainted! $basedir = "$prefix/$website/$environment"; } else die "Bad or no environment '$1'"; } use lib "$basedir/lib"; my $tt = Template->new({INCLUDE_PATH => "$basedir/templates"}); ...;

    The BEGIN block is needed to do the necessary calculations during the compilation so that the directory is available when use lib is processed.

    Other alternatives include setting the environment as an environment (sic!) variable in the corresponding section of the web server config. Environment variables are tainted, so again you need to validate/untaint them.

      If a website has more than one environment, then you need a plan anyway (again, nothing to do with taint mode) how you deploy and maintain the files in your different environments. There are many solutions for that, but I'd go for something like this:
      /home/myusername/somewebsite/prod/cgi-bin /home/myusername/somewebsite/prod/lib /home/myusername/somewebsite/prod/templates

      That is pretty much what I have at present - except the contents of lib are hung directly off cgi-bin. So doing it that way doesn't mean changing things drastically which is a good thing.

      But I don't see how having the modules like this

      /home/myusername/somewebsite/prod/lib/Site/HTML.pm
      is anymore secure than having them like this
      /home/myusername/somewebsite/prod/cgi-bin/Site/HTML.pm
      as they are still accessible through HTTP as prod/ is the web root. Of course they can be made inaccessible either through putting an index.html file in there or through an .htaccess file.

        as they are still accessible through HTTP as prod/ is the web root.

        Why is that so? Do you understand the purpose of "web root"? Please clean that up: neither cgi-bin nor lib are supposed to lie under the web root (nor are templates). Also, an index.html doesn't make anything inaccessible, it just gets served when a browser is pointed to the directory (in a typical configuration).

        I mean, of course you can fiddle with as many of .htaccess files as you like, but why not simply avoid the problem in the first place?

Re^3: Using relative paths with taint mode
by marto (Cardinal) on Jun 20, 2021 at 14:04 UTC

    "later versions of Perl are trying to make it difficult to use relative paths for modules!"

    They made perl safer, not more difficult to use. local::lib has been mentioned you a couple of times previously.

      They made perl safer, not more difficult to use

      My point was that Perl is making one thing more difficult to do - and, by implication, that thing is being discouraged! I was not suggesting that Perl is, or is becoming, difficult to use!

      From your linked search, the last mention of local::lib was February 2016 which was before my time...

        "From your linked search, the last mention of local::lib was February 2016 which was before my time..."

        I didn't link to a search. Read what I wrote. local::lib has been mentioned to you, super search if you need to find where.

      I must be missing something...
      local::lib is for a "Perl module library located within the user's home directory".

      I don't see how that helps to separate development, test and production versions of a module when they are all in the same user's home directory.

        A home directory can contain more than one directory, the documentation gives examples of how to use this and specify a path (DEV/SYT/UAT...) which would make sense if you wanted to test your things with various combinations of cpan modules. If it's just your things you're interested in you obviously don't need to do this, and just go for the use lib method.