roda 3.74.0 → 3.75.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 +4 -4
- data/CHANGELOG +4 -0
- data/doc/release_notes/3.75.0.txt +19 -0
- data/lib/roda/plugins/cookie_flags.rb +157 -0
- data/lib/roda/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ebdbc5b5707ba21044b5f4c83445ff8fca6a3925488c72a5176cc662c2ad15b
|
4
|
+
data.tar.gz: ac528e50bfe1e778b5b4d32d16d12e117e87dc55b2f7cad1170b682e2f979586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7d13975d6c7705f1d7b184f27430320e1dfd5fea96e532f119f86b4c09fdb5c7e460107033d8d099c6ef8da354a514289981163d74cdb293b89074299a57eda
|
7
|
+
data.tar.gz: d16c1b3a2edd401a73b104bf9458fcb865e441f4de649dcfcb8144eb3102abcd6abee741ecbbbf1cad3b13d8efca7260d7785b7e5a2505f29541ad001de9b1e4
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
= 3.75.0 (2023-12-14)
|
2
|
+
|
3
|
+
* Add cookie_flags plugin, for overriding, warning, or raising for incorrect cookie flags (jeremyevans)
|
4
|
+
|
1
5
|
= 3.74.0 (2023-11-13)
|
2
6
|
|
3
7
|
* Add redirect_http_to_https plugin, helping to ensure future requests from the browser are submitted via HTTPS (jeremyevans)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A cookie_flags plugin has been added, for overriding, warning, or
|
4
|
+
raising for incorrect cookie flags. The plugin by default checks
|
5
|
+
whether the secure, httponly, and samesite=strict flags are set.
|
6
|
+
The default behavior is to add the appropriate flags if they are
|
7
|
+
not set, and change the samesite flag to strict if it is set to
|
8
|
+
something else. You can configure the flag checking behavior
|
9
|
+
via the :httponly, :same_site, and :secure options.
|
10
|
+
|
11
|
+
You can configure the action the plugin takes via the :action option.
|
12
|
+
The default action is to modify the flags, but the :action option can
|
13
|
+
be set to :raise, :warn, or :warn_and_modify to override the behavior.
|
14
|
+
|
15
|
+
The recommended way to use the plugin is to use it during testing,
|
16
|
+
and specify action: :raise, so you can catch places where cookies
|
17
|
+
are set with the wrong flags. Then you can fix those places to
|
18
|
+
use the correct flags, which is better than relying on the plugin
|
19
|
+
at runtime in production to fix incorrect flags.
|
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
class Roda
|
5
|
+
module RodaPlugins
|
6
|
+
# The cookie_flags plugin allows users to force specific cookie flags for
|
7
|
+
# all cookies set by the application. It can also be used to warn or
|
8
|
+
# raise for unexpected cookie flags.
|
9
|
+
#
|
10
|
+
# The cookie_flags plugin deals with the following cookie flags:
|
11
|
+
#
|
12
|
+
# httponly :: Disallows access to the cookie from client-side scripts.
|
13
|
+
# samesite :: Restricts to which domains the cookie is sent.
|
14
|
+
# secure :: Instructs the browser to only transmit the cookie over HTTPS.
|
15
|
+
#
|
16
|
+
# This plugin ships in secure-by-default mode, where it enforces
|
17
|
+
# secure, httponly, samesite=strict cookies. You can disable enforcing
|
18
|
+
# specific flags using the following options:
|
19
|
+
#
|
20
|
+
# :httponly :: Set to false to not enforce httponly flag.
|
21
|
+
# :same_site :: Set to symbol or string to enforce a different samesite
|
22
|
+
# setting, or false to not enforce a specific samesite setting.
|
23
|
+
# :secure :: Set to false to not enforce secure flag.
|
24
|
+
#
|
25
|
+
# For example, to enforce secure cookies and enforce samesite=lax, but not enforce
|
26
|
+
# an httponly flag:
|
27
|
+
#
|
28
|
+
# plugin :cookie_flags, httponly: false, same_site: 'lax'
|
29
|
+
#
|
30
|
+
# In general, overriding cookie flags using this plugin should be considered a
|
31
|
+
# stop-gap solution. Instead of overriding cookie flags, it's better to fix
|
32
|
+
# whatever is setting the cookie flags incorrectly. You can use the :action
|
33
|
+
# option to modify the behavior:
|
34
|
+
#
|
35
|
+
# # Issue warnings when modifying cookie flags
|
36
|
+
# plugin :cookie_flags, action: :warn_and_modify
|
37
|
+
#
|
38
|
+
# # Issue warnings for incorrect cookie flags without modifying cookie flags
|
39
|
+
# plugin :cookie_flags, action: :warn
|
40
|
+
#
|
41
|
+
# # Raise errors for incorrect cookie flags
|
42
|
+
# plugin :cookie_flags, action: :raise
|
43
|
+
#
|
44
|
+
# The recommended way to use the plugin is to use it only during testing with
|
45
|
+
# <tt>action: :raise</tt>. Then as long as you have fully covering tests, you
|
46
|
+
# can be sure the cookies set by your application use the correct flags.
|
47
|
+
#
|
48
|
+
# Note that this plugin only affects cookies set by the application, and does not
|
49
|
+
# affect cookies set by middleware the application is using.
|
50
|
+
module CookieFlags
|
51
|
+
# :nocov:
|
52
|
+
MATCH_METH = RUBY_VERSION >= '2.4' ? :match? : :match
|
53
|
+
# :nocov:
|
54
|
+
private_constant :MATCH_METH
|
55
|
+
|
56
|
+
DEFAULTS = {:secure=>true, :httponly=>true, :same_site=>'strict', :action=>:modify}.freeze
|
57
|
+
private_constant :DEFAULTS
|
58
|
+
|
59
|
+
# Error class raised for action: :raise when incorrect cookie flags are used.
|
60
|
+
class Error < RodaError
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.configure(app, opts=OPTS)
|
64
|
+
previous = app.opts[:cookie_flags] || DEFAULTS
|
65
|
+
opts = app.opts[:cookie_flags] = previous.merge(opts)
|
66
|
+
|
67
|
+
case opts[:same_site]
|
68
|
+
when String, Symbol
|
69
|
+
opts[:same_site] = opts[:same_site].to_s.downcase.freeze
|
70
|
+
opts[:same_site_string] = "; samesite=#{opts[:same_site]}".freeze
|
71
|
+
opts[:secure] = true if opts[:same_site] == 'none'
|
72
|
+
end
|
73
|
+
|
74
|
+
opts.freeze
|
75
|
+
end
|
76
|
+
|
77
|
+
module InstanceMethods
|
78
|
+
private
|
79
|
+
|
80
|
+
def _handle_cookie_flags_array(cookies)
|
81
|
+
opts = self.class.opts[:cookie_flags]
|
82
|
+
needs_secure = opts[:secure]
|
83
|
+
needs_httponly = opts[:httponly]
|
84
|
+
if needs_same_site = opts[:same_site]
|
85
|
+
same_site_string = opts[:same_site_string]
|
86
|
+
same_site_regexp = /;\s*samesite\s*=\s*(\S+)\s*(?:\z|;)/i
|
87
|
+
end
|
88
|
+
action = opts[:action]
|
89
|
+
|
90
|
+
cookies.map do |cookie|
|
91
|
+
if needs_secure
|
92
|
+
add_secure = !/;\s*secure\s*(?:\z|;)/i.send(MATCH_METH, cookie)
|
93
|
+
end
|
94
|
+
|
95
|
+
if needs_httponly
|
96
|
+
add_httponly = !/;\s*httponly\s*(?:\z|;)/i.send(MATCH_METH, cookie)
|
97
|
+
end
|
98
|
+
|
99
|
+
if needs_same_site
|
100
|
+
has_same_site = same_site_regexp.match(cookie)
|
101
|
+
unless add_same_site = !has_same_site
|
102
|
+
update_same_site = needs_same_site != has_same_site[1].downcase
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
next cookie unless add_secure || add_httponly || add_same_site || update_same_site
|
107
|
+
|
108
|
+
case action
|
109
|
+
when :raise, :warn, :warn_and_modify
|
110
|
+
message = "Response contains cookie with unexpected flags: #{cookie.inspect}." \
|
111
|
+
"Expecting the following cookie flags: "\
|
112
|
+
"#{'secure ' if add_secure}#{'httponly ' if add_httponly}#{same_site_string[2..-1] if add_same_site || update_same_site}"
|
113
|
+
|
114
|
+
if action == :raise
|
115
|
+
raise Error, message
|
116
|
+
else
|
117
|
+
warn(message)
|
118
|
+
next cookie if action == :warn
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
if update_same_site
|
123
|
+
cookie = cookie.gsub(same_site_regexp, same_site_string)
|
124
|
+
else
|
125
|
+
cookie = cookie.dup
|
126
|
+
cookie << same_site_string if add_same_site
|
127
|
+
end
|
128
|
+
|
129
|
+
cookie << '; secure' if add_secure
|
130
|
+
cookie << '; httponly' if add_httponly
|
131
|
+
|
132
|
+
cookie
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
if Rack.release >= '3'
|
137
|
+
def _handle_cookie_flags(cookies)
|
138
|
+
cookies = [cookies] if cookies.is_a?(String)
|
139
|
+
_handle_cookie_flags_array(cookies)
|
140
|
+
end
|
141
|
+
else
|
142
|
+
def _handle_cookie_flags(cookie_string)
|
143
|
+
_handle_cookie_flags_array(cookie_string.split("\n")).join("\n")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Handle cookie flags in response
|
148
|
+
def _roda_after_85__cookie_flags(res)
|
149
|
+
return unless res && (headers = res[1]) && (value = headers[RodaResponseHeaders::SET_COOKIE])
|
150
|
+
headers[RodaResponseHeaders::SET_COOKIE] = _handle_cookie_flags(value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
register_plugin(:cookie_flags, CookieFlags)
|
156
|
+
end
|
157
|
+
end
|
data/lib/roda/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.75.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -248,6 +248,7 @@ extra_rdoc_files:
|
|
248
248
|
- doc/release_notes/3.72.0.txt
|
249
249
|
- doc/release_notes/3.73.0.txt
|
250
250
|
- doc/release_notes/3.74.0.txt
|
251
|
+
- doc/release_notes/3.75.0.txt
|
251
252
|
- doc/release_notes/3.8.0.txt
|
252
253
|
- doc/release_notes/3.9.0.txt
|
253
254
|
files:
|
@@ -329,6 +330,7 @@ files:
|
|
329
330
|
- doc/release_notes/3.72.0.txt
|
330
331
|
- doc/release_notes/3.73.0.txt
|
331
332
|
- doc/release_notes/3.74.0.txt
|
333
|
+
- doc/release_notes/3.75.0.txt
|
332
334
|
- doc/release_notes/3.8.0.txt
|
333
335
|
- doc/release_notes/3.9.0.txt
|
334
336
|
- lib/roda.rb
|
@@ -357,6 +359,7 @@ files:
|
|
357
359
|
- lib/roda/plugins/common_logger.rb
|
358
360
|
- lib/roda/plugins/content_for.rb
|
359
361
|
- lib/roda/plugins/content_security_policy.rb
|
362
|
+
- lib/roda/plugins/cookie_flags.rb
|
360
363
|
- lib/roda/plugins/cookies.rb
|
361
364
|
- lib/roda/plugins/csrf.rb
|
362
365
|
- lib/roda/plugins/custom_block_results.rb
|