From: gwelch925@... Date: 2015-08-14T05:59:39+00:00 Subject: [ruby-core:70380] [Ruby trunk - Bug #11442] Bug: Symbols should be taintable. Issue #11442 has been updated by Grant Welch. Subject changed from String#to_sym returns an untainted Symbol. to Bug: Symbols should be taintable. After some additional testing, I've come to the conclusion that Symbols cannot be tainted (example below). I expect this may be due to the fact that symbols have a dual meaning. 1) They are a String because we want them to be human-readable, and 2) they are a Number so they can be quickly retrieved. It's understandable that Numbers don't carry a taint flag, but since Symbols have practical use cases in place of Strings, they should carry over 'tainted?' when coming from String#to_sym. ~~~ proc {$SAFE=3;(a = :foo).tainted?}.call # => false ~~~ ~~~ a = :foo a.taint a.tainted? # => false ~~~ Note: I have come to the conclusion that the behavior is as expected, but I am leaving the issue as a Bug (rather than a Feature) because the logic that Symbols should be un-taintable is flawed. ---------------------------------------- Bug #11442: Bug: Symbols should be taintable. https://bugs.ruby-lang.org/issues/11442#change-53783 * Author: Grant Welch * Status: Open * Priority: Normal * Assignee: Yukihiro Matsumoto * ruby -v: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux] * Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN ---------------------------------------- Subject: String#to_sym returns an untainted Symbol. Taint checking can be subverted by a String if a tainted String is converted to a Symbol. After experiencing this issue, I went looking for unit tests in ruby/ruby, ruby/mspec, and ruby/rubyspec, but was unable to come up with any tests that focus on $SAFE. If they exist, could you point out where they are located? If not, I'd be willing to write some. --------------------------------------------------------------- # Proof of Concept: ~~~ # cat untainted_sym.rb #!/usr/bin/env ruby -w print 'Enter a string? ' a = gets puts "a: #{a.inspect}, tainted? #{a.tainted?}" b = a.to_sym puts "b: #{b.inspect}, tainted? #{b.tainted?}" c = b.to_s puts "c: #{c.inspect}, tainted? #{c.tainted?}" puts "a == c: #{a == c}" ~~~ # Output: ~~~ $ ruby -w untainted_sym.rb Enter a string? foobar a: "foobar\n", tainted? true b: :"foobar\n", tainted? false c: "foobar\n", tainted? false a == c: true ~~~ # Sample Workaround: (to provide the expected SecurityError) ~~~ # safe_level, 1 or 2 # uncertain_var, some variable that could, potentially, be tainted untainted_sym = proc { $SAFE=safe_level; eval("'#{uncertain_var}'") && uncertain_var.to_sym}.call # => Symbol for untainted var, SecurityError for tainted var ~~~ # Versions Tested: * ruby 1.9.3p551 (2014-11-13 revision 48407) [x86_64-linux] * ruby 2.0.0p645 (2015-04-13 revision 50299) [x86_64-linux] * ruby 2.1.6p336 (2015-04-13 revision 50298) [x86_64-linux] * ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux] -- https://bugs.ruby-lang.org/