>irb irb(main):001:0> RUBY_DESCRIPTION => "ruby 1.8.7 (2008-05-31 patchlevel 0) [i386-mswin32_90]" irb(main):002:0> $SAFE=1 => 1 irb(main):003:0> $:.unshift "hoge".taint => ["hoge", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8",..., "."] irb(main):004:0> require 'cgi' SecurityError: Insecure operation - require from (irb):4:in `require' from (irb):4 from :0 irb(main):005:0>
1.8.7でもこうなのだから知らない俺が抜けているのだが、$SAFE=1のときに汚染された文字列を $LOAD_PATHに追加する(pushでも unshiftでも)と、一切の requireができなくなる。
期待したいのは、hoge/cgi.rbや hoge/cgi.soなどが存在するときには、このパスは汚染されているので SecurityError。存在しないときはファイルの探索を続けて C:/Program Files (x86)/ruby/lib/ruby/1.8/cgi.rb (このパスは汚染されていないはず)を読み込む、という動作なのだけど……。
実際はそうではないのだから tDiaryの
tdiary.rb:12: $:.insert( 1, File::dirname( __FILE__ ) + '/misc/lib' )
というのは __FILE__ が汚染されているときに、わりと危険な操作ということになる。問題が起きないのは SAKURAのレンタルサーバの Rubyが 1.8.6だからなのか、__FILE__、File.dirname(__FILE__) が汚染されていることが稀だからなのか。(汚染されていることが実際にあるのは、20090117p01で書いたように、untaintすることで状況が改善したことから推測できる)
問題が起きないのは SAKURAのレンタルサーバの Rubyが 1.8.6だからなのか、__FILE__、File.dirname(__FILE__) が汚染されていることが稀だからなのか。
両方でした。__FILE__が汚染されているのは Ruby-1.9.1RC1だから(多分)。
$SAFE=1のときに汚染された文字列を $LOAD_PATHに追加する(pushでも unshiftでも)と、一切の requireができなくなる。
書きながら誇張だとは気付いていたのだけど(一切の、の部分が)、そうでない例を自分で見つけたので追記(2009-02-02)。
Windowsで、フルパスで、あるいは拡張子(.rb)なしのフルパスでなら requireできる。
Y:\...\Desktop\a>irb irb(main):001:0> RUBY_DESCRIPTION => "ruby 1.8.7 (2008-05-31 patchlevel 0) [i386-mswin32_90]" irb(main):002:0> $SAFE=1 => 1 irb(main):003:0> $:.push "".taint => ["C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby/1.8/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby/site_ruby", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby/1.8/i386-msvcr90", "C:/Program Files (x86)/ruby/lib/ruby/vendor_ruby", "C:/Program Files (x86)/ruby/lib/ruby/1.8", "C:/Program Files (x86)/ruby/lib/ruby/1.8/i386-mswin32_90", ".", ""] irb(main):004:0> require "a" SecurityError: Insecure operation - require from (irb):4:in `require' from (irb):4 from :0 irb(main):005:0> require "a.rb" SecurityError: Insecure operation - require from (irb):5:in `require' from (irb):5 from :0 irb(main):006:0> require "./a.rb" SecurityError: Insecure operation - require from (irb):6:in `require' from (irb):6 from :0 irb(main):007:0> require "Y:/.../Desktop/a/a" => true irb(main):008:0> require "Y:/.../Desktop/a/a.rb" => false irb(main):009:0> require "a" SecurityError: Insecure operation - require from (irb):9:in `require' from (irb):9 from :0 irb(main):010:0>