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

I've recently come across a 'Insecure dependency in chdir while running setuid' problem (again). The source of the thorn comes from the File::Path rmtree() function.

File::Path uses the following code to untaint directory reads:
$entry =~ /^(.*)$/s; $entry = $1; # untaint
But it appears this isn't sufficient. To fully untaint the path, the code needs to match/assign from different variables more like:
$_ = $entry; ($entry) = /^(.*)$/s; # result and source are different
Hopefully someday, File::Path will be corrected. But in the mean time, my application (which has properly untainted the directory name in the first place) can't call rmtree() without bombing.

My options as I see it are to either:
(a) patch File::Path (don't want to touch external code)
(b) copy the rmtree() code into my application and fix it there (may as well not use the module at all)
(c) turn off taint checking in my application when ever I call rmtree() (this doesn't work).

Option (c) seems the least obtrusive but taint checking alone doesn't seem to be the cure. Are there any other ways to get around this?

Replies are listed 'Best First'.
Re: inconsistency in untaint
by shmem (Chancellor) on Aug 30, 2006 at 17:29 UTC
    Must be something different. I guess the variable you pass to rmtree is tainted.
    This works fine on my box (perl 5.8.8, Linux):
    #!/usr/bin/perl -T # file rmtree.pl use File::Path; my $dir = 'path'; rmtree($dir);

    called as

    qwurx [shmem] ~> mkdir -p path/to/some/file qwurx [shmem] ~> perl -T rmtree.pl

    and removes the path directory without complaint, as does

    #!/usr/bin/perl -T # file rmtree.pl use File::Path; my $dir = shift; $dir =~ /^(.*)$/ && ($dir = $1); rmtree($dir);
    called as
    qwurx [shmem] ~> mkdir -p path/to/some/file qwurx [shmem] ~> perl -T rmtree.pl path

    while this barfs

    #!/usr/bin/perl -T # file rmtree.pl use File::Path; my $dir = shift; # $dir =~ /^(.*)$/ && ($dir = $1); rmtree($dir);

    as it should:

    qwurx [shmem] ~> mkdir -p path/to/some/file qwurx [shmem] ~> perl -T rmtree.pl path Insecure dependency in chdir while running with -T switch at /usr/lib/ +perl5/5.8.8/File/Path.pm line 195.

    Mind to post some code?

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Also note the error message. You got 'while running with -T switch' which indicates the tainted data where as I'm getting 'while running setuid' which (I believe) indicates something more than standard untaint procedures.
        Oh, I overlooked that.

        The setuid bit doesn't matter on my system, same result with or without. AFAIK the only difference is that setuid forces the taint flag to be set, otherwise you must set it explicitly.

        What system are you running perl on?

        Tried with a C wrapper around your script as described in perlsec?

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Perl 5.8.7
      Does the script you're testing with have the suid bit set? I don't think it's stricly a taint problem. Initially I also thought it was an issue with passing tainted input so I put debug warnings in rmtree(). The first path value (passed in from the application) was taint free through the first chdir call. The subsequent recursive calls to sub directories as found and sanitized by File::Path then died.

      I noticed that File::Find also had issues like this and they've added an untaint flag to the interface. The File::Find code swaps between two variables (which File::Path doesn't) when untainting and doesn't appear to suffer from the bug as a result
Re: inconsistency in untaint
by nerfherder (Monk) on Feb 08, 2011 at 02:06 UTC
    I just had this same error message when calling mkdir() with a string containing a scalar which was passed to the function as an argument.

    The solution was to do something similar to what File::Path does to untaint to the variable prior to the mkdir() call:

    if ($tainted =~ /^([ &:#-\@\w.]+)$/) { $tainted = $1; #data is now untainted } else { # data is bad, log this: print STDERR "[TAINT] Bad Data received as \$tainted \n"; }