8000 Don't allow session to be recreated accidentally. · rack/rack-session@c58ad79 · GitHub
[go: up one dir, main page]

Skip to content

Commit c58ad79

Browse files
committed
Don't allow session to be recreated accidentally.
1 parent 8a02143 commit c58ad79

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

lib/rack/session/pool.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ def find_session(req, sid)
5353

5454
def write_session(req, session_id, new_session, options)
5555
@mutex.synchronize do
56+
return false unless get_session_with_fallback(session_id)
5657
@pool.store session_id.private_id, new_session
5758
session_id
5859
end
@@ -62,7 +63,12 @@ def delete_session(req, session_id, options)
6263
@mutex.synchronize do
6364
@pool.delete(session_id.public_id)
6465
@pool.delete(session_id.private_id)
65-
generate_sid(use_mutex: false) unless options[:drop]
66+
67+
unless options[:drop]
68+
sid = generate_sid(use_mutex: false)
69+
@pool.store(sid.private_id, {})
70+
sid
71+
end
6672
end
6773
end
6874

releases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- Prevent `Rack::Session::Pool` from recreating deleted sessions [CVE-2025-46336](https://github.com/rack/rack-session/security/advisories/GHSA-9j94-67jr-4cqj).
6+
37
## v2.1.0
48

59
- Improved compatibility with Ruby 3.3+ and Rack 3+.

test/spec_session_pool.rb

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,4 +288,52 @@
288288
res = Rack::MockRequest.new(app).get("/")
289289
res["Set-Cookie"].must_be_nil
290290
end
291+
292+
user_id_session = Rack::Lint.new(lambda do |env|
293+
session = env["rack.session"]
294+
295+
case env["PATH_INFO"]
296+
when "/login"
297+
session[:user_id] = 1
298+
when "/logout"
299+
if session[:user_id].nil?
300+
raise "User not logged in"
301+
end
302+
303+
session.delete(:user_id)
304+
session.options[:renew] = true
305+
when "/slow"
306+
Fiber.yield
307+
end
308+
309+
Rack::Response.new(session.inspect).to_a
310+
end)
311+
312+
it "doesn't allow session id to be reused" do
313+
app = Rack::Session::Pool.new(user_id_session)
314+
315+
login_response = Rack::MockRequest.new(app).get("/login")
316+
login_cookie = login_response["Set-Cookie"]
317+
318+
slow_request = Fiber.new do
319+
Rack::MockRequest.new(app).get("/slow", "HTTP_COOKIE" => login_cookie)
320+
end
321+
slow_request.resume
322+
323+
# Check that the session is valid:
324+
response = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => login_cookie)
325+
response.body.must_equal({"user_id" => 1}.to_s)
326+
327+
logout_response = Rack::MockRequest.new(app).get("/logout", "HTTP_COOKIE" => login_cookie)
328+
logout_cookie = logout_response["Set-Cookie"]
329+
330+
# Check that the session id is different after logout:
331+
login_cookie[session_match].wont_equal logout_cookie[session_match]
332+
333+
slow_response = slow_request.resume
334+
335+
# Check that the cookie can't be reused:
336+
response = Rack::MockRequest.new(app).get("/", "HTTP_COOKIE" => login_cookie)
337+
response.body.must_equal "{}"
338+
end
291339
end

0 commit comments

Comments
 (0)
0