safe_redirect 0.2.1 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 432d56c2fe2e256b7040f00a82822d9778ef257c
4
- data.tar.gz: 4cd2ccdf44e92e79d613b5ad960b81f486a80009
3
+ metadata.gz: 73595819096734251288a747c73948f27deb1470
4
+ data.tar.gz: f1f7de8ed97ee7a9bf50dc7e67d687e896d19e40
5
5
  SHA512:
6
- metadata.gz: e615e2700b962aae967a8894aef1af26484d5ccf7ba1b4c8868090ea49f426f9007ec0e5950f93dc20cb7624049c3d0129fe963470be00073da1f741de92b023
7
- data.tar.gz: 71d7558aac96b2a794daf3edb895998b8321b4e03fbde1ed182964612171d8252469034d6927ebc483b7a7b04b682466fd16da987c31c3be71321ba27ce9e2fb
6
+ metadata.gz: 645b2a52d54d86d5e4e023e511c85ec1fc3ff7f057f25561bb430ebd18708ba0fe158756100171263eb0eedbb4c3c096e7bff26c7ec9cebab8bf3f647e9f897f
7
+ data.tar.gz: f8fc5d77f0eb82bf925abfcb8d701b690d9f40e007bd8df03f1ae33c89928c6a94b81417d196889d64c21fdd9b4f9ef3ab33fcd49d5d9e9cbb9a2628e73377b1
data/README.md CHANGED
@@ -21,6 +21,14 @@ SafeRedirect.configure do |config|
21
21
  end
22
22
  ```
23
23
 
24
+ We can also use wildcard subdomain on domain whitelists (thanks to [Mike Campbell](https://github.com/mikecmpbll)).
25
+
26
+ ```rb
27
+ SafeRedirect.configure do |config|
28
+ config.domain_whitelists = ['*.foo.org'] # whitelisting foo.org, m.foo.org, www.foo.org, ...
29
+ end
30
+ ```
31
+
24
32
  Add this line to the controllers you wish to secure from open redirection.
25
33
 
26
34
  ```rb
@@ -12,11 +12,20 @@ module SafeRedirect
12
12
  end
13
13
 
14
14
  class Configuration
15
- attr_accessor :default_path, :domain_whitelists
15
+ attr_accessor :default_path
16
+ attr_reader :domain_whitelists
16
17
 
17
18
  def initialize
18
19
  self.default_path = '/'
19
20
  self.domain_whitelists = []
20
21
  end
22
+
23
+ def domain_whitelists=(whitelists)
24
+ if whitelists.any?{ |w| w =~ /\*\z/ }
25
+ raise ArgumentError, "whitelisted domain cannot end with a glob (*)"
26
+ end
27
+
28
+ @domain_whitelists = whitelists
29
+ end
21
30
  end
22
31
  end
@@ -3,17 +3,37 @@ require 'uri'
3
3
  module SafeRedirect
4
4
  def safe_domain?(uri)
5
5
  return true if uri.host.nil? && uri.scheme.nil?
6
- SafeRedirect.configuration.domain_whitelists.include?(uri.host)
6
+ return false if uri.host.nil?
7
+
8
+ SafeRedirect.configuration.domain_whitelists.any? do |domain|
9
+ if domain.include?("*")
10
+ rf = domain.split(/(\*)/).map{ |f| f == "*" ? "\\w*" : Regexp.escape(f) }
11
+ regexp = Regexp.new("\\A#{rf.join}\\z")
12
+
13
+ safe = uri.host.match(regexp)
14
+
15
+ # if domain starts with *. and contains no other wildcards, include the
16
+ # naked domain too (e.g. foo.org when *.foo.org is the whitelist)
17
+ if domain =~ /\A\*\.[^\*]+\z/
18
+ naked_domain = domain.gsub("*.", "")
19
+ safe || uri.host == naked_domain
20
+ else
21
+ safe
22
+ end
23
+ else
24
+ uri.host == domain
25
+ end
26
+ end
7
27
  end
8
28
 
9
29
  def safe_path(path)
10
30
  case path
11
31
  when String
12
32
  clean_path(path)
13
- when Symbol, Hash
14
- path
33
+ when Hash
34
+ sanitize_hash(path)
15
35
  else
16
- SafeRedirect.configuration.default_path
36
+ path
17
37
  end
18
38
  end
19
39
 
@@ -27,8 +47,16 @@ module SafeRedirect
27
47
 
28
48
  def clean_path(path)
29
49
  uri = URI.parse(path)
30
- safe_domain?(uri) ? path : '/'
50
+ safe_domain?(uri) ? path : SafeRedirect.configuration.default_path
31
51
  rescue URI::InvalidURIError
32
- '/'
52
+ SafeRedirect.configuration.default_path
53
+ end
54
+
55
+ def sanitize_hash(hash)
56
+ protocol = hash[:protocol] || 'http'
57
+ host = hash[:host]
58
+ uri = URI.parse("#{protocol}://#{host}")
59
+ hash.delete(:host) unless safe_domain?(uri)
60
+ hash
33
61
  end
34
62
  end
@@ -1,3 +1,3 @@
1
1
  module SafeRedirect
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -6,6 +6,16 @@ module SafeRedirect
6
6
  reset_config
7
7
  end
8
8
 
9
+ it 'errors if you try to end whitelisted domain with glob' do
10
+ config_update = -> do
11
+ SafeRedirect.configure do |config|
12
+ config.domain_whitelists = ["foo.*"]
13
+ end
14
+ end
15
+
16
+ expect(config_update).to raise_error(ArgumentError)
17
+ end
18
+
9
19
  it 'default default_path is /' do
10
20
  expect(SafeRedirect.configuration.default_path).to eq('/')
11
21
  end
@@ -15,8 +15,11 @@ module SafeRedirect
15
15
  '/',
16
16
  '/foobar',
17
17
  'http://www.twitter.com',
18
+ 'http://blah.foo.org',
19
+ 'http://foo.org',
18
20
  :back,
19
- { controller: 'home', action: 'index' }
21
+ ['some', 'object'],
22
+ { controller: 'home', action: 'index' },
20
23
  ]
21
24
 
22
25
  UNSAFE_PATHS = [
@@ -26,6 +29,7 @@ module SafeRedirect
26
29
  "%@%@%@%@%@%@%@%@%@%@evil.com",
27
30
  "https://www-bukalapak.com",
28
31
  "https://www.bukalapak.com\n.evil.com",
32
+ "http://blah.blah.foo.org",
29
33
  ]
30
34
 
31
35
  SAFE_PATHS.each do |path|
@@ -36,10 +40,16 @@ module SafeRedirect
36
40
 
37
41
  UNSAFE_PATHS.each do |path|
38
42
  it "considers #{path} an unsafe path" do
39
- expect(Controller.safe_path(path)).to eq('/')
43
+ expect(Controller.safe_path(path)).to eq(SafeRedirect.configuration.default_path)
40
44
  end
41
45
  end
42
46
 
47
+ it 'filters host, port, and protocol options when hash is passed to safe_path' do
48
+ hash = { host: 'yahoo.com', port: 80, protocol: 'https', controller: 'home', action: 'index' }
49
+ safe_hash = { port: 80, protocol: 'https', controller: 'home', action: 'index' }
50
+ expect(Controller.safe_path(hash)).to eq(safe_hash)
51
+ end
52
+
43
53
  it 'can use redirect_to method with only the target path' do
44
54
  Controller.redirect_to '/'
45
55
  end
data/spec/spec_helper.rb CHANGED
@@ -10,7 +10,7 @@ end
10
10
  def load_config
11
11
  SafeRedirect.configure do |config|
12
12
  config.default_path = '/sdsdkkk'
13
- config.domain_whitelists = ['www.twitter.com', 'www.bukalapak.com']
13
+ config.domain_whitelists = %w{www.twitter.com www.bukalapak.com *.foo.org}
14
14
  end
15
15
  end
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safe_redirect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edwin Tunggawan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-05 00:00:00.000000000 Z
11
+ date: 2016-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -71,3 +71,4 @@ test_files:
71
71
  - spec/lib/safe_redirect/configuration_spec.rb
72
72
  - spec/lib/safe_redirect/safe_redirect_spec.rb
73
73
  - spec/spec_helper.rb
74
+ has_rdoc: