Okay, here's a patch. When Safe code is eval'ed now, there are no lexical variables declared within any nested scope, apart from one called $__ExPr__, which is actually local to the code being evaled and has no connection with a lexical variable of the same name that happens to be in an outer nested scope and which is used by Safe.pm. So its secure, but ever so slightly untidy. The one remaining lexical is needed because a closure is used to pass the code to be eval'ed. This is necessary because Opcode.xs provides a safe_call_cv() function but not a safe_eval_pv()-type function. So Safe.pm used to do the rough equivalent of sub reval { my $expr = (code to be evaled); safe_call_sv(sub { eval $expr }); ); My patch moves the relevant code to the start of the file to avoid most lexical variables being in scope; renames $expr to $__ExPr__, and adds an extra my to the start of the code: sub { eval 'my $__ExPr__;' . $__ExPr__ }; Given that this ia security patch, other eyes may want to give it a one-over. Dave. -- Justice is when you get what you deserve. Law is when you get what you pay for. --- ext/Opcode/Safe.pm- Sun Sep 7 17:24:51 2003 +++ ext/Opcode/Safe.pm Sun Sep 7 18:58:44 2003 @@ -5,6 +5,26 @@ $Safe::VERSION = "2.09"; +# *** Don't declare any lexicals above this point *** +# +# This function should return a closure which contains an eval that can't +# see any lexicals in scope (apart from __ExPr__ which is unavoidable) + +sub lexless_anon_sub { + # $_[0] is package; + # $_[1] is strict flag; + my $__ExPr__ = $_[2]; # must be a lexical to create the closure that + # can be used to pass the value into the safe + # world + + # Create anon sub ref in root of compartment. + # Uses a closure (on $__ExPr__) to pass in the code to be executed. + # (eval on one line to keep line numbers as expected by caller) + eval sprintf + 'package %s; %s strict; sub { @_=(); eval q[my $__ExPr__;] . $__ExPr__; }', + $_[0], $_[1] ? 'use' : 'no'; +} + use Carp; use Opcode 1.01, qw( @@ -211,15 +231,7 @@ my ($obj, $expr, $strict) = @_; my $root = $obj->{Root}; - # Create anon sub ref in root of compartment. - # Uses a closure (on $expr) to pass in the code to be executed. - # (eval on one line to keep line numbers as expected by caller) - my $evalcode = sprintf('package %s; sub { @_ = (); eval $expr; }', $root); - my $evalsub; - - if ($strict) { use strict; $evalsub = eval $evalcode; } - else { no strict; $evalsub = eval $evalcode; } - + my $evalsub = lexless_anon_sub($root,$strict, $expr); return Opcode::_safe_call_sv($root, $obj->{Mask}, $evalsub); }