http://www.perlmonks.org?node_id=720526


in reply to Re^5: magic-diamond <> behavior -- WHAT?!
in thread magic-diamond <> behavior -- WHAT?!


That's everytime -n or -p is used. If tainting was employed, it defeats the purpose of using the shorthand notation in the first place.


This cannot be anticipated by the perl program. Perl gets @ARGV as it is from the executing shell because the shell has already done the expansion.


Well, even if the environment is trusted, the possibility of stray filenames can cause other types of damage. I mean, bad filenames may be created unintentionally by some other program working in tandem with perl's <ARGV>.

Replies are listed 'Best First'.
Re^7: magic-diamond <> behavior -- WHAT?!
by JavaFan (Canon) on Oct 30, 2008 at 18:21 UTC
    If tainting was employed, it defeats the purpose of using the shorthand notation in the first place.
    Why? If you're using a simple -n/-p one-liner from the CLI, you can still do that with -T. Your one-liner will still run fine, except for the one time that you do have a filename ending with '|' (or starting with '<', '>' or '|'). I assume you don't have the habit of using such filenames all the time.
    This cannot be anticipated by the perl program. Perl gets @ARGV as it is from the executing shell because the shell has already done the expansion.
    Yes, but it can be anticipated by the person running the program.
    I mean, bad filenames may be created unintentionally by some other program working in tandem with perl's <ARGV>.
    Which means, the environment is untrusted. That really isn't any different from:
    while (<STDIN>) { # No magic open chomp; unlink or die; }
    if the input is created by a program that unintentionally produces a name of an important file, you also have a problem. Again, a problem that could have been prevented by checking the data you got from the outside (and enabling tainting means Perl checks whether you've checked).
        Why? If you're using a simple -n/-p one-liner from the CLI, you can still do that with -T.

      This
      now becomes
        perl -Tpe 'BEGIN { $ENV{PATH} = "" } s/#.*$//'

      Here's the deal:

      • I agree that the one-liner still runs fine, but the shorthand notation is defeated.
      • I agree that taint is a good thing, but I don't need its power & nit-pickiness for such a common, simple operation.
      • I need to be able to whip up many safe read-only operations quickly. The current magic-diamond behavior is causing worries for me.

        Yes, but it can be anticipated by the person running the program.

      How? By checking the expanded filenames manually? I pass my filter to a co-worker in good spirit. "What, she ran it on a filename that ended with pipe-char "|"? Shame on her! for not knowing better that that means it will magically run a shell progra.... with 2-argument ope....."

      OK, ok. I pass my tainted filter to a co-worker in good spirit. "What, she got some Insecure dependency message? It only did half the files? Oh, she must have ran into a filename that ended with pipe-char "|". Shame on her! for not knowing better that that means Perl is in taint mode which checks for... among other things... so that it doesn't run a shell progra.... with 2-argument ope.... to get around this whole stinki...."

      Eyes will glaze over at the explanations above, or ignorance is bliss. Either way, Perl gets a bad rep.

        That really isn't any different from:

      No, it is different. Once again, your example is an explicit call to unlink. The magic-diamond implicitly performs arbitrary shell commands. "Arbitrary shell commands" is much worse than "fixed, predetermined perl function (unlink) call".
        This
        perl -pe 's/#.*$//'
        now becomes
        perl -Tpe 'BEGIN { $ENV{PATH} = "" } s/#.*$//'
        Why? You don't want to run external commands, do you? perl -Tpe 's/#.*$//' runs fine as long as magic open doesn't try to open a pipe to a program. But if you happen to pass rm -rf * | as a filename, taint will abort the program.
        Yes, but it can be anticipated by the person running the program.
        How? By checking the expanded filenames manually? I pass my filter to a co-worker in good spirit. "What, she ran it on a filename that ended with pipe-char "|"? Shame on her! for not knowing better that that means it will magically run a shell progra.... with 2-argument ope....."
        No, shame on you for not telling her.

        Suppose you would give her 'rm', and tell her it removes all files you give it as arguments. Now she runs 'rm *', and suddenly all her directories are gone as well, because she happened to have a file called '-rf' in her directory. I think she has the right to blame you for not telling her the entire truth.

        BTW, suppose you, and all the other people in this thread who agree with you, manage to eliminate magic open because it's too dangerous if someone runs a program using magic open with a shell expanded '*', what's next? Eliminate Getopt::*? Because that could also do unexpected things if such a program is run with a shell expanded '*'.

        No, it is different. Once again, your example is an explicit call to unlink
        You were talking about "other" programs unintentionally creating data (in this case, filenames) which could have unwanted effects, yet it somehow isn't serious enough to warrant enabling taint checking. I came with a similar example of an "other" program unintentionally creating data (in my case, input to the program) which could have unwanted effects. My point is that if your program relies on data which cannot be trusted, it should taint check that data. Whether it's because you're using magic open, unlink or something else.

      From the programmer's perspective:
      When you use unlink, you expect to delete a file (user supplied or otherwise).
      When you use <>, you expect to read a file (user supplied or otherwise), but it doesn't.

      From the user's perspective:
      When asked for the name of a file to delete, you're not surprised if the file you specified gets deleted.
      When providing the name of a file to read (script.pl *), you're *are* surprised if the file name gets treated as a shell command.

      The problem is the divergence between the programmer's needs and the tools provided by the language. <> is the closest thing provided to what the programmer needs, so it gets used. The alternatives are just too costly in almost all circumstances.