From 175e7d206b8ff2bce4d98d7ba429adf73c674bfb Mon Sep 17 00:00:00 2001
From: Jeremy Evans <code@jeremyevans.net>
Date: Mon, 16 Feb 2026 11:58:06 +0900
Subject: [PATCH] XSS injection via malicious filename in `Rack::Directory`.

Without this, if the file started with a URL scheme, it would not
be treated as a relative link.
---
 lib/rack/directory.rb  | 2 +-
 test/spec_directory.rb | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

--- a/lib/rack/directory.rb
+++ b/lib/rack/directory.rb
@@ -14,7 +14,7 @@
   # If +app+ is not specified, a Rack::Files of the same +root+ will be used.
 
   class Directory
-    DIR_FILE = "<tr><td class='name'><a href='%s'>%s</a></td><td class='size'>%s</td><td class='type'>%s</td><td class='mtime'>%s</td></tr>"
+    DIR_FILE = "<tr><td class='name'><a href='./%s'>%s</a></td><td class='size'>%s</td><td class='type'>%s</td><td class='mtime'>%s</td></tr>"
     DIR_PAGE = <<-PAGE
 <html><head>
   <title>%s</title>
--- a/test/spec_directory.rb
+++ b/test/spec_directory.rb
@@ -35,6 +35,15 @@
     end
   end
 
+  it "serve root directory index" do
+    res = Rack::MockRequest.new(Rack::Lint.new(app)).
+      get("/")
+
+    res.must_be :ok?
+    assert_includes(res.body, '<html><head>')
+    assert_includes(res.body, "href='./cgi")
+  end
+
   it "serve directory indices" do
     res = Rack::MockRequest.new(Rack::Lint.new(app)).
       get("/cgi/")
