Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight

Proper and acceptable use of backticks in a modern Perl script

by Polyglot (Chaplain)
on Sep 18, 2023 at 10:23 UTC ( #11154513=perlquestion: print w/replies, xml ) Need Help??

Polyglot has asked for the wisdom of the Perl Monks concerning the following question:

I'm not even invoking taint in the script--but it seems that taint is active (is this because of the Perl version? more on that below), and crashes the program for one simple line:

my @fonts = `/usr/bin/fc-list : family`;

My perl version is:

perl -v This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-li +nux-gnu-thread-multi (with 58 registered patches, see perl -V for more detail)

The error that appears in my logs is: "Insecure $ENV{PATH} while running with -T switch . . .," despite the fact that my shebang line has only #!/usr/bin/perl and, while narrowing the problem down, I have disabled all module uses except one: use CGI qw(-utf8);.

As is clear to be seen, there are no variables, nor any executable code, inside the backticks--so there should be no legitimate security issue worthy of shutting down the execution of the script. They invoke a standard command which is useful for displaying the fonts available and installed on the server. Should those fonts change, such as if more were to be installed, the next run of the script would automatically show this--which is what I want.

But even if I put ls inside those backticks, the whole script will fail, and I get "Internal Server Error" as the message in my browser.

Other options than using backticks seem cludgy at best, and problematic at worst. I could run a cronjob that writes the output of this command to a file, then the perl script reads from that file. To be up-to-date, this cronjob would have to run often, consuming server resources--not to mention the added unnecessary file to be stored in the system.

I could use a system call (assuming taint would allow this--I haven't tried it yet) that would do what the cronjob does, then, after opening and reading the file, I could unlink it. This requires multiple steps, much more code, involves file permissions which create potential failure points, and just seems quite rather unperlish.

I fell in love with perl years ago when it gave me the ability to do what I wanted in easy and intuitive ways. This taintedness is rubbing against the grain.

Why is taint even forced on the script without my having invoked it? In actual fact, I would like the script to run with taint, but I need to be able to run this command, too. Is this as impossible as wanting to have my cake and eat it too?



Replies are listed 'Best First'.
Re: Proper and acceptable use of backticks in a modern Perl script
by hippo (Bishop) on Sep 18, 2023 at 10:50 UTC
    Insecure $ENV{PATH} while running with -T switch

    Solution: untaint $ENV{PATH}.

    BEGIN { $ENV{PATH} = '/bin'; }

    Where's the problem?


      Yes, this would solve the problem. I find it frustrating, however, that Perl's taint would not figure out that the path in the backticks was not a relative path and would be entirely unaffected by the $ENV{PATH} variable. One could set that to anything at all!



        the path in the backticks was not a relative path and would be entirely unaffected by the $ENV{PATH} variable

        That's not the (whole) issue. The code you are executing within the backticks could do anything including spawning subshells which could execute code in the tainted PATH. Much more secure to specify the PATH either by hard-coding as here or with careful untainting. Just because your command statement at the top level doesn't utilise $PATH it doesn't mean that some part of it won't when running.


Re: Proper and acceptable use of backticks in a modern Perl script
by marto (Cardinal) on Sep 18, 2023 at 10:32 UTC

    Did you read Taint mode? There's some criteria where taint is automatically enabled.

      Thank you for the response. No, I hadn't read that. Reading it now, however, I see that it points toward issues I do not have:

      1) An issue with either SETUID or SETGID, neither of which applies to my case. This is being run as an ordinary cgi script on the server, with no special permissions.

      2) An issue with the external command affecting something else external to the script. Not applicable to my use case either.


      So, what applies to my case is this:

      $arg, `true`;        # Insecure (although it isn't really)

      The parenthesized statement, the last in its list of examples, is what applies to me. What I am doing should not be a problem! But, I don't see in that file what I am supposed to do about this.


      Then I found this:

      On versions of Perl before 5.26, activating taint mode will also remov +e the current directory (".") from the default value of @INC. Since v +ersion 5.26, the current directory isn't included in @INC by default. Cleaning Up Your Path For "Insecure $ENV{PATH}" messages, you need to set $ENV{'PATH'} to a +known value, and each directory in the path must be absolute and non- +writable by others than its owner and group. You may be surprised to +get this message even if the pathname to your executable is fully qua +lified. This is not generated because you didn't supply a full path t +o the program; instead, it's generated because you never set your PAT +H environment variable, or you didn't set it to something that was sa +fe. Because Perl can't guarantee that the executable in question isn' +t itself going to turn around and execute some other program that is +dependent on your PATH, it makes sure you set the PATH.

      ...and I added a line to my code:

      $ENV{'PATH'} = '/var/www/';

      ...and simple as that, the problem was solved. I guess I have heretofore been fortunate enough to work with versions of Perl before 5.26.



        $ENV{'PATH'} = '/var/www/';

        All relevant executables are in /var/www? I HIGHLY doubt that. A safe value for $ENV{'PATH'} is generally /bin:/usr/bin (which is also the default path set by the operating system, i.e. kernel and/or init). If you want to avoid any executable to be run without an giving its absolute path, set $ENV{'PATH'} to a non-existing or empty directory.


        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11154513]
Approved by marto
Front-paged by Corion
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (2)
As of 2023-12-09 18:50 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (38 votes). Check out past polls.