Skip to content

Instantly share code, notes, and snippets.

@briandfoy
Last active September 19, 2019 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save briandfoy/065bb5179108ef98cc8b1a93a0762f44 to your computer and use it in GitHub Desktop.
Save briandfoy/065bb5179108ef98cc8b1a93a0762f44 to your computer and use it in GitHub Desktop.
Using TMPDIR under taint-checking
#!/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