Last active
September 19, 2019 21:19
-
-
Save briandfoy/065bb5179108ef98cc8b1a93a0762f44 to your computer and use it in GitHub Desktop.
Using TMPDIR under taint-checking
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/Users/brian/bin/perl | |
use v5.10; | |
BEGIN { | |
=pod | |
Windows: | |
$ENV{TMPDIR} | |
$ENV{TEMP} | |
$ENV{TMP} | |
SYS:/temp | |
C:\system\temp | |
C:/temp | |
/tmp | |
/ | |
=cut | |
print <<"HERE"; | |
TMPDIR: $ENV{TMPDIR} | |
TEMP: $ENV{TEMP} | |
TMP: $ENV{TMP} | |
HERE | |
# these are the directories that File::Spec will check | |
# each OS has a different set | |
my %sysdirs = ( | |
unix => [qw( /tmp )], | |
MSWin32 => [qw( | |
SYS:/temp | |
C:\system\temp | |
C:/temp | |
/tmp | |
/ | |
)], | |
cygwin => [qw( | |
/tmp | |
C:/temp | |
)], | |
); | |
# these are the variables that File::Spec will check | |
my %envvars = ( | |
MSWin32 => [qw( TMPDIR TEMP TMP )], | |
cygwin => [qw( TMPDIR )], | |
unix => [qw( TMPDIR )], | |
); | |
my $keys = $envvars{ exists $envvars{$^O} ? $^O : 'unix' }; | |
my( $candidate_key ) = grep { defined $ENV{$_} } $keys->@*; | |
say "Candidate key is $candidate_key"; | |
# try the enviroment variable first | |
if( exists $ENV{$candidate_key} ) { | |
$pattern = '.+'; # a real pattern is much more complicated path matcher | |
if( $ENV{$candidate_key} =~ m/($pattern)/ ) { | |
my $matched = $1; | |
unless( -d $matched ) { | |
die "TMPDIR value <$matched> does not exist"; | |
} | |
unless( -w $matched ) { | |
die "TMPDIR value <$matched> is not writeable"; | |
} | |
say "Untainting <$matched>"; | |
$ENV{$candidate_key} = $matched; | |
} | |
else { | |
die "Could not untaint TMPDIR value: $ENV{$candidate_key}"; | |
} | |
} | |
# without an environment value, try the system dirs. Note that cygwin | |
# mixes the order of environment values and system dirs, though. I don't | |
# handle that here. | |
else { | |
my $sysdirs = $sysdirs{ exists $envvars{$^O} ? $^O : 'unix' }; | |
foreach my $dir ( $sysdirs->@* ) { | |
say "Temp dir <$dir> is a writable dir? ", -d -w $dir; | |
} | |
} | |
} | |
use File::Spec qw(tmpdir); | |
# having untainted env vars, ask File::Spec for the temp dir. This is | |
# what File::Temp will do for you. | |
my $tmpdir = File::Spec->tmpdir(); | |
# Just because you have a value doesn't mean it's valid. As with any | |
# filesystem operation, check its value before you blindly use it. | |
say "Temp dir is $tmpdir"; | |
unless( -d $tmpdir ) { | |
die "<$tempdir> does not exist"; | |
} | |
unless( -w $tmpdir ) { | |
die "<$tempdir> is not writeable by you"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment