clean_room 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,4 @@
1
1
  require "clean_room/air_lock"
2
- require "clean_room/dsl"
3
2
  require "clean_room/exceptions"
4
3
  require "clean_room/filter"
5
4
  require "clean_room/version"
@@ -1,29 +1,61 @@
1
1
  module CleanRoom
2
2
  module AirLock
3
- class Parameters
3
+ module Parameters
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base.clean_room_rules = {}
7
+ end
8
+
9
+ def params
10
+ @_params ||= HashWithIndifferentAccess.new(CleanRoom::Filter.clean(request.parameters, nested_rules: self.class.clean_room_rules))
11
+ end
12
+
13
+ def params=(val)
14
+ @_params = val.is_a?(Hash) ? HashWithIndifferentAccess.new(CleanRoom::Filter.clean(val, nested_rules: self.class.clean_room_rules)) : val
15
+ end
16
+
4
17
  class << self
5
- def activate
6
- ActionController::Base.send :include, CleanParameters
18
+ def clean_room_rules(rules = {})
19
+ clean_room_rules = rules
7
20
  end
8
21
  end
9
22
  end
10
23
 
11
- class ModelBasedFilter
12
- class << self
13
- def filter(parameters)
14
- # TODO: check the parameter names against the model sanitization rules, when no rules found do a 'normal' sanitization
15
- HashWithIndifferentAccess.new(CleanRoom::Filter.clean(parameters))
24
+ module Model
25
+ def self.included(base)
26
+ base.extend ClassMethods
27
+ base.sanitizable_attributes = {}
28
+
29
+ if base.respond_to? :before_validate
30
+ base.before_validate :sanitize_attributes
16
31
  end
17
32
  end
18
- end
19
33
 
20
- module CleanParameters
21
- def params
22
- @_params ||= ModelBasedFilter.filter(request.parameters)
34
+ def sanitize_attributes
35
+ self.class.sanitizable_attributes.each do |name, rules|
36
+ sanitize_attribute name, rules
37
+ end
23
38
  end
24
39
 
25
- def params=(val)
26
- @_params = val.is_a?(Hash) ? ModelBasedFilter.filter(val) : val
40
+ def sanitize_attribute(name, rules = {})
41
+ current_value = self.send(name)
42
+ cleaned_value = Filter.clean(current_value, rules)
43
+
44
+ raise Exceptions::Contaminated.new("#{name} contained unacceptable data") if rules[:raise] && (current_value != cleaned_value)
45
+ self.send("#{name}=".to_sym, cleaned_value)
46
+ end
47
+
48
+ module ClassMethods
49
+ attr_accessor :sanitizable_attributes
50
+
51
+ def sanitize_attribute(name, rules = {})
52
+ name = name.to_sym
53
+ if instance_methods.include?(name) && instance_methods.include?("#{name}=".to_sym)
54
+ sanitizable_attributes[name] = rules
55
+ else
56
+ raise Exceptions::InvalidAttribute.new("#{self.class} does not respond to '#{name}(=)'")
57
+ end
58
+ end
27
59
  end
28
60
  end
29
61
  end
@@ -7,54 +7,59 @@ module CleanRoom
7
7
  class << self
8
8
  include SanitizeUrl
9
9
 
10
- def clean(dirty_value, options = {})
11
- determine_and_filter(dirty_value, options)
10
+ def clean(dirty_value, rules = {})
11
+ determine_and_filter(dirty_value, rules)
12
12
  end
13
13
 
14
14
  private
15
15
 
16
- def determine_and_filter(dirty_value, options)
16
+ def determine_and_filter(dirty_value, rules)
17
+ nested_rules = rules[:nested_rules] || {}
17
18
 
18
19
  case dirty_value
19
20
  when Array
20
- dirty_value.map{ |dv| determine_and_filter(dv, options) }
21
+ dirty_value.map{ |dv| determine_and_filter(dv, rules) }
21
22
  when Hash
22
- Hash[dirty_value.map {|k,dv| [determine_and_filter(k, allow: (k.is_a?(Symbol) ? :symbol : :string)),determine_and_filter(dv, options)]}]
23
+ Hash[dirty_value.map {|k,dv| [determine_and_filter(k, allow: (k.is_a?(Symbol) ? :symbol : :string)),determine_and_filter(dv, nested_rules[k] ? nested_rules[k] : rules)]}]
23
24
  when Fixnum
24
25
  dirty_value
25
26
  when Symbol
26
- filter(dirty_value, options).to_sym
27
+ filter(dirty_value, rule: :symbol)
27
28
  when FalseClass
28
29
  false
29
30
  when NilClass
30
31
  nil
31
32
  else
32
- filter(dirty_value, options)
33
+ filter(dirty_value, rules)
33
34
  end
34
35
  end
35
36
 
36
- def filter(dirty_value, options)
37
+ def filter(dirty_value, rules)
37
38
  dirty_value = dirty_value.to_s
38
- case (options[:allow] || :plain_text)
39
+ intermediate_value = case (rules[:rule] || :plain_text)
39
40
  when :html
40
- Sanitize.clean(dirty_value, Sanitize::Config::RELAXED)
41
+ sql_injection(Sanitize.clean(dirty_value, Sanitize::Config::RELAXED))
41
42
  when :simple_html
42
- Sanitize.clean(dirty_value, Sanitize::Config::BASIC)
43
+ sql_injection(Sanitize.clean(dirty_value, Sanitize::Config::BASIC))
43
44
  when :strict
44
- regex = /[^#{options[:character_class] || "a-zA-Z0-9 "}]/
45
+ regex = /[^#{rules[:character_class] || "a-zA-Z0-9 "}]/
45
46
  Sanitize.clean(dirty_value).gsub(regex, "")
46
47
  when :url
47
- sanitize_url(dirty_value)
48
+ sql_injection(sanitize_url(dirty_value))
48
49
  when :symbol
49
- Sanitize.clean(dirty_value).gsub(/[^a-zA-Z0-9]/, "").to_sym
50
+ sql_injection(Sanitize.clean(dirty_value)).gsub(/[^a-zA-Z0-9]/, "").to_sym
50
51
  when :fixnum
51
52
  Sanitize.clean(dirty_value).gsub(/[^0-9]\.\,/, "").gsub(",",".").to_i
52
53
  when :float
53
54
  Sanitize.clean(dirty_value).gsub(/[^0-9\.\,]/, "").gsub(",",".").to_f
54
55
  else
55
- Sanitize.clean(dirty_value)
56
+ sql_injection(Sanitize.clean(dirty_value))
56
57
  end
57
58
  end
59
+
60
+ def sql_injection(dirty_value)
61
+ dirty_value.gsub(/(\'|\-\-|\#)[\s;\(\)]*(AND|OR|SELECT|DROP|INSERT|UPDATE|DELETE|UNION).*/, "")
62
+ end
58
63
  end
59
64
  end
60
- end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module CleanRoom
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -4,11 +4,11 @@ class CleanRoomTest < MiniTest::Unit::TestCase
4
4
  def test_can_be_included
5
5
 
6
6
  test_class = Class.new do
7
- include CleanRoom::DSL
7
+ include CleanRoom::AirLock::Model
8
8
  end
9
9
 
10
10
  test_class = Class.new do
11
- include CleanRoom::DSL
11
+ include CleanRoom::AirLock::Model
12
12
  attr_accessor :field1
13
13
 
14
14
  sanitize_attribute :field1
@@ -16,7 +16,7 @@ class CleanRoomTest < MiniTest::Unit::TestCase
16
16
 
17
17
  assert_raises CleanRoom::Exceptions::InvalidAttribute do
18
18
  test_class = Class.new do
19
- include CleanRoom::DSL
19
+ include CleanRoom::AirLock::Model
20
20
 
21
21
  sanitize_attribute :field1
22
22
  end
@@ -38,8 +38,17 @@ class CleanRoomTest < MiniTest::Unit::TestCase
38
38
  assert_equal [{"test1" => "test3"},"test2"], CleanRoom::Filter.clean([{"<b>test1</b>" => "<b>test3</b>"},"<b>test2</b>"])
39
39
  assert_equal [{test1: "test3"},"test2"], CleanRoom::Filter.clean([{:"<b>te * st1</b>" => "<b>test3</b>"},"<b>test2</b>"])
40
40
  assert_equal ["123.", "456.3", "789.8"], CleanRoom::Filter.clean(["<b>123.</b>","456.3", 789.8])
41
- assert_equal [123, 456, 789], CleanRoom::Filter.clean(["<b>123.</b>","456.3", 789.8], allow: :fixnum)
42
- assert_equal [123.0, 456.3, 789.8], CleanRoom::Filter.clean(["<b>123.</b>","456.3", 789.8], allow: :float)
41
+ assert_equal [123, 456, 789], CleanRoom::Filter.clean(["<b>123.</b>","456.3", 789.8], rule: :fixnum)
42
+ assert_equal [123.0, 456.3, 789.8], CleanRoom::Filter.clean(["<b>123.</b>","456.3", 789.8], rule: :float)
43
+
44
+ # SQL injection
45
+ assert_equal "test", CleanRoom::Filter.clean("test' ; DROP TABLE ")
46
+ assert_equal "test", CleanRoom::Filter.clean("test'DROP TABLE `sdfdsf`")
47
+ assert_equal "", CleanRoom::Filter.clean("'DROP TABLE `sdfdsf`")
48
+
49
+ # nested rules
50
+ assert_equal({"test" => {"integer" => "4324.1"}}, CleanRoom::Filter.clean({"test" => {"integer" => "4324.1"}}))
51
+ assert_equal({"test" => {"integer" => 4324}}, CleanRoom::Filter.clean({"test" => {"integer" => "4324.1"}}, nested_rules: {"integer" => {rule: :fixnum}}))
43
52
  end
44
53
 
45
54
  def attribute_test(field, value_in, value_out)
@@ -51,15 +60,15 @@ class CleanRoomTest < MiniTest::Unit::TestCase
51
60
 
52
61
  def object_generator
53
62
  test_class = Class.new do
54
- include CleanRoom::DSL
63
+ include CleanRoom::AirLock::Model
55
64
  attr_accessor :normal, :strict, :very_strict, :simple_html, :html, :url
56
65
 
57
66
  sanitize_attribute :normal
58
- sanitize_attribute :strict, allow: :strict
59
- sanitize_attribute :very_strict, allow: :strict, character_class: "a-z"
60
- sanitize_attribute :simple_html, allow: :simple_html
61
- sanitize_attribute :html, allow: :html
62
- sanitize_attribute :url, allow: :url
67
+ sanitize_attribute :strict, rule: :strict
68
+ sanitize_attribute :very_strict, rule: :strict, character_class: "a-z"
69
+ sanitize_attribute :simple_html, rule: :simple_html
70
+ sanitize_attribute :html, rule: :html
71
+ sanitize_attribute :url, rule: :url
63
72
  end
64
73
 
65
74
  test_class.new
@@ -72,7 +81,7 @@ class CleanRoomTest < MiniTest::Unit::TestCase
72
81
  def self.before_validate(method_name)
73
82
  puts method_name
74
83
  end
75
- include CleanRoom::DSL
84
+ include CleanRoom::AirLock::Model
76
85
  end
77
86
  end
78
87
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clean_room
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-19 00:00:00.000000000 Z
12
+ date: 2012-06-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sanitize
16
- requirement: &70156494356660 !ruby/object:Gem::Requirement
16
+ requirement: &70210935928440 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.0.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70156494356660
24
+ version_requirements: *70210935928440
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sanitize-url
27
- requirement: &70156494356120 !ruby/object:Gem::Requirement
27
+ requirement: &70210935927900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.1.4
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70156494356120
35
+ version_requirements: *70210935927900
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: pry
38
- requirement: &70156494355660 !ruby/object:Gem::Requirement
38
+ requirement: &70210935927440 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70156494355660
46
+ version_requirements: *70210935927440
47
47
  description: Work in progress, this will be a generic attribute sanitizer which can
48
48
  be used for sanitizing models and other objects holding data
49
49
  email:
@@ -60,7 +60,6 @@ files:
60
60
  - clean_room.gemspec
61
61
  - lib/clean_room.rb
62
62
  - lib/clean_room/air_lock.rb
63
- - lib/clean_room/dsl.rb
64
63
  - lib/clean_room/exceptions.rb
65
64
  - lib/clean_room/filter.rb
66
65
  - lib/clean_room/version.rb
@@ -1,40 +0,0 @@
1
- module CleanRoom
2
- module DSL
3
-
4
- def self.included(base)
5
- base.extend ClassMethods
6
- base.sanitizable_attributes = {}
7
-
8
- if base.respond_to? :before_validate
9
- base.before_validate :sanitize_attributes
10
- end
11
- end
12
-
13
- def sanitize_attributes
14
- self.class.sanitizable_attributes.each do |name, options|
15
- sanitize_attribute name, options
16
- end
17
- end
18
-
19
- def sanitize_attribute(name, options = {})
20
- current_value = self.send(name)
21
- cleaned_value = Filter.clean(current_value, options)
22
-
23
- raise Exceptions::Contaminated.new("#{name} contained unacceptable data") if options[:raise] && (current_value != cleaned_value)
24
- self.send("#{name}=".to_sym, cleaned_value)
25
- end
26
-
27
- module ClassMethods
28
- attr_accessor :sanitizable_attributes
29
-
30
- def sanitize_attribute(name, options = {})
31
- name = name.to_sym
32
- if instance_methods.include?(name) && instance_methods.include?("#{name}=".to_sym)
33
- sanitizable_attributes[name] = options
34
- else
35
- raise Exceptions::InvalidAttribute.new("#{self.class} does not respond to '#{name}(=)'")
36
- end
37
- end
38
- end
39
- end
40
- end