rails_xss 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/rails_xss.rb +3 -0
- data/test/active_record_helper_test.rb +74 -0
- data/test/asset_tag_helper_test.rb +49 -0
- data/test/caching_test.rb +43 -0
- data/test/date_helper_test.rb +29 -0
- data/test/deprecated_output_safety_test.rb +112 -0
- data/test/erb_util_test.rb +36 -0
- data/test/form_helper_test.rb +1447 -0
- data/test/form_tag_helper_test.rb +354 -0
- data/test/helper.rb +10 -0
- data/test/output_safety_test.rb +115 -0
- data/test/rails_xss_test.rb +23 -0
- data/test/test_helper.rb +5 -0
- data/test/test_rails_xss.rb +7 -0
- data/test/text_helper_test.rb +17 -0
- metadata +97 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 joloudov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= rails_xss
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 joloudov. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "rails_xss"
|
8
|
+
gem.summary = %Q{A plugin for rails 2.3 apps which switches the default to escape by default}
|
9
|
+
gem.description = %Q{This plugin replaces the default ERB template handlers with erubis, and switches the behaviour to escape by default rather than requiring you to escape. This is consistent with the behaviour in Rails 3.0.}
|
10
|
+
gem.email = "joloudov@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/joloudov/rails_xss"
|
12
|
+
gem.authors = ["joloudov"]
|
13
|
+
gem.add_development_dependency "erubis", ">= 2.6.5"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
Jeweler::GemcutterTasks.new
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake/testtask'
|
22
|
+
Rake::TestTask.new(:test) do |test|
|
23
|
+
test.libs << 'lib' << 'test'
|
24
|
+
test.pattern = 'test/**/test_*.rb'
|
25
|
+
test.verbose = true
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
require 'rcov/rcovtask'
|
30
|
+
Rcov::RcovTask.new do |test|
|
31
|
+
test.libs << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
rescue LoadError
|
36
|
+
task :rcov do
|
37
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
task :test => :check_dependencies
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "rails_xss #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/rails_xss.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ActiveRecordHelperTest < ActionView::TestCase
|
4
|
+
silence_warnings do
|
5
|
+
Post = Struct.new("Post", :title, :author_name, :body, :secret, :written_on)
|
6
|
+
Post.class_eval do
|
7
|
+
alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
|
8
|
+
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
|
9
|
+
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup_post
|
14
|
+
@post = Post.new
|
15
|
+
def @post.errors
|
16
|
+
Class.new {
|
17
|
+
def on(field)
|
18
|
+
case field.to_s
|
19
|
+
when "author_name"
|
20
|
+
"can't be empty"
|
21
|
+
when "body"
|
22
|
+
true
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
def empty?() false end
|
28
|
+
def count() 1 end
|
29
|
+
def full_messages() [ "Author name can't be empty" ] end
|
30
|
+
}.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def @post.new_record?() true end
|
34
|
+
def @post.to_param() nil end
|
35
|
+
|
36
|
+
def @post.column_for_attribute(attr_name)
|
37
|
+
Post.content_columns.select { |column| column.name == attr_name }.first
|
38
|
+
end
|
39
|
+
|
40
|
+
silence_warnings do
|
41
|
+
def Post.content_columns() [ Column.new(:string, "title", "Title"), Column.new(:text, "body", "Body") ] end
|
42
|
+
end
|
43
|
+
|
44
|
+
@post.title = "Hello World"
|
45
|
+
@post.author_name = ""
|
46
|
+
@post.body = "Back to the hill and over it again!"
|
47
|
+
@post.secret = 1
|
48
|
+
@post.written_on = Date.new(2004, 6, 15)
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup
|
52
|
+
setup_post
|
53
|
+
|
54
|
+
@response = ActionController::TestResponse.new
|
55
|
+
|
56
|
+
@controller = Object.new
|
57
|
+
def @controller.url_for(options)
|
58
|
+
options = options.symbolize_keys
|
59
|
+
|
60
|
+
[options[:action], options[:id].to_param].compact.join('/')
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_text_field_with_errors_is_safe
|
65
|
+
assert text_field("post", "author_name").html_safe?
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_text_field_with_errors
|
69
|
+
assert_dom_equal(
|
70
|
+
%(<div class="fieldWithErrors"><input id="post_author_name" name="post[author_name]" size="30" type="text" value="" /></div>),
|
71
|
+
text_field("post", "author_name")
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class AssetTagHelperTest < ActionView::TestCase
|
4
|
+
def setup
|
5
|
+
@controller = Class.new do
|
6
|
+
attr_accessor :request
|
7
|
+
def url_for(*args) "http://www.example.com" end
|
8
|
+
end.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_auto_discovery_link_tag
|
12
|
+
assert_dom_equal(%(<link href="http://www.example.com" rel="Not so alternate" title="ATOM" type="application/atom+xml" />),
|
13
|
+
auto_discovery_link_tag(:atom, {}, {:rel => "Not so alternate"}))
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_javascript_include_tag_with_blank_asset_id
|
17
|
+
ENV["RAILS_ASSET_ID"] = ""
|
18
|
+
assert_dom_equal(%(<script src="/javascripts/test.js" type="text/javascript"></script>\n<script src="/javascripts/prototype.js" type="text/javascript"></script>\n<script src="/javascripts/effects.js" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js" type="text/javascript"></script>\n<script src="/javascripts/controls.js" type="text/javascript"></script>\n<script src="/javascripts/application.js" type="text/javascript"></script>),
|
19
|
+
javascript_include_tag("test", :defaults))
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_javascript_include_tag_with_given_asset_id
|
23
|
+
ENV["RAILS_ASSET_ID"] = "1"
|
24
|
+
assert_dom_equal(%(<script src="/javascripts/prototype.js?1" type="text/javascript"></script>\n<script src="/javascripts/effects.js?1" type="text/javascript"></script>\n<script src="/javascripts/dragdrop.js?1" type="text/javascript"></script>\n<script src="/javascripts/controls.js?1" type="text/javascript"></script>\n<script src="/javascripts/application.js?1" type="text/javascript"></script>),
|
25
|
+
javascript_include_tag(:defaults))
|
26
|
+
ENV["RAILS_ASSET_ID"] = ""
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_javascript_include_tag_is_html_safe
|
30
|
+
assert javascript_include_tag(:defaults).html_safe?
|
31
|
+
assert javascript_include_tag("prototype").html_safe?
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_stylesheet_link_tag
|
35
|
+
assert_dom_equal(%(<link href="http://www.example.com/styles/style.css" media="screen" rel="stylesheet" type="text/css" />),
|
36
|
+
stylesheet_link_tag("http://www.example.com/styles/style"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_stylesheet_link_tag_is_html_safe
|
40
|
+
assert stylesheet_link_tag('dir/file').html_safe?
|
41
|
+
assert stylesheet_link_tag('dir/other/file', 'dir/file2').html_safe?
|
42
|
+
assert stylesheet_tag('dir/file', {}).html_safe?
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_image_tag
|
46
|
+
assert_dom_equal(%(<img alt="Mouse" onmouseover="this.src='/images/mouse_over.png'" onmouseout="this.src='/images/mouse.png'" src="/images/mouse.png" />),
|
47
|
+
image_tag("mouse.png", :mouseover => image_path("mouse_over.png")))
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
CACHE_DIR = 'test_cache'
|
4
|
+
# Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
|
5
|
+
FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
|
6
|
+
ActionController::Base.page_cache_directory = FILE_STORE_PATH
|
7
|
+
ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
|
8
|
+
|
9
|
+
class FragmentCachingTestController < ActionController::Base
|
10
|
+
def some_action; end;
|
11
|
+
end
|
12
|
+
|
13
|
+
class FragmentCachingTest < ActionController::TestCase
|
14
|
+
def setup
|
15
|
+
ActionController::Base.perform_caching = true
|
16
|
+
@store = ActiveSupport::Cache::MemoryStore.new
|
17
|
+
ActionController::Base.cache_store = @store
|
18
|
+
@controller = FragmentCachingTestController.new
|
19
|
+
@params = {:controller => 'posts', :action => 'index'}
|
20
|
+
@request = ActionController::TestRequest.new
|
21
|
+
@response = ActionController::TestResponse.new
|
22
|
+
@controller.params = @params
|
23
|
+
@controller.request = @request
|
24
|
+
@controller.response = @response
|
25
|
+
@controller.send(:initialize_current_url)
|
26
|
+
@controller.send(:initialize_template_class, @response)
|
27
|
+
@controller.send(:assign_shortcuts, @request, @response)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_html_safety
|
31
|
+
assert_nil @store.read('views/name')
|
32
|
+
content = 'value'.html_safe
|
33
|
+
assert_equal content, @controller.write_fragment('name', content)
|
34
|
+
|
35
|
+
cached = @store.read('views/name')
|
36
|
+
assert_equal content, cached
|
37
|
+
assert_equal String, cached.class
|
38
|
+
|
39
|
+
html_safe = @controller.read_fragment('name')
|
40
|
+
assert_equal content, html_safe
|
41
|
+
assert html_safe.html_safe?
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DateHelperTest < ActionView::TestCase
|
4
|
+
silence_warnings do
|
5
|
+
Post = Struct.new("Post", :id, :written_on, :updated_at)
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_select_html_safety
|
9
|
+
assert select_day(16).html_safe?
|
10
|
+
assert select_month(8).html_safe?
|
11
|
+
assert select_year(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
|
12
|
+
assert select_minute(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
|
13
|
+
assert select_second(Time.mktime(2003, 8, 16, 8, 4, 18)).html_safe?
|
14
|
+
|
15
|
+
assert select_minute(8, :use_hidden => true).html_safe?
|
16
|
+
assert select_month(8, :prompt => 'Choose month').html_safe?
|
17
|
+
|
18
|
+
assert select_time(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector').html_safe?
|
19
|
+
assert select_date(Time.mktime(2003, 8, 16), :date_separator => " / ", :start_year => 2003, :end_year => 2005, :prefix => "date[first]").html_safe?
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_object_select_html_safety
|
23
|
+
@post = Post.new
|
24
|
+
@post.written_on = Date.new(2004, 6, 15)
|
25
|
+
|
26
|
+
assert date_select("post", "written_on", :default => Time.local(2006, 9, 19, 15, 16, 35), :include_blank => true).html_safe?
|
27
|
+
assert time_select("post", "written_on", :ignore_date => true).html_safe?
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DeprecatedOutputSafetyTest < ActiveSupport::TestCase
|
4
|
+
def setup
|
5
|
+
@string = "hello"
|
6
|
+
end
|
7
|
+
|
8
|
+
test "A string can be marked safe using html_safe!" do
|
9
|
+
assert_deprecated do
|
10
|
+
@string.html_safe!
|
11
|
+
assert @string.html_safe?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test "Marking a string safe returns the string using html_safe!" do
|
16
|
+
assert_deprecated do
|
17
|
+
assert_equal @string, @string.html_safe!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "Adding a safe string to another safe string returns a safe string using html_safe!" do
|
22
|
+
assert_deprecated do
|
23
|
+
@other_string = "other".html_safe!
|
24
|
+
@string.html_safe!
|
25
|
+
@combination = @other_string + @string
|
26
|
+
|
27
|
+
assert_equal "otherhello", @combination
|
28
|
+
assert @combination.html_safe?
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
test "Adding an unsafe string to a safe string returns an unsafe string using html_safe!" do
|
33
|
+
assert_deprecated do
|
34
|
+
@other_string = "other".html_safe!
|
35
|
+
@combination = @other_string + "<foo>"
|
36
|
+
@other_combination = @string + "<foo>"
|
37
|
+
|
38
|
+
assert_equal "other<foo>", @combination
|
39
|
+
assert_equal "hello<foo>", @other_combination
|
40
|
+
|
41
|
+
assert !@combination.html_safe?
|
42
|
+
assert !@other_combination.html_safe?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
test "Concatting safe onto unsafe yields unsafe using html_safe!" do
|
47
|
+
assert_deprecated do
|
48
|
+
@other_string = "other"
|
49
|
+
@string.html_safe!
|
50
|
+
|
51
|
+
@other_string.concat(@string)
|
52
|
+
assert !@other_string.html_safe?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
test "Concatting unsafe onto safe yields unsafe using html_safe!" do
|
57
|
+
assert_deprecated do
|
58
|
+
@other_string = "other".html_safe!
|
59
|
+
string = @other_string.concat("<foo>")
|
60
|
+
assert_equal "other<foo>", string
|
61
|
+
assert !string.html_safe?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
test "Concatting safe onto safe yields safe using html_safe!" do
|
66
|
+
assert_deprecated do
|
67
|
+
@other_string = "other".html_safe!
|
68
|
+
@string.html_safe!
|
69
|
+
|
70
|
+
@other_string.concat(@string)
|
71
|
+
assert @other_string.html_safe?
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
test "Concatting safe onto unsafe with << yields unsafe using html_safe!" do
|
76
|
+
assert_deprecated do
|
77
|
+
@other_string = "other"
|
78
|
+
@string.html_safe!
|
79
|
+
|
80
|
+
@other_string << @string
|
81
|
+
assert !@other_string.html_safe?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
test "Concatting unsafe onto safe with << yields unsafe using html_safe!" do
|
86
|
+
assert_deprecated do
|
87
|
+
@other_string = "other".html_safe!
|
88
|
+
string = @other_string << "<foo>"
|
89
|
+
assert_equal "other<foo>", string
|
90
|
+
assert !string.html_safe?
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
test "Concatting safe onto safe with << yields safe using html_safe!" do
|
95
|
+
assert_deprecated do
|
96
|
+
@other_string = "other".html_safe!
|
97
|
+
@string.html_safe!
|
98
|
+
|
99
|
+
@other_string << @string
|
100
|
+
assert @other_string.html_safe?
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
test "Concatting a fixnum to safe always yields safe using html_safe!" do
|
105
|
+
assert_deprecated do
|
106
|
+
@string.html_safe!
|
107
|
+
@string.concat(13)
|
108
|
+
assert_equal "hello".concat(13), @string
|
109
|
+
assert @string.html_safe?
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|