Bugs: Browse | Submit New | Admin

[#28336] "Insecure operation: initialize" when safe-mode is on

Date:
2010-06-28 14:04
Priority:
3
Submitted By:
Kasper Johansen (kaspernj)
Assigned To:
Nobody (None)
Category:
None
State:
Open
Summary:
"Insecure operation: initialize" when safe-mode is on

Detailed description
When SAFE is on, it is not possible to load a .mo-file.

Reproduceable code:

require "gettext"
include GetText
ENV["LANGUAGE"] = "da_DK"
GetText.bindtextdomain("locales", File.dirname(__FILE__) + "/../locales", "da_DK")
print _("Test")


Fails with:
index.rhtml:0: Insecure operation - initialize


It does not help to untaint any of the variables given to bindtextdomain. No backtrace.

I manually traced it back to the file: "gettext/runtime/mofile.rb" lines 273 - 281 the code:

def load_from_file(filename)
	@filename = filename
	begin
		File.open(filename, 'rb'){|f| load_from_stream(f)}
	rescue => e
		e.set_backtrace("File: #{@filename}")
		raise e
	end
end



Since the variable "filename" is "frozen" it cannot be "untaint". Therefore the following
replace solves the problem:

def load_from_file(filename)
	@filename = filename
	fn = String.new(filename)
	fn.untaint
	
	begin
		File.open(fn, 'rb'){|f| load_from_stream(f)}
	rescue => e
		e.set_backtrace("File: #{@filename}")
		raise e
	end
end


Further more this would have been A LOT easier if there wasnt a "e.set_backtrace; raise e". Why is that there
anyway?

If you remove the begin-rescue-end an easy backtrace is shown.


OS: Ubuntu 10.04, i386
Ruby -v: ruby 1.8.7 (2010-01-10 patchlevel 249) [i486-linux]
gettext versions tried: The one from Ubuntu-packages and the one from gems

Add A Comment: Notepad

Please login


Followup

Message
Date: 2011-09-24 10:44
Sender: Hleb Valoshka

Kasper, your solution is incomplete, because in file
runtime/mofile.rb, line 75 we have File.stat with that tainted
filename (okay, it's inside begin-rescue, but we still need it
to work).

So it seems better to redefine GetText::MOFile.load (anyway,
it's just a temporary solution) [Change 1]:

module GetText
  class MOFile
  alias :oldload :load
    def load(arg)
      arg = arg.dup.untaint if arg.kind_of? String
      oldload(arg)
    end
  end
end

But the code responsible for the exception residents in
gettext/runtime/locale_path.rb line 92 (the corresponding function
is ``initialize''):

90        Dir.glob(rule %{:lang => "*", :name =>
name}).each do |path|
91          if /#{this_path_rules}/ =~ path
92            @locale_paths[$1] = path unless @locale_paths[$1]
93          end
94        end

The fix is to change that line to [Change 2]

@locale_paths[$1] = path.untaint unless @locale_paths[$1]

It's because results of Dir.glob are considered to be insecure.

But it's not enough, if we want to use ruby 1.9! The next problem
is Locale.require_driver, we need to ``untaint'' argument to
``require'' [Change 3]:

module Locale 
  module_function
  def require_driver(name)  #:nodoc:
    require File.join(ROOT, "locale/driver",
name.to_s).untaint
  end
end

So, ``Change 1'' is a quick fix to make your program work under
ruby 1.8. But it's under 1.9 we still have exception on File.stat
at runtime/mofile.rb, line 75, and I don't know why. The library
will basically work, but there will be issues with MOFile#update!.
``Change 3'' can be used as a quick fix in your program too.
With ``Change 2'' (and 3 too) applied to library itself any program
works with $SAFE=1.
Date: 2010-07-04 12:23
Sender: Kasper Johansen

Hi Masao.

Thank you for responding.

I was running it through mod_ruby, where safe-mode is 
enabled by default.

If the test should fail, then the mo-file has to exist, or 
else the spawning-code wont be called and you wont get the 
error, which I guess is why you cant reproduce.

Any .mo-file should do it.
Date: 2010-07-04 01:10
Sender: Masao Mutoh

> Further more this would have been A LOT easier if there
wasnt a "e.set_backtrace; raise e". Why is that there
anyway?

I thought it' better to know know the filename which causes the
error.
Date: 2010-07-04 00:52
Sender: Masao Mutoh

How did you set SAFE to ON ?

If you mean you set $SAFE=1, I couldn't reproduce your problem
with your script.

% cat test.rb              
$SAFE=1
require "gettext"
include GetText
ENV["LANGUAGE"] = "da_DK"
GetText.bindtextdomain("locales", File.dirname(__FILE__)
+ "/../locales", "da_DK")
puts _("Test")

p GetText::VERSION
[mutoh@linux]~/dev/git/gettext/test% ruby -v -rubygems test.rb
ruby 1.8.7 (2010-01-10 patchlevel 249) [x86_64-linux]
Test
"2.1.0"

--

And what is index.rhtml ? Does it mean you use your sample code
file name with something like a web framework?
If so, how can I run it?

Attached Files:

Name Description Download
No Files Currently Attached

Changes:

Field Old Value Date By
summary"Insecure operation: initialize" when safe-mode is on2010-07-04 12:23kaspernj
summary"Insecure operation: initialize" when safe-mode is on2010-07-04 01:10mutoh
summary"Insecure operation: initialize" when safe-mode is on2010-07-04 00:52mutoh