File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. For info on
77### Security
88
99- [ CVE-2026 -25500] ( https://github.com/advisories/GHSA-whrj-4476-wvmp ) XSS injection via malicious filename in ` Rack::Directory ` .
10+ - [ CVE-2026 -22860] ( https://github.com/advisories/GHSA-mxw3-3hh2-x2mh ) Directory traversal via root prefix bypass in ` Rack::Directory ` .
1011
1112### Fixed
1213
Original file line number Diff line number Diff line change @@ -82,6 +82,7 @@ def DIR_FILE_escape(htmls)
8282 # Set the root directory and application for serving files.
8383 def initialize ( root , app = nil )
8484 @root = ::File . expand_path ( root )
85+ @root_with_separator = @root . end_with? ( ::File ::SEPARATOR ) ? @root : "#{ @root } #{ ::File ::SEPARATOR } "
8586 @app = app || Files . new ( @root )
8687 @head = Head . new ( method ( :get ) )
8788 end
@@ -118,7 +119,9 @@ def check_bad_request(path_info)
118119 # Rack response to use for requests with paths outside the root, or nil if path is inside the root.
119120 def check_forbidden ( path_info )
120121 return unless path_info . include? ".."
121- return if ::File . expand_path ( ::File . join ( @root , path_info ) ) . start_with? ( @root )
122+
123+ expanded_path = ::File . expand_path ( ::File . join ( @root , path_info ) )
124+ return if expanded_path == @root || expanded_path . start_with? ( @root_with_separator )
122125
123126 body = "Forbidden\n "
124127 [ 403 , { CONTENT_TYPE => "text/plain" ,
Original file line number Diff line number Diff line change @@ -149,6 +149,21 @@ def setup
149149 res . must_be :forbidden?
150150 end
151151
152+ it "not allow directory traversal via root prefix bypass" do
153+ Dir . mktmpdir do |dir |
154+ root = File . join ( dir , "root" )
155+ outside = "#{ root } _test"
156+ FileUtils . mkdir_p ( root )
157+ FileUtils . mkdir_p ( outside )
158+ FileUtils . touch ( File . join ( outside , "test.txt" ) )
159+
160+ app = Rack ::Directory . new ( root )
161+ res = Rack ::MockRequest . new ( app ) . get ( "/../#{ File . basename ( outside ) } /" )
162+
163+ res . must_be :forbidden?
164+ end
165+ end
166+
152167 it "not allow dir globs" do
153168 Dir . mktmpdir do |dir |
154169 weirds = "uploads/.?/.?"
You can’t perform that action at this time.
0 commit comments