inquisition 0.2

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.
@@ -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
+