Changeset 156
- Timestamp:
- 02/11/08 20:38:28 (7 months ago)
- Files:
-
- incubator/sentinel/init.rb (modified) (1 diff)
- incubator/sentinel/lib/relevance/sentinel/active_record.rb (modified) (1 diff)
- incubator/sentinel/README (modified) (1 diff)
- incubator/sentinel/test/fixtures (added)
- incubator/sentinel/test/fixtures/schema.rb (added)
- incubator/sentinel/test/relevance/sentinel/active_record_test.rb (modified) (1 diff)
- incubator/sentinel/test/relevance/sentinel_test.rb (modified) (1 diff)
- incubator/sentinel/test/test_helper.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
incubator/sentinel/init.rb
r155 r156 1 1 # Include hook code here 2 require 'relevance/sentinel' incubator/sentinel/lib/relevance/sentinel/active_record.rb
r155 r156 2 2 def self.sanitize_all_finds 3 3 ActiveRecord::Base.class_eval do 4 include Relevance::Sentinel::ActiveRecord 5 alias_method_chain :find, :sentinel_sanitize 6 def sentinel_sanitize(*args, &blk) 7 args.last = Relevance::Sentinel::ActiveRecord.sanitize_find_options(args.last) if Hash === args.last 8 find_without_sentinel_sanitize(*args, &blk) 4 extend Relevance::Sentinel::ActiveRecord 5 class << self 6 def find_with_sentinel_sanitize(*args, &blk) 7 args.push(sanitize_find_options!(args.pop)) if Hash === args.last 8 find_without_sentinel_sanitize(*args, &blk) 9 end 10 alias_method_chain :find, :sentinel_sanitize 9 11 end 10 12 end incubator/sentinel/README
r155 r156 1 Sentinel 2 ======== 1 Sentinel 0.1 2 ============ 3 3 4 Introduction goes here. 4 Rails programmers know to be careful with :conditions clauses to avoid 5 SQL injection attacks. For example: 6 7 # Bad: 8 find(:first, :conditions => "user_name = '#{user_name}' AND password = '#{password}'") 9 # Better: 10 find(:first, :conditions => { :user_name => user_name, :password => password }) 11 12 However, there is a lot of code that gives less care to the other options on 13 ActiveRecord::Base#find. For example, consider the following misuses of ":limit": 14 15 Asset.find(:all, :limit => "10 into outfile '/tmp/outfile'") 16 Asset.find(:all, :limit => "10 procedure someproc()") 17 18 You probably don't want users to be able to create files on the server or 19 execute arbitrary stored procedures! Sentinel aims to prevent these misuses. 20 21 Usage 22 ============ 23 24 There are two ways to use Sentinel: 25 26 1. You can mix in Relevance::Sentinel::ActiveRecord and call 27 sanitize_find_options! on an options hash before passing it to ActiveRecord. 28 29 2. You can activate Sentinel for all finds by calling 30 Relevance::Sentinel::ActiveRecord.sanitize_all_finds 31 If you rely on passing complex SQL to find options, this option may 32 not work for you, as Sentinel may reject some complex (but safe) SQL. 33 34 Warning! 35 ============ 36 Sentinel is not production ready. At this time it is probably broken in 37 both directions, i.e. 38 39 * Sentinel may allow accept some bad inputs 40 * Sentinel may reject some good inputs 41 42 Sentinel is under active development. If you have a case that is not covered, 43 please contribute a patch or at least a broken test to stu@thinkrelevance.com. 5 44 6 45 7 Example 8 ======= 46 TODO 47 ============ 48 * cover every possible option to ActiveRecord::Base#find. 49 * investigate patching ActiveRecord at a different level than find 50 * should sanitization throw exceptions, neuter bad data, or some of both? 51 * test other databases 9 52 10 Example goes here. 11 12 13 Copyright (c) 2008 [name of plugin creator], released under the MIT license 53 Copyright (c) 2008 Relevance, Inc., released under the MIT license incubator/sentinel/test/relevance/sentinel/active_record_test.rb
r155 r156 35 35 end 36 36 37 Relevance::Sentinel::ActiveRecord.sanitize_all_finds 38 39 describe "ActiveRecord find method" do 40 # this test might behave different for other db layers than MySQL... 41 it "does not sanitize :limit" do 42 lambda { 43 Person.find_without_sentinel_sanitize(:all, :limit => "invalid value") 44 }.should.raise(ActiveRecord::StatementInvalid) 45 end 46 end 47 37 48 describe "Relevance::Sentinel::ActiveRecord ActiveRecord integration" do 49 it "protects all finds" do 50 lambda { 51 Person.find_with_sentinel_sanitize(:all, :limit => "invalid value") 52 }.should.raise(ArgumentError) 53 end 38 54 55 it "delegates through to find" do 56 Person.expects(:find_without_sentinel_sanitize).with(:all, :limit => 10) 57 Person.find_with_sentinel_sanitize(:all, :limit => 10) 58 end 39 59 end incubator/sentinel/test/relevance/sentinel_test.rb
r155 r156 1 1 require File.join(File.dirname(__FILE__), "..", "test_helper.rb") 2 2 3 describe "Relevance::Sentinel" do4 5 endincubator/sentinel/test/test_helper.rb
r155 r156 5 5 require 'mocha' 6 6 require 'ruby-debug' 7 require 'relevance/sentinel'8 7 9 8 gem 'activerecord' 10 9 require 'active_record' 11 12 db_config_file = File.join(File.dirname(__FILE__) + '/config/database.yml') 10 db_config_file = File.join(basedir + '/config/database.yml') 13 11 ActiveRecord::Base.configurations = YAML.load_file(db_config_file) 14 12 ActiveRecord::Base.establish_connection('sentinel_test') 13 require File.join(basedir, "fixtures/schema.rb") 15 14 15 require 'relevance/sentinel'
