I was reading about Ruby string methods in the docs and came accross the methods
taint
trust
untaint
I found this link to me informative about tainted
Data in ruby.
http://ruby.about.com/od/advancedruby/a/tainted.htm
"Tainted" objects are those that have come from some type of user input. Either from a file, the keyboard or the network, unless the object is a literal in the program or created by the program directly, it will be tainted. The tainted flag is always there on your objects, all you have to do is check it before you do anything unsafe. If you've confirmed that the data is indeed safe, you can then untaint the object.
taint
and trust
are part of Ruby's security model. In Ruby, each object has a few flags that it carries around with it, two of which are the Trusted flag and the Tainted flag. How these flags are acted on depends on something called the safe level. The safe level is stored in $SAFE
.
Each thread and fiber in a program can have its own safe level. Safe levels range from 0 through 4, with 0 enforcing no security and 4 enforcing so much it should only be used when you're eval
ing code. You can't assign a lower value to $SAFE
than it already has. Also, on UNIX systems where a Ruby script runs as setuid, Ruby automatically sets the safe level to 1.
When a object has it's tainted flag set, that means, roughly, that the object came from an unreliable source and therefore can't be used in sensitive operations. When the safe level is 0, the taint flag is ignored (but still set, you can pay attention to it if you want). There are a few methods related to tainting:
taint
-- Make an object tainted. You can taint an object on all levels with the exception of safe level 4.tainted?
-- Check if an object is tainted.untaint
-- Remove tainting from an object. This can only be used in safe levels 0, 1, and 2.Here's an example from the pragprog pickaxe (source) that shows tainting:
# internal data
# =============
x1 = "a string"
x1.tainted? → false
x2 = x1[2, 4]
x2.tainted? → false
x1 =~ /([a-z])/ → 0
$1.tainted? → false
# external data
# =============
y1 = ENV["HOME"]
y1.tainted? → true
y2 = y1[2, 4]
y2.tainted? → true
y1 =~ /([a-z])/ → 1
$1.tainted? → true
To summarize, you can't use dangerous methods on tainted data. So if you do this in safe level 3, you'd get an error:
eval(gets)
Trust is a lot simpler. Trust has to do with whether the object came from a trusted or untrusted source -- basically, whether it came from anything less than safe level 4, or safe level 4. I'm not sure exactly what effect Ruby's trust has, but take a look here: http://www.ruby-forum.com/topic/1887006 .
Here are some more resources: http://phrogz.net/ProgrammingRuby/taint.html -- Some great stuff on safe levels, but I think it's from 1.8 -- there is an updated version for 1.9, just only in the printed version of the book.
http://www.ruby-forum.com/topic/79295 -- On whether safe is safe enough.
taint
and trust
each set a flag that the object carries around with it everywhere. The only difference that I can tell (from ruby-doc.org) is that some method calls behave differently when given tainted objects whereas trust seems to be entirely up to the programmer to interpret.
The main purpose of tainting is to flag user input as potentially dangerous e.g. a dynamically loaded script or CGI form data. You then implement sanitizing methods that make sure objects are safe and untaint them before using them elsewhere in your code.
See also "What's the purpose of tainting Ruby objects?".