studio-engine 0.91.1 → 0.91.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 +4 -4
- data/CHANGELOG.md +16 -0
- data/app/controllers/concerns/studio/link_consumption.rb +2 -2
- data/app/models/studio/site_identity.rb +2 -2
- data/lib/studio/booking.rb +5 -3
- data/lib/studio/link_token.rb +5 -3
- data/lib/studio/local_path.rb +28 -0
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 270fe9f569b46f626593afa13ce7cf925f23e783541f76e06d6a465d06837278
|
|
4
|
+
data.tar.gz: 40f8eefcec2e4eee79baa652da57aca97a6b49b794fab4fb3ca166dd3f27333d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ae76749cc7fd004b7a93b2108d0af84e21645b1801f50be212d0d5346d503f8d3355fea7c3350ab74a059edbcfc4d60163b245ae34c7f4c68a249e1115b5588f
|
|
7
|
+
data.tar.gz: 683b4be2cb7b68b01c167db0e3973aefe9b0dd133b8ddb200f5d76f387d19dc1bff6378204fc0e34c4716e1b08bd9e0d08b4f572e40d3b2c15d007e97a6ba48e
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.91.2 — 2026-10-06
|
|
8
|
+
|
|
9
|
+
### Security
|
|
10
|
+
|
|
11
|
+
- **A return path beginning `/\` no longer redirects off-site.** Browsers read
|
|
12
|
+
`/\evil.com` as `//evil.com`, and the engine's path sanitizers checked only for
|
|
13
|
+
one leading `/` and not two, so a magic link minted with `return_to=/\evil.com`
|
|
14
|
+
sent the visitor to another host after sign-in (or, under Rails'
|
|
15
|
+
`raise_on_open_redirects`, answered 500). One predicate, `Studio::LocalPath.local?`,
|
|
16
|
+
now holds the rule (one leading `/`, no backslash, no control character) and
|
|
17
|
+
every engine site uses it: `Studio::LinkToken.sanitize_path`, the link-consume
|
|
18
|
+
redirect, `Studio::Booking.local_path?`, and the link-preview fallback image.
|
|
19
|
+
Each site keeps its fallback: a refused return path lands on the default page.
|
|
20
|
+
Consumers that sanitize a return path themselves should call
|
|
21
|
+
`Studio::LocalPath.local?` instead of a bare `start_with?("/")` check.
|
|
22
|
+
|
|
7
23
|
## 0.91.1 — 2026-10-06
|
|
8
24
|
|
|
9
25
|
### Fixed
|
|
@@ -163,10 +163,10 @@ module Studio
|
|
|
163
163
|
user.update!(email_verified_at: Time.current)
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
# Only
|
|
166
|
+
# Only local paths survive (Studio::LocalPath); everything else collapses to nil.
|
|
167
167
|
def safe_path(path)
|
|
168
168
|
p = path.to_s
|
|
169
|
-
|
|
169
|
+
Studio::LocalPath.local?(p) ? p : nil
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
172
|
end
|
|
@@ -183,7 +183,7 @@ module Studio
|
|
|
183
183
|
def static_image
|
|
184
184
|
path = Studio.link_preview_fallback_image.to_s
|
|
185
185
|
return nil if path.empty?
|
|
186
|
-
return path unless
|
|
186
|
+
return path unless Studio::LocalPath.local?(path)
|
|
187
187
|
|
|
188
188
|
@static_files ||= Concurrent::Map.new
|
|
189
189
|
present = @static_files.compute_if_absent(path) do
|
|
@@ -203,7 +203,7 @@ module Studio
|
|
|
203
203
|
# per path like static_image.
|
|
204
204
|
def static_image_dimensions
|
|
205
205
|
path = static_image
|
|
206
|
-
return nil
|
|
206
|
+
return nil unless Studio::LocalPath.local?(path)
|
|
207
207
|
|
|
208
208
|
@static_dimensions ||= Concurrent::Map.new
|
|
209
209
|
dims = @static_dimensions.compute_if_absent(path) do
|
data/lib/studio/booking.rb
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
#
|
|
12
12
|
# `gv=true` is what makes Google serve the embeddable page, so the frame and the
|
|
13
13
|
# popup add it; the "open the booking page" link does not.
|
|
14
|
+
require_relative "local_path"
|
|
15
|
+
|
|
14
16
|
module Studio
|
|
15
17
|
module Booking
|
|
16
18
|
EMBED_PARAM = "gv=true"
|
|
@@ -116,10 +118,10 @@ module Studio
|
|
|
116
118
|
# hrefs (the footer's booking links, `studio_booking_link`). It begins with
|
|
117
119
|
# one "/" and carries no control character. That refuses a scheme
|
|
118
120
|
# ("javascript:", "https:") and a protocol-relative "//host", which a browser
|
|
119
|
-
# reads as another site.
|
|
121
|
+
# reads as another site. The rule is Studio::LocalPath's, shared with every
|
|
122
|
+
# other engine path sanitizer.
|
|
120
123
|
def local_path?(path)
|
|
121
|
-
|
|
122
|
-
string.start_with?("/") && !string.start_with?("//") && !string.match?(/[\x00-\x1f\x7f\\]/)
|
|
124
|
+
Studio::LocalPath.local?(path)
|
|
123
125
|
end
|
|
124
126
|
|
|
125
127
|
# Studio.booking_path: nil, a local path, or a callable receiving the view.
|
data/lib/studio/link_token.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "securerandom"
|
|
4
|
+
require_relative "local_path"
|
|
4
5
|
|
|
5
6
|
module Studio
|
|
6
7
|
# Pure-Ruby helpers behind the Studio::Link model — token minting, the kind
|
|
@@ -53,12 +54,13 @@ module Studio
|
|
|
53
54
|
email.to_s.strip.downcase
|
|
54
55
|
end
|
|
55
56
|
|
|
56
|
-
# Only
|
|
57
|
+
# Only local paths survive (Studio::LocalPath: one leading "/", no
|
|
58
|
+
# backslash, no control character); protocol-relative ("//evil", "/\evil"),
|
|
57
59
|
# absolute URLs, and blanks collapse to nil so callers fall back to a safe
|
|
58
|
-
# default redirect.
|
|
60
|
+
# default redirect.
|
|
59
61
|
def sanitize_path(path)
|
|
60
62
|
p = path.to_s
|
|
61
|
-
|
|
63
|
+
Studio::LocalPath.local?(p) ? p : nil
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Studio
|
|
4
|
+
# The one rule for "is this a path on THIS site?", used wherever the engine
|
|
5
|
+
# writes a caller-supplied path into a redirect or an href: a sign-in's
|
|
6
|
+
# return_to, a link's target, the booking page, the link-preview fallback image.
|
|
7
|
+
#
|
|
8
|
+
# A local path begins with exactly one "/" and carries no control character
|
|
9
|
+
# and no backslash. Each clause closes a way a browser leaves the site:
|
|
10
|
+
# "https://x", "javascript:x" - no leading "/": a scheme or a relative path
|
|
11
|
+
# "//x" - protocol-relative: another host
|
|
12
|
+
# "/\x", "/\/x" - browsers (the WHATWG URL parser) read "\" as
|
|
13
|
+
# "/", so these are "//x" in disguise
|
|
14
|
+
# "/\tx", "/\nx" - the URL parser strips tab and newline, so a
|
|
15
|
+
# control character can hide a second "/"
|
|
16
|
+
# Pure Ruby, so it loads and unit-tests without Rails.
|
|
17
|
+
module LocalPath
|
|
18
|
+
# A control character (C0 or DEL) or a backslash anywhere in the path.
|
|
19
|
+
UNSAFE_CHARACTER = /[\x00-\x1f\x7f\\]/
|
|
20
|
+
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
def local?(path)
|
|
24
|
+
string = path.to_s
|
|
25
|
+
string.start_with?("/") && !string.start_with?("//") && !string.match?(UNSAFE_CHARACTER)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/studio/version.rb
CHANGED
data/lib/studio.rb
CHANGED
|
@@ -12,6 +12,7 @@ require "active_support/core_ext/module/attribute_accessors"
|
|
|
12
12
|
require "active_support/core_ext/numeric/time"
|
|
13
13
|
require "active_support/core_ext/integer/time"
|
|
14
14
|
require "studio/version"
|
|
15
|
+
require "studio/local_path"
|
|
15
16
|
require "studio/log_rotation"
|
|
16
17
|
require "studio/ip_locations"
|
|
17
18
|
require "studio/geo"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.91.
|
|
4
|
+
version: 0.91.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
@@ -614,6 +614,7 @@ files:
|
|
|
614
614
|
- lib/studio/link_preview.rb
|
|
615
615
|
- lib/studio/link_resolution.rb
|
|
616
616
|
- lib/studio/link_token.rb
|
|
617
|
+
- lib/studio/local_path.rb
|
|
617
618
|
- lib/studio/log_rotation.rb
|
|
618
619
|
- lib/studio/mail_transport.rb
|
|
619
620
|
- lib/studio/name_parts.rb
|