From 173ecf7d2ec37ae530ee641b81a0799b71fc9f90 Mon Sep 17 00:00:00 2001
From: Samuel Williams <samuel.williams@oriontransfer.co.nz>
Date: Sat, 8 Mar 2025 11:13:39 +1300
Subject: Use a fully resolved file path when confirming if a file can be
 served by `Rack::Static`.

---
 lib/rack/static.rb  | 3 ++-
 test/spec_static.rb | 6 ++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/lib/rack/static.rb b/lib/rack/static.rb
index 9a0017db..3c95b1c1 100644
--- a/lib/rack/static.rb
+++ b/lib/rack/static.rb
@@ -121,8 +121,9 @@ module Rack
 
     def call(env)
       path = env[PATH_INFO]
+      actual_path = Utils.clean_path_info(Utils.unescape_path(path))
 
-      if can_serve(path)
+      if can_serve(actual_path)
         if overwrite_file_path(path)
           env[PATH_INFO] = (add_index_root?(path) ? path + @index : @urls[path])
         elsif @gzip && env['HTTP_ACCEPT_ENCODING'] && /\bgzip\b/.match?(env['HTTP_ACCEPT_ENCODING'])
diff --git a/test/spec_static.rb b/test/spec_static.rb
index d33e8edc..7df55d4c 100644
--- a/test/spec_static.rb
+++ b/test/spec_static.rb
@@ -43,6 +43,12 @@ describe Rack::Static do
     res.body.must_match(/ruby/)
   end
 
+  it "does not serve files outside :urls" do
+    res = @request.get("/cgi/../#{File.basename(__FILE__)}")
+    res.must_be :ok?
+    res.body.must_equal "Hello World"
+  end
+
   it "404s if url root is known but it can't find the file" do
     res = @request.get("/cgi/foo")
     res.must_be :not_found?
-- 
2.30.2

