rack-protection 0.1.0

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.

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: []