Running perl
one-liners from command line has security implications.
The problem is that options -n/-p
trigger the diamond operator <>
, which use two arguments form of open
, so with files name contain special characters, perl
doesn't work as expected:
$ perl -pe '' 'uname|'
Linux
Or more dangerous when files name starting with >
, like >file
. In this case, file will be truncated.
For work around with this issue, we can:
ARGV::readonly
module by ourself:perl -pe 'BEGIN{$_.="\0" for @ARGV} ...' ./*
-i
option, as perl
will check for file existed before processing it.-T
option to enable taint mode.I think all solutions can fix this issue, but also have their side effects. If we can force perl
always use thee argument form of open
, it'll be a better solution.
I wonder can we do it, force perl
always use thee argument form of open
?
Note
The question only apply for the case when running perl
one liners from command line, because (of course) we can always use three argument form of open
in Perl script.
You probably only want to do this for one-liners (using the -e
switch), so you'll want to customize ARGV::readonly
for that purpose.
package Sanitize::ARGV;
if ($0 eq '-e') {
@ARGV = map { # from ARGV::readonly
s/^(\s+)/.\/$1/;
s/^/< /;
$_.qq/\0/;
} @ARGV;
}
1;
To force this package to be used system-wide, you can use an alias as Patrick J.S. suggests
alias perl='perl -MSanitize::ARGV'
or set a system-wide PERL5OPT
variable
PERL5OPT="-MSanitize::ARGV"
And if you want to be more paranoid, hide your system perl (rename it to something unintelligible) and replace it with a wrapper
#!/bin/bash
THE_REAL_PERL=/usr/bin/glorbqweroinuerqwer
$THE_REAL_PERL -MSanitize::ARGV "$@"
The shell wrapper will still respect any user customizations to PERL5OPT
In the general case, you can use the CORE::GLOBAL
mechanism to override the builtin open
function, e.g.
package SafeOpen;
use Carp;
BEGIN {
*CORE::GLOBAL::open = sub (*;$@) {
goto &CORE::open if @_ > 2;
Carp::cluck("OH MY GOD USING THE TWO-ARG open ARE YOU LIKE INSANE?");
return CORE::open($_[0], '<', $_[1] // $_[0]);
};
}
1;
and when this module is in use you will catch anyone in the act of using a 2-arg open
call. Unfortunately, I think the mechanism of the ARGV
filehandle magic bypasses this, so it still doesn't help with goofy filenames on the command line in a one-liner.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With