inquisition 0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,54 @@
1
+ require 'html5'
2
+ require 'html5lib_sanitize'
3
+
4
+ # == Introduction
5
+ #
6
+ # Inquisition will escape html included in specified attributes to
7
+ # eliminate xss-style attacks.
8
+ module Inquisition
9
+ def self.included(klass)
10
+ klass.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ def sanitize_attribute(*attributes)
15
+ sanitize_attribute_reader(*attributes)
16
+ sanitize_attribute_writer(*attributes)
17
+ end
18
+
19
+ def sanitize_attribute_reader(*attributes)
20
+ write_inheritable_attribute(:cleansed_attr_readers, attributes)
21
+ class_inheritable_reader(:cleansed_attr_readers)
22
+
23
+ define_method(:read_attribute_with_cleansing) do |attribute|
24
+ value = read_attribute_without_cleansing(attribute)
25
+ if cleansed_attr_readers.include?(attribute.to_sym) && !value.blank?
26
+ HTML5libSanitize.sanitize_html(value)
27
+ else
28
+ value
29
+ end
30
+ end
31
+ alias_method_chain :read_attribute, :cleansing
32
+
33
+ attributes.each { |attr| define_method(attr.to_sym) { read_attribute(attr.to_sym) } }
34
+ end
35
+
36
+ def sanitize_attribute_writer(*attributes)
37
+ write_inheritable_attribute(:cleansed_attr_writers, attributes)
38
+ class_inheritable_reader(:cleansed_attr_writers)
39
+
40
+ define_method(:write_attribute_with_cleansing) do |attribute, value|
41
+ if cleansed_attr_writers.include?(attribute.to_sym) && !value.blank?
42
+ value = HTML5libSanitize.sanitize_html(value)
43
+ end
44
+
45
+ write_attribute_without_cleansing(attribute, value)
46
+ end
47
+ alias_method_chain :write_attribute, :cleansing
48
+ end
49
+ end #Class Methods
50
+ end #Inquisition
51
+
52
+ class Object
53
+ include Inquisition
54
+ end
@@ -0,0 +1,50 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class InquisitionTest < Test::Unit::TestCase
4
+ context "a fine Whisky" do
5
+ setup do
6
+ @whisky = Whisky.new(:name => "<script>alert('Cragganmore')</script>",
7
+ :origin => "<SCRIPT SRC=http://ha.ckers.org/xss.js>Scotland</SCRIPT>", :abv => 42,
8
+ :description => %Q['';!--"<XSS>=&{()}a buttery scotch])
9
+ end
10
+
11
+ should "have heresy removed from name" do
12
+ assert_equal "&lt;script&gt;alert('Cragganmore')&lt;/script&gt;", @whisky.name
13
+ end
14
+
15
+ should "remove already-ingrained heresey" do
16
+ @whisky.instance_variable_set(:@attributes, "name" => "<script>alert('Cragganmore')</script>")
17
+ assert_equal "&lt;script&gt;alert('Cragganmore')&lt;/script&gt;", @whisky.name
18
+ end
19
+
20
+ should "cleanse heresy before setting" do
21
+ @whisky.name = "<script>alert('Cragganmore')</script>"
22
+ private_name = @whisky.attributes["name"]
23
+
24
+ assert_equal "&lt;script&gt;alert('Cragganmore')&lt;/script&gt;", private_name
25
+ end
26
+
27
+ should "not cleanse fields not targeted for cleansing" do
28
+ assert_equal "<SCRIPT SRC=http://ha.ckers.org/xss.js>Scotland</SCRIPT>", @whisky.origin
29
+ end
30
+
31
+ should "not cleanse and set fields not targeted for cleansing" do
32
+ @whisky.origin = "<SCRIPT SRC=http://ha.ckers.org/xss.js>Scotland</SCRIPT>"
33
+ private_origin = @whisky.attributes["origin"]
34
+ assert_equal "<SCRIPT SRC=http://ha.ckers.org/xss.js>Scotland</SCRIPT>", @whisky.origin
35
+ end
36
+
37
+ should "not show pain for setting blank attributes" do
38
+ @whisky.origin = nil
39
+ @whisky.name = nil
40
+ assert_equal nil, @whisky.origin
41
+ assert_equal nil, @whisky.name
42
+ end
43
+
44
+ should "not show pain for getting blank attributes" do
45
+ @whisky.update_attributes(:origin => nil, :name => nil)
46
+ assert_equal nil, @whisky.origin
47
+ assert_equal nil, @whisky.name
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,29 @@
1
+ ActiveRecord::Base.establish_connection :adapter => 'sqlite3', :database => File.join(File.dirname(__FILE__), 'test.db')
2
+
3
+ class CreateSchema < ActiveRecord::Migration
4
+ def self.up
5
+ create_table :whiskies, :force => true do |t|
6
+ t.string :name, :origin, :description
7
+ t.integer :abv
8
+ end
9
+ create_table :animals, :force => true do |t|
10
+ t.string :name, :noise
11
+ end
12
+ end
13
+ end
14
+
15
+ CreateSchema.suppress_messages { CreateSchema.migrate(:up) }
16
+
17
+ class Animal < ActiveRecord::Base
18
+ def bark
19
+ "#{noise.capitalize}! #{noise.capitalize}!"
20
+ end
21
+ end
22
+
23
+ class Whisky < ActiveRecord::Base
24
+ sanitize_attribute :name, :description
25
+
26
+ def drink
27
+ "You quaffed #{description}"
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ require 'benchmark'
2
+ require File.join(File.dirname(__FILE__), 'test_helper')
3
+
4
+ @whisky = Whisky.new({})
5
+ Benchmark.bmbm do |x|
6
+ x.report("normal") do
7
+ 1_000.times do
8
+ @whisky.origin = "<script>foo</script>"
9
+ @whisky.instance_variable_set(:@origin, "<script>foo</script>")
10
+ @whisky.origin
11
+ end
12
+ end
13
+ x.report("cleansed") do
14
+ 1_000.times do
15
+ @whisky.name = "<script>foo</script>"
16
+ @whisky.instance_variable_set(:@name, "<script>foo</script>")
17
+ @whisky.name
18
+ end
19
+ end
20
+ x.report("writer only") do
21
+ 1_000.times do @whisky.name = "<script>foo</script>" end
22
+ end
23
+ x.report("reader only") do
24
+ 1_000.times do
25
+ @whisky.instance_variable_set(:@name, "<script>foo</script>")
26
+ @whisky.name = "<script>foo</script>"
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'activerecord'
6
+ require 'activesupport'
7
+ require 'shoulda'
8
+ require 'inquisition'
9
+ require 'models'
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inquisition
3
+ version: !ruby/object:Gem::Version
4
+ version: "0.2"
5
+ platform: ruby
6
+ authors:
7
+ - toothrot
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-06 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: html5
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.10.0
24
+ version:
25
+ description:
26
+ email: scissorjammer@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - LICENSE
34
+ files:
35
+ - VERSION.yml
36
+ - README.rdoc
37
+ - lib/inquisition.rb
38
+ - lib/html5lib_sanitize.rb
39
+ - test/inquisition_test.rb
40
+ - test/performance.rb
41
+ - test/models.rb
42
+ - test/test_helper.rb
43
+ - Rakefile
44
+ - LICENSE
45
+ has_rdoc: true
46
+ homepage: http://github.com/thumblemonks/inquisition
47
+ licenses: []
48
+
49
+ post_install_message: Choosy heretics choose Thumble Monks.
50
+ rdoc_options:
51
+ - --inline-source
52
+ - --charset=UTF-8
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ requirements: []
68
+
69
+ rubyforge_project:
70
+ rubygems_version: 1.3.5
71
+ signing_key:
72
+ specification_version: 2
73
+ summary: Inquisition is a fancy way to protect your ActiveRecord attributes from XSS
74
+ test_files: []
75
+