I'm sure others are already pointing this out, but the second eval line uses double quotes, so an interpolation is being done before eval "" even sees it.
My preferred form is:
if (defined $module)
{
# Detaint
$module =~ m/^(My_Safe_Namespace(?:\:\:\w+)*)$/
or die "Unsafe module name: $module\n";
$module = $1;
eval "use $1;";
die if $@;
# Call 'run' as a method to avoid eval-string
$module->run();
}
Eval-string is generally a bad idea for security reasons, assuming you're relying on data external to the program. This is just a way of minimising its use.