> the Chapter "Locking Ruby in the Safe" says this should
> work:
>
>   fn = 'dummy.rb'
>   File.open fn, 'w' do |f|
>     f.puts 'puts "hello"'
>   end
>   Thread.start {
>     $SAFE = 4
>     load fn, true
>   }.join
>
> I get an error:
>
>   in `load': Insecure operation `load' at level 4 (SecurityError)
>
> Why?

This is the expected behaviour: inside the thread you create you set
the $SAFE level to 4, meaning that from here on within the thread you
can't access variables from outside the thread scope. What you can do
is either hardcode the file name in the #load or pass an argument to
the thread:

| Thread.start(File.expand_path(fn)) { |fn|
|   $SAFE = 4
|   load fn, true
| }.join

The expand_path is because you cannot load a relative path when in
$SAFE >= 2.
Notice that your 'dummy.rb' file contains a call to Kernel#puts, which
is also not allowed. Try it with:

| File.open fn, 'w' do |f|
|   f.puts 'raise "hello"'
| end

HTH,
Assaph