cookiefilter 1.0.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +33 -0
- data/lib/cookiefilter.rb +172 -0
- data/lib/cookiefilter/errors.rb +15 -0
- data/lib/cookiefilter/rules.rb +22 -0
- data/lib/cookiefilter/utils.rb +66 -0
- data/lib/cookiefilter/validator.rb +69 -0
- data/lib/cookiefilter/version.rb +3 -0
- data/lib/tasks/cookiefilter_tasks.rake +4 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 661342b71d73b5849ad89f06d046a5fceec8d011
|
4
|
+
data.tar.gz: 0eae238747a3364560084e7e3173bf2d5de0a3b6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b01b281d624b06c45693b36fa0e363336ec1be8d65b0cda7cf3b0c33735cc8db149fe9b3d2650a770df0c089f0ead44bfe9996c81a63074bb2922f47012b1790
|
7
|
+
data.tar.gz: 92aaac588a58bacbf263c5e80d3b3cd1abe827df47387c32c5e79173e750bfbbbec93ac35badc01c8504e790f876ddb83a3dc3e48bccf48181c2241d5ef45357
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2017 Stefan Wallin
|
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.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
[](https://travis-ci.org/StefanWallin/cookiefilter-rails)
|
2
|
+
# Cookiefilter
|
3
|
+
Cookie Filter uses a developer defined safelist of allowed cookies and their
|
4
|
+
values to filter cookies that are not allowed by the safelist configuration.
|
5
|
+
This gem filters both incoming cookies from the browser and what cookies can
|
6
|
+
be set from rails. I want to thank MittMedia DMU for allowing me to open source
|
7
|
+
this piece of code. We are always looking for new developers ;).
|
8
|
+
|
9
|
+
## When would I use this?
|
10
|
+
- If you want to be on top of what data is allowed to be passed to your server.
|
11
|
+
- If you have third party code executing on your first party domain(ads) that set
|
12
|
+
arbitrary cookies.
|
13
|
+
- If your amount and size of cookies can run out of control and exceed the http
|
14
|
+
header limit of 8186 bytes. (At which time certain cloud providers simply
|
15
|
+
interpret that request as an attack and serves back a white page)
|
16
|
+
- If you're already running mod_security or similar web firewalls and need to
|
17
|
+
complement with cookie filtering.
|
18
|
+
|
19
|
+
## Performance
|
20
|
+
Measurment has shown that this filter adds less than 1ms per request.
|
21
|
+
|
22
|
+
This library has been in production on sites with 5 million weekly pageviews
|
23
|
+
for 2 years before being packaged as a gem and open sourced.
|
24
|
+
|
25
|
+
*This gem package has not been tested in production.*
|
26
|
+
|
27
|
+
## Getting started
|
28
|
+
Install the [cookiefilter](http://rubygems.org/StefanWallin/cookiefilter) gem;
|
29
|
+
or add it to your Gemfile with bundler:
|
30
|
+
|
31
|
+
Add this line to your application's `Gemfile`:
|
32
|
+
```ruby
|
33
|
+
gem 'cookiefilter'
|
34
|
+
```
|
35
|
+
|
36
|
+
And then execute:
|
37
|
+
```bash
|
38
|
+
$ bundle install
|
39
|
+
```
|
40
|
+
|
41
|
+
Tell your app to use the Cookiefilter middleware.
|
42
|
+
For Rails 4+ apps:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
# In config/application.rb
|
46
|
+
config.middleware.use Cookiefilter
|
47
|
+
```
|
48
|
+
|
49
|
+
Add a `cookiefilter.rb` file to `config/initializers/`:
|
50
|
+
```ruby
|
51
|
+
# In config/initializers/cookiefilter.rb
|
52
|
+
class Cookiefilter
|
53
|
+
def self.safelist
|
54
|
+
# This is an array of hashes. It serves as a living documentation of our
|
55
|
+
# allowed cookies and their format. Need help with regex? Visit this site:
|
56
|
+
# http://rubular.com/
|
57
|
+
|
58
|
+
# Each hash in the array is per cookie with the following format:
|
59
|
+
# description: Human readable string of what/who this cookie pertains.
|
60
|
+
# key: A regex that matches the name of the cookie or cookies matching
|
61
|
+
# the above description.
|
62
|
+
# value: A regex that validates the content of the cookie, if the regex
|
63
|
+
# is nil, no validation is done.
|
64
|
+
# sacred: This is a boolean indicating that this cookie are not to be
|
65
|
+
# removed to decrease the overall size of cookies per domain.
|
66
|
+
# It will however be removed in second run if no other options
|
67
|
+
# are left.
|
68
|
+
[
|
69
|
+
{
|
70
|
+
description: 'Rails Session Cookie',
|
71
|
+
key: /\Aproject_name_session\z/,
|
72
|
+
value: nil,
|
73
|
+
sacred: true
|
74
|
+
}
|
75
|
+
]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
**Then restart your rails server.**
|
81
|
+
|
82
|
+
Happy filtering!
|
83
|
+
|
84
|
+
## License
|
85
|
+
The gem is available as open source under the terms of the
|
86
|
+
[MIT License](http://opensource.org/licenses/MIT).
|
87
|
+
|
88
|
+
## Contribute
|
89
|
+
All contributions are welcome, issues and PR's.
|
90
|
+
Make sure tests pass by running them like so:
|
91
|
+
```ruby
|
92
|
+
rake test
|
93
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Cookiefilter'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
task default: :test
|
data/lib/cookiefilter.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'cookiefilter/utils'
|
2
|
+
require 'cookiefilter/rules'
|
3
|
+
require 'cookiefilter/errors'
|
4
|
+
require 'cookiefilter/validator'
|
5
|
+
|
6
|
+
class Cookiefilter
|
7
|
+
class << self
|
8
|
+
def filter_request_cookies(http_cookie)
|
9
|
+
# Flag by replacing with cookie emoji(\u{1F36a}) as a token to identify
|
10
|
+
# and invalidate cookies later on in is_valid_cookie!
|
11
|
+
cookies = Cookiefilter::Utils.sanitize_utf8_string(
|
12
|
+
http_cookie,
|
13
|
+
Cookiefilter::Rules::DISALLOWED_CHARS,
|
14
|
+
Cookiefilter::Rules::INVALID_TOKEN
|
15
|
+
)
|
16
|
+
cookies = Cookiefilter::Utils.parse_request_cookies(cookies)
|
17
|
+
delete, keep = Cookiefilter.validate_request_cookies(cookies)
|
18
|
+
header = Cookiefilter::Utils.construct_request_header(keep)
|
19
|
+
{ delete: delete, keep: keep, header: header.strip }
|
20
|
+
end
|
21
|
+
|
22
|
+
def filter_response_cookies(host, response_header, response_cookies)
|
23
|
+
keep, delete1 = response_cookies[:keep], response_cookies[:delete]
|
24
|
+
cookies = Cookiefilter::Utils.parse_set_cookie_header(response_header)
|
25
|
+
set, delete2 = Cookiefilter.validate_response_cookies(cookies)
|
26
|
+
cookies = Cookiefilter.merge_keep_and_set(keep, set)
|
27
|
+
cookies = Cookiefilter.sort_by_size(cookies)
|
28
|
+
keepers, limited = Cookiefilter.maintain_limits(cookies)
|
29
|
+
set = Cookiefilter.filter_out_keepers(keepers)
|
30
|
+
deleted = Cookiefilter.delete_cookies(delete1 + delete2, limited)
|
31
|
+
Cookiefilter::Utils.construct_response_header(host, deleted + set)
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_request_cookies(cookies)
|
35
|
+
cookies_to_keep = cookies.select do |cookie|
|
36
|
+
is_valid_cookie!(cookie)
|
37
|
+
end
|
38
|
+
cookies_to_delete = cookies.reject do |cookie|
|
39
|
+
is_valid_cookie!(cookie)
|
40
|
+
end
|
41
|
+
[cookies_to_delete, cookies_to_keep]
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_response_cookies(cookies)
|
45
|
+
cookies_to_set, cookies_to_delete = [], []
|
46
|
+
cookies.each do |cookie|
|
47
|
+
if is_valid_cookie!(cookie)
|
48
|
+
cookies_to_set << cookie
|
49
|
+
else
|
50
|
+
cookies_to_delete << cookie
|
51
|
+
end
|
52
|
+
end
|
53
|
+
[cookies_to_set, cookies_to_delete]
|
54
|
+
end
|
55
|
+
|
56
|
+
def delete_cookies(blocked, limited)
|
57
|
+
blocked.each do |cookie|
|
58
|
+
delete(cookie)
|
59
|
+
end
|
60
|
+
limited.each do |cookie|
|
61
|
+
delete(cookie)
|
62
|
+
end
|
63
|
+
blocked + limited
|
64
|
+
end
|
65
|
+
|
66
|
+
def delete(cookie)
|
67
|
+
cookie[:options] = ' max-age=0; expires=Thu, 01 Jan 1970 00:00:00 -0000;'
|
68
|
+
cookie[:value] = 'unset'
|
69
|
+
cookie
|
70
|
+
end
|
71
|
+
|
72
|
+
def merge_keep_and_set(keep, set)
|
73
|
+
keep.each do |keeper|
|
74
|
+
keeper[:type] = :keep
|
75
|
+
end
|
76
|
+
set.each do |setter|
|
77
|
+
setter[:type] = :set
|
78
|
+
end
|
79
|
+
return keep + set
|
80
|
+
end
|
81
|
+
|
82
|
+
def maintain_limits(sized_cookies, kept_large = [], limited = [])
|
83
|
+
if Cookiefilter.cookie_size_too_large?(kept_large, sized_cookies)
|
84
|
+
removed = sized_cookies.shift if sized_cookies.count > 0
|
85
|
+
removed = kept_large.shift if removed.nil?
|
86
|
+
if removed[:sacred] && sized_cookies.count > 0
|
87
|
+
kept_large.push(removed)
|
88
|
+
else
|
89
|
+
limited.push(removed)
|
90
|
+
end
|
91
|
+
return Cookiefilter.maintain_limits(sized_cookies, kept_large, limited)
|
92
|
+
else
|
93
|
+
return [kept_large + sized_cookies, limited]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def filter_out_keepers(keepers)
|
98
|
+
keepers.select { |keeper| keeper[:type] == :set }
|
99
|
+
end
|
100
|
+
|
101
|
+
def sort_by_size(cookies)
|
102
|
+
cookies.sort! do |a, b|
|
103
|
+
b[:size] <=> a[:size]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def total_cookie_size(keep, set)
|
108
|
+
@size = 0
|
109
|
+
keep.each do |cookie|
|
110
|
+
@size += cookie[:size]
|
111
|
+
end
|
112
|
+
set.each do |cookie|
|
113
|
+
@size += cookie[:size]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def cookie_size_too_large?(keep, set)
|
118
|
+
Cookiefilter.total_cookie_size(keep, set)
|
119
|
+
@size >= Cookiefilter::Rules::COOKIE_DOMAIN_LIMIT
|
120
|
+
end
|
121
|
+
|
122
|
+
# This method will regex-check both key and value for
|
123
|
+
# this cookie against all safelisted cookies until match
|
124
|
+
# is found.
|
125
|
+
# If a valid match is found, true is returned
|
126
|
+
# Otherwise false is returned.
|
127
|
+
|
128
|
+
def is_valid_cookie!(cookie)
|
129
|
+
return false if "#{cookie[:key]}=#{cookie[:value]}".bytesize > Cookiefilter::Rules::COOKIE_LIMIT
|
130
|
+
return false if /[\u{1F36A}]/.match(cookie[:value])
|
131
|
+
Cookiefilter::Rules::safelist.each do |allowed_cookie|
|
132
|
+
if allowed_cookie[:key].match(cookie[:key])
|
133
|
+
regex = allowed_cookie[:value]
|
134
|
+
|
135
|
+
# Set sacred attribute
|
136
|
+
cookie[:sacred] = allowed_cookie[:sacred]
|
137
|
+
|
138
|
+
# Cookies with nil as value-regex, pass validation.
|
139
|
+
return true if regex.nil?
|
140
|
+
|
141
|
+
return true if regex.match(cookie[:value])
|
142
|
+
|
143
|
+
# Not matching value regex, fail validation.
|
144
|
+
return false
|
145
|
+
end
|
146
|
+
end
|
147
|
+
# Unknown cookie. Log this and fail
|
148
|
+
false
|
149
|
+
end
|
150
|
+
end # end class methods
|
151
|
+
|
152
|
+
def initialize(app)
|
153
|
+
Cookiefilter::Validator.validate_safelist(Cookiefilter::Rules.safelist)
|
154
|
+
@app = app
|
155
|
+
@size = 0
|
156
|
+
end
|
157
|
+
|
158
|
+
# entry point, executes directly after initialize
|
159
|
+
def call(env)
|
160
|
+
result = Cookiefilter.filter_request_cookies(env['HTTP_COOKIE'])
|
161
|
+
env['HTTP_COOKIE'] = result[:header]
|
162
|
+
status, headers, body = @app.call(env)
|
163
|
+
response = Rack::Response.new body, status, headers
|
164
|
+
header = Cookiefilter.filter_response_cookies(
|
165
|
+
env['HTTP_HOST'],
|
166
|
+
response.header['Set-Cookie'],
|
167
|
+
result
|
168
|
+
)
|
169
|
+
response.header['Set-Cookie'] = header
|
170
|
+
response.finish
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Cookiefilter::SafelistMissingError < StandardError
|
2
|
+
def message
|
3
|
+
'Please define your cookie safelist as documented in Readme and then\
|
4
|
+
restart your rails server.'
|
5
|
+
end
|
6
|
+
def backtrace
|
7
|
+
[]
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Cookiefilter::MalformedSafelistError < StandardError
|
12
|
+
def backtrace
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Cookiefilter::Rules
|
2
|
+
COOKIE_DOMAIN_LIMIT = 8186
|
3
|
+
COOKIE_LIMIT = 4093
|
4
|
+
DISALLOWED_CHARS = [
|
5
|
+
"\192", "\193", "\245", "\246", "\247", "\248", "\249",
|
6
|
+
"\250", "\251", "\252", "\253", "\254", "\255"
|
7
|
+
]
|
8
|
+
INVALID_TOKEN = "\u{1F36A}"
|
9
|
+
|
10
|
+
|
11
|
+
def self.method_missing(m, *args, &block)
|
12
|
+
if m.to_sym == :safelist
|
13
|
+
raise Cookiefilter::SafelistMissingError
|
14
|
+
else
|
15
|
+
raise ArgumentError.new("Method `#{m}` doesn't exist.")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.respond_to?(method_name, include_private = false)
|
20
|
+
method_name.to_sym == :safelist || super
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'cookiefilter/errors'
|
2
|
+
|
3
|
+
class Cookiefilter::Utils
|
4
|
+
class << self
|
5
|
+
def sanitize_utf8_string(cookie_string, banned_chars, replace_char)
|
6
|
+
result = ''
|
7
|
+
# blank? can'd handle broken utf-8 characters.
|
8
|
+
return result if cookie_string.nil?
|
9
|
+
cookie_string.each_char do |char|
|
10
|
+
if banned_chars.include? char
|
11
|
+
result << replace_char
|
12
|
+
else
|
13
|
+
result << char
|
14
|
+
end
|
15
|
+
end
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse_request_cookies(cookie_string)
|
20
|
+
cookies = []
|
21
|
+
return cookies if cookie_string.blank?
|
22
|
+
cookie_strings = cookie_string.split(';')
|
23
|
+
cookie_strings.each do |cookie|
|
24
|
+
key, value = cookie.strip.split('=', 2)
|
25
|
+
cookies << { key: key, value: value, size: "#{key}=#{value}; ".bytesize }
|
26
|
+
end
|
27
|
+
cookies
|
28
|
+
end
|
29
|
+
|
30
|
+
def parse_set_cookie_header(header)
|
31
|
+
cookies = []
|
32
|
+
return cookies if header.blank?
|
33
|
+
header_cookies = header.split("\n")
|
34
|
+
header_cookies.each do |cookie|
|
35
|
+
key, rest = cookie.strip.split('=', 2)
|
36
|
+
value, options = rest.strip.split(';', 2)
|
37
|
+
options = '' if options.nil?
|
38
|
+
size = "#{key}=#{value}; ".bytesize
|
39
|
+
cookies << { key: key, value: value, options: options, size: size }
|
40
|
+
end
|
41
|
+
cookies
|
42
|
+
end
|
43
|
+
|
44
|
+
def construct_request_header(cookies_to_keep)
|
45
|
+
http_cookie = ''
|
46
|
+
cookies_to_keep.each do |cookie|
|
47
|
+
http_cookie << "#{cookie[:key]}=#{cookie[:value]}; "
|
48
|
+
end
|
49
|
+
# Chopping last ';' since headers does not expect it.
|
50
|
+
http_cookie.strip.chomp(';')
|
51
|
+
end
|
52
|
+
|
53
|
+
def construct_response_header(host, set)
|
54
|
+
http_cookies = []
|
55
|
+
naked_host = host.sub!(/\Awww\./, '')
|
56
|
+
set.each do |cookie|
|
57
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};#{cookie[:options]}"
|
58
|
+
if cookie[:value] == 'unset'
|
59
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};Domain=.#{naked_host};#{cookie[:options]}"
|
60
|
+
http_cookies << "#{cookie[:key]}=#{cookie[:value]};Domain=www.#{naked_host};#{cookie[:options]}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
http_cookies.join("\n")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Cookiefilter::Validator
|
2
|
+
class << self
|
3
|
+
def validate_safelist(safelist)
|
4
|
+
err = Cookiefilter::MalformedSafelistError
|
5
|
+
Cookiefilter::Validator.validate_array(err, safelist)
|
6
|
+
|
7
|
+
safelist.each_index do |index|
|
8
|
+
obj = safelist[index]
|
9
|
+
Cookiefilter::Validator.validate_hash(err, index, obj)
|
10
|
+
Cookiefilter::Validator.validate_keys(err, index, obj)
|
11
|
+
Cookiefilter::Validator.validate_description(err, index, obj)
|
12
|
+
Cookiefilter::Validator.validate_key(err, index, obj)
|
13
|
+
Cookiefilter::Validator.validate_value(err, index, obj)
|
14
|
+
Cookiefilter::Validator.validate_sacred(err, index, obj)
|
15
|
+
end
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate_array(err, list)
|
20
|
+
raise err, 'safelist method does not return Array' if list.class != Array
|
21
|
+
end
|
22
|
+
|
23
|
+
def validate_hash(err, index, obj)
|
24
|
+
if obj.class != Hash
|
25
|
+
raise err, "safelist child with index #{index}: Is not an Hash Object"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_keys(err, index, obj)
|
30
|
+
%w(description key value sacred).each do |key|
|
31
|
+
unless obj.has_key?(key.to_sym)
|
32
|
+
raise err, "safelist child with index #{index}: Missing key :#{key}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_description(err, index, obj)
|
38
|
+
description = obj[:description]
|
39
|
+
if description.class != String
|
40
|
+
return raise err, "safelist child with index #{index}: ':description' \
|
41
|
+
must be of class String, got #{description.class}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def validate_key(err, index, obj)
|
46
|
+
key = obj[:key]
|
47
|
+
if key.class != Regexp
|
48
|
+
return raise err, "safelist child with index #{index}: ':key' \
|
49
|
+
must be of class Regexp, got #{key.class}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def validate_value(err, index, obj)
|
54
|
+
value = obj[:value]
|
55
|
+
if value.class != Regexp && value.class != NilClass
|
56
|
+
return raise err, "safelist child with index #{index}: ':value' \
|
57
|
+
must be of class Regexp or NilClass, got #{value.class}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_sacred(err, index, obj)
|
62
|
+
sacred = obj[:sacred]
|
63
|
+
if obj[:sacred].class != TrueClass && obj[:sacred].class != FalseClass
|
64
|
+
return raise err, "safelist child with index #{index}: ':sacred' \
|
65
|
+
must be of class TrueClass or FalseClass, got #{sacred.class}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cookiefilter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stefan Wallin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.1.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.1.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faker
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: |-
|
56
|
+
Cookie Filter uses a developer defined whitelist of \
|
57
|
+
allowed cookies and their values to filter cookies that do \
|
58
|
+
not live up to the standard.
|
59
|
+
email:
|
60
|
+
- cookiefilter@stefan-wallin.se
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- MIT-LICENSE
|
66
|
+
- README.md
|
67
|
+
- Rakefile
|
68
|
+
- lib/cookiefilter.rb
|
69
|
+
- lib/cookiefilter/errors.rb
|
70
|
+
- lib/cookiefilter/rules.rb
|
71
|
+
- lib/cookiefilter/utils.rb
|
72
|
+
- lib/cookiefilter/validator.rb
|
73
|
+
- lib/cookiefilter/version.rb
|
74
|
+
- lib/tasks/cookiefilter_tasks.rake
|
75
|
+
homepage: https://github.com/StefanWallin/cookiefilter
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata: {}
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
requirements: []
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.6.13
|
96
|
+
signing_key:
|
97
|
+
specification_version: 4
|
98
|
+
summary: Whitelist your users cookies for your domain.
|
99
|
+
test_files: []
|