rack-protection 0.1.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack-protection might be problematic. Click here for more details.

@@ -0,0 +1,5 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe Rack::Protection do
4
+ it_behaves_like "any rack application"
5
+ end
@@ -0,0 +1,31 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe Rack::Protection::RemoteReferrer do
4
+ it_behaves_like "any rack application"
5
+
6
+ it "accepts post requests with no referrer" do
7
+ post('/').should be_ok
8
+ end
9
+
10
+ it "does not accept post requests with no referrer if allow_empty_referrer is false" do
11
+ mock_app do
12
+ use Rack::Protection::RemoteReferrer, :allow_empty_referrer => false
13
+ run DummyApp
14
+ end
15
+ post('/').should_not be_ok
16
+ end
17
+
18
+ it "should allow post request with a relative referrer" do
19
+ post('/', {}, 'HTTP_REFERER' => '/').should be_ok
20
+ end
21
+
22
+ it "accepts post requests with the same host in the referrer" do
23
+ post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.com')
24
+ last_response.should be_ok
25
+ end
26
+
27
+ it "denies post requests with a remote referrer" do
28
+ post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.org')
29
+ last_response.should_not be_ok
30
+ end
31
+ end
@@ -0,0 +1,42 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe Rack::Protection::RemoteToken do
4
+ it_behaves_like "any rack application"
5
+
6
+ it "accepts post requests with no referrer" do
7
+ post('/').should be_ok
8
+ end
9
+
10
+ it "accepts post requests with a local referrer" do
11
+ post('/', {}, 'HTTP_REFERER' => '/').should be_ok
12
+ end
13
+
14
+ it "denies post requests with a remote referrer and no token" do
15
+ post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.org')
16
+ last_response.should_not be_ok
17
+ end
18
+
19
+ it "accepts post requests with a remote referrer and correct X-CSRF-Token header" do
20
+ post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.org',
21
+ 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "a")
22
+ last_response.should be_ok
23
+ end
24
+
25
+ it "denies post requests with a remote referrer and wrong X-CSRF-Token header" do
26
+ post('/', {}, 'HTTP_REFERER' => 'http://example.com/foo', 'HTTP_HOST' => 'example.org',
27
+ 'rack.session' => {:csrf => "a"}, 'HTTP_X_CSRF_TOKEN' => "b")
28
+ last_response.should_not be_ok
29
+ end
30
+
31
+ it "accepts post form requests with a remote referrer and correct authenticity_token field" do
32
+ post('/', {"authenticity_token" => "a"}, 'HTTP_REFERER' => 'http://example.com/foo',
33
+ 'HTTP_HOST' => 'example.org', 'rack.session' => {:csrf => "a"})
34
+ last_response.should be_ok
35
+ end
36
+
37
+ it "denies post form requests with a remote referrer and wrong authenticity_token field" do
38
+ post('/', {"authenticity_token" => "a"}, 'HTTP_REFERER' => 'http://example.com/foo',
39
+ 'HTTP_HOST' => 'example.org', 'rack.session' => {:csrf => "b"})
40
+ last_response.should_not be_ok
41
+ end
42
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe Rack::Protection::SessionHijacking do
4
+ it_behaves_like "any rack application"
5
+
6
+ it "accepts a session without changes to tracked parameters" do
7
+ session = {:foo => :bar}
8
+ get '/', {}, 'rack.session' => session
9
+ get '/', {}, 'rack.session' => session
10
+ session[:foo].should == :bar
11
+ end
12
+
13
+ it "denies requests with a changing User-Agent header" do
14
+ session = {:foo => :bar}
15
+ get '/', {}, 'rack.session' => session, 'HTTP_USER_AGENT' => 'a'
16
+ get '/', {}, 'rack.session' => session, 'HTTP_USER_AGENT' => 'b'
17
+ session.should be_empty
18
+ end
19
+
20
+ it "denies requests with a changing Accept-Encoding header" do
21
+ session = {:foo => :bar}
22
+ get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_ENCODING' => 'a'
23
+ get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_ENCODING' => 'b'
24
+ session.should be_empty
25
+ end
26
+
27
+ it "denies requests with a changing Accept-Language header" do
28
+ session = {:foo => :bar}
29
+ get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'a'
30
+ get '/', {}, 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => 'b'
31
+ session.should be_empty
32
+ end
33
+
34
+ it "denies requests with a changing Version header"do
35
+ session = {:foo => :bar}
36
+ get '/', {}, 'rack.session' => session, 'HTTP_VERSION' => '1.0'
37
+ get '/', {}, 'rack.session' => session, 'HTTP_VERSION' => '1.1'
38
+ session.should be_empty
39
+ end
40
+ end
@@ -0,0 +1,157 @@
1
+ require 'rack/protection'
2
+ require 'rack/test'
3
+ require 'forwardable'
4
+ require 'stringio'
5
+
6
+ if defined? Gem.loaded_specs and Gem.loaded_specs.include? 'rack'
7
+ version = Gem.loaded_specs['rack'].version.to_s
8
+ else
9
+ version = Rack.release + '.0'
10
+ end
11
+
12
+ if version == "1.3"
13
+ Rack::Session::Abstract::ID.class_eval do
14
+ private
15
+ def prepare_session(env)
16
+ session_was = env[ENV_SESSION_KEY]
17
+ env[ENV_SESSION_KEY] = SessionHash.new(self, env)
18
+ env[ENV_SESSION_OPTIONS_KEY] = OptionsHash.new(self, env, @default_options)
19
+ env[ENV_SESSION_KEY].merge! session_was if session_was
20
+ end
21
+ end
22
+ end
23
+
24
+ module DummyApp
25
+ def self.call(env)
26
+ Thread.current[:last_env] = env
27
+ [200, {'Content-Type' => 'text/plain'}, ['ok']]
28
+ end
29
+ end
30
+
31
+ module TestHelpers
32
+ extend Forwardable
33
+ def_delegators :last_response, :body, :headers, :status, :errors
34
+ def_delegators :current_session, :env_for
35
+ attr_writer :app
36
+
37
+ def app
38
+ @app || mock_app(DummyApp)
39
+ end
40
+
41
+ def mock_app(app = nil, &block)
42
+ app = block if app.nil? and block.arity == 1
43
+ if app
44
+ klass = described_class
45
+ mock_app do
46
+ use Rack::Head
47
+ use(Rack::Config) { |e| e['rack.session'] ||= {}}
48
+ use klass
49
+ run app
50
+ end
51
+ else
52
+ @app = Rack::Lint.new Rack::Builder.new(&block).to_app
53
+ end
54
+ end
55
+
56
+ def with_headers(headers)
57
+ proc { [200, {'Content-Type' => 'text/plain'}.merge(headers), ['ok']] }
58
+ end
59
+
60
+ def env
61
+ Thread.current[:last_env]
62
+ end
63
+ end
64
+
65
+ # see http://blog.101ideas.cz/posts/pending-examples-via-not-implemented-error-in-rspec.html
66
+ module NotImplementedAsPending
67
+ def self.included(base)
68
+ base.class_eval do
69
+ alias_method :__finish__, :finish
70
+ remove_method :finish
71
+ end
72
+ end
73
+
74
+ def finish(reporter)
75
+ if @exception.is_a?(NotImplementedError)
76
+ from = @exception.backtrace[0]
77
+ message = "#{@exception.message} (from #{from})"
78
+ @pending_declared_in_example = message
79
+ metadata[:pending] = true
80
+ @exception = nil
81
+ end
82
+
83
+ __finish__(reporter)
84
+ end
85
+
86
+ RSpec::Core::Example.send :include, self
87
+ end
88
+
89
+ RSpec.configure do |config|
90
+ config.expect_with :rspec, :stdlib
91
+ config.include Rack::Test::Methods
92
+ config.include TestHelpers
93
+ end
94
+
95
+ shared_examples_for 'any rack application' do
96
+ it "should not interfere with normal get requests" do
97
+ get('/').should be_ok
98
+ body.should == 'ok'
99
+ end
100
+
101
+ it "should not interfere with normal head requests" do
102
+ head('/').should be_ok
103
+ end
104
+
105
+ it 'should not leak changes to env' do
106
+ klass = described_class
107
+ detector = Struct.new(:app)
108
+
109
+ detector.send(:define_method, :call) do |env|
110
+ was = env.dup
111
+ res = app.call(env)
112
+ was.each do |k,v|
113
+ next if env[k] == v
114
+ fail "env[#{k.inspect}] changed from #{v.inspect} to #{env[k].inspect}"
115
+ end
116
+ res
117
+ end
118
+
119
+ mock_app do
120
+ use Rack::Head
121
+ use(Rack::Config) { |e| e['rack.session'] ||= {}}
122
+ use detector
123
+ use klass
124
+ run DummyApp
125
+ end
126
+
127
+ get('/..', :foo => '<bar>').should be_ok
128
+ end
129
+
130
+ it 'allows passing on values in env' do
131
+ klass = described_class
132
+ detector = Struct.new(:app)
133
+ changer = Struct.new(:app)
134
+
135
+ detector.send(:define_method, :call) do |env|
136
+ res = app.call(env)
137
+ env['foo.bar'].should == 42
138
+ res
139
+ end
140
+
141
+ changer.send(:define_method, :call) do |env|
142
+ env['foo.bar'] = 42
143
+ app.call(env)
144
+ end
145
+
146
+ mock_app do
147
+ use Rack::Head
148
+ use(Rack::Config) { |e| e['rack.session'] ||= {}}
149
+ use detector
150
+ use klass
151
+ use changer
152
+ run DummyApp
153
+ end
154
+
155
+ get('/').should be_ok
156
+ end
157
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../spec_helper.rb', __FILE__)
2
+
3
+ describe Rack::Protection::XSSHeader do
4
+ it_behaves_like "any rack application"
5
+
6
+ it 'should set the X-XSS-Protection' do
7
+ get('/').headers["X-XSS-Protection"].should == "1; mode=block"
8
+ end
9
+
10
+ it 'should allow changing the protection mode' do
11
+ # I have no clue what other modes are available
12
+ mock_app do
13
+ use Rack::Protection::XSSHeader, :xss_mode => :foo
14
+ run DummyApp
15
+ end
16
+
17
+ get('/').headers["X-XSS-Protection"].should == "1; mode=foo"
18
+ end
19
+
20
+ it 'should not override the header if already set' do
21
+ mock_app with_headers("X-XSS-Protection" => "0")
22
+ get('/').headers["X-XSS-Protection"].should == "0"
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-protection
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Konstantin Haase
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-20 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: &2153646760 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2153646760
25
+ - !ruby/object:Gem::Dependency
26
+ name: escape_utils
27
+ requirement: &2153646220 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2153646220
36
+ - !ruby/object:Gem::Dependency
37
+ name: rack-test
38
+ requirement: &2153645700 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *2153645700
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &2153645080 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *2153645080
58
+ description: You should use protection!
59
+ email:
60
+ - konstantin.mailinglists@googlemail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - License
66
+ - README.md
67
+ - Rakefile
68
+ - lib/rack-protection.rb
69
+ - lib/rack/protection.rb
70
+ - lib/rack/protection/authenticity_token.rb
71
+ - lib/rack/protection/base.rb
72
+ - lib/rack/protection/escaped_params.rb
73
+ - lib/rack/protection/form_token.rb
74
+ - lib/rack/protection/frame_options.rb
75
+ - lib/rack/protection/ip_spoofing.rb
76
+ - lib/rack/protection/json_csrf.rb
77
+ - lib/rack/protection/path_traversal.rb
78
+ - lib/rack/protection/remote_referrer.rb
79
+ - lib/rack/protection/remote_token.rb
80
+ - lib/rack/protection/session_hijacking.rb
81
+ - lib/rack/protection/version.rb
82
+ - lib/rack/protection/xss_header.rb
83
+ - rack-protection.gemspec
84
+ - spec/authenticity_token_spec.rb
85
+ - spec/escaped_params_spec.rb
86
+ - spec/form_token_spec.rb
87
+ - spec/frame_options_spec.rb
88
+ - spec/ip_spoofing_spec.rb
89
+ - spec/json_csrf_spec.rb
90
+ - spec/path_traversal_spec.rb
91
+ - spec/protection_spec.rb
92
+ - spec/remote_referrer_spec.rb
93
+ - spec/remote_token_spec.rb
94
+ - spec/session_hijacking_spec.rb
95
+ - spec/spec_helper.rb
96
+ - spec/xss_header_spec.rb
97
+ homepage: http://github.com/rkh/rack-protection
98
+ licenses: []
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ! '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ requirements: []
116
+ rubyforge_project:
117
+ rubygems_version: 1.8.5
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: You should use protection!
121
+ test_files: []