4

Question about Rails magic:

I was playing with IRB and the tainted? method, then I just did the following:

>> User.first.attributes.collect { |column, value| [column, value.tainted?] }
=> [["phone", true], ["state", false], ["persistence_token", true], ["last_login_ip", true], ["country", true], ["login_count", false], ["last_request_at", false], ["id", false], ["forname", true], ["current_login_at", false], ["name", true]]

Does anyone know why some of the params are tainted and some are not? And if there is a way to select which column should be tainted?

EDIT:

Thanks for the answers.

@sgtFloyd: I just tried to update manually the country. and here is what's happening:

>> u = User.first
>> u.country = "USA"
=> "USA"
>> u.country.tainted?
=> false
>> u.save
=> true
>> u.country.tainted?
=> false
>> u.reload
>> u.country.tainted?
=> true
>> u.country.class
=> String # it's also string in the database

EDIT 2:

I removed everything inside the User model, and some String columns do not appear tainted whereas some do...

Thanks a lot!

jrichardlai
  • 3,047
  • 4
  • 18
  • 22
  • could you add the value itself? is it false when there is no value, vs true when there is a value? – DGM Mar 15 '12 at 22:12
  • What datatype is your emailing field? All the others that have tainted?==false are numeric (including dates) whereas the tainted ones are strings. It could be something about the way ActiveRecord manages string data, perhaps? – Henry Collingridge Mar 15 '12 at 22:39
  • Yes, true only the string are tainted, but not all ( some of my string columns are not tainted ) ! That's why its weird... – jrichardlai Mar 15 '12 at 23:19
  • **tainted?==true** just means that Ruby considers these fields to be subject to some *external* influence, which is why when you change a field's value, the tainted? property doesn't change (Ruby knows it's only you that's changing it, not some external entity). I can only assume this is to do with something going on down in the ActiveRecord code. Presumably the numerics are considered 'brand new' and therefore untainted. Again, if you just care about whether a field value has changed, you can use **changed?**, and **Object.tainted?** is irrelevant. – Henry Collingridge Mar 16 '12 at 20:29

3 Answers3

3

taint and tainted? are methods of Ruby's Object class. If you're looking to find what objects have been modified in your Rails app, you might be looking for changed?

@customer.email = 'new@email.com'
do_something if @customer.email_changed? 
Henry Collingridge
  • 1,885
  • 2
  • 14
  • 21
2

AFAIK, Rails does not make use of taint, it keeps track of changes, and html_safe conditions, but I have not seen any mention of taint. The ruby docs for taint say it is supposed to be tainted when it comes from external sources, I would guess that has something to do with the sql libraries in use. But without seeing that library itself, I can't guess as to why some are tainted and some aren't.

Running that code on my projects comes up with all false. It likely depends on what version of ruby/rails etc you are running, and since it isn't defined by rails, is probably unsuitable to depend on.

DGM
  • 25,680
  • 6
  • 56
  • 79
2

From Programming Ruby

Any Ruby object derived from some external source (for example, a string read from a file, or an environment variable) is automatically marked as being tainted. If your program uses a tainted object to derive a new object, then that new object will also be tainted...

From your example, columns like last_login_at, password_salt and created_at are created and handled solely internally, without using any user input. phone, email, country etc. are derived from user input, so they're intrinsically untrustworthy.

sgtFloyd
  • 957
  • 9
  • 18
  • Thanks for the answer, I added another example in my post, I dont get why if the data comes from my input it's still tainted. – jrichardlai Mar 15 '12 at 23:15