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.
- data/LICENSE +20 -0
- data/README.rdoc +28 -0
- data/Rakefile +56 -0
- data/VERSION.yml +4 -0
- data/lib/html5lib_sanitize.rb +2453 -0
- data/lib/inquisition.rb +54 -0
- data/test/inquisition_test.rb +50 -0
- data/test/models.rb +29 -0
- data/test/performance.rb +29 -0
- data/test/test_helper.rb +9 -0
- metadata +75 -0
data/lib/inquisition.rb
ADDED
@@ -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 "<script>alert('Cragganmore')</script>", @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 "<script>alert('Cragganmore')</script>", @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 "<script>alert('Cragganmore')</script>", 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
|
data/test/models.rb
ADDED
@@ -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
|
data/test/performance.rb
ADDED
@@ -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
|
data/test/test_helper.rb
ADDED
@@ -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
|
+
|