Apr 2, 2026·6 min read·4 visits
A partial string matching flaw in Rack::Static allows unauthenticated attackers to retrieve unintended files sharing a text prefix with static directories. Updating to patched versions resolves the issue.
Rack, a foundational Ruby web server interface, suffers from an information disclosure vulnerability in its Rack::Static middleware prior to versions 2.2.23, 3.1.21, and 3.2.6. The vulnerability arises from an insecure partial string comparison logic flaw in the URL routing mechanism, allowing attackers to access sensitive files that inadvertently share a common prefix with configured static asset directories.
Rack serves as a foundational modular interface for Ruby web applications, bridging various web frameworks and application servers. The Rack::Static middleware provides a convenient mechanism for serving static files, such as stylesheets, JavaScript, and images, directly from a specified root directory on the filesystem. Developers configure this middleware by defining an array of URL prefixes that trigger static file resolution.
CVE-2026-34785 represents an information disclosure vulnerability within this routing mechanism, categorized under CWE-187 (Partial String Comparison) and CWE-200 (Exposure of Sensitive Information). The flaw exists in Rack versions prior to 2.2.23, 3.1.21, and 3.2.6. It allows unauthenticated remote attackers to access unintended files located within the configured static root directory.
The vulnerability manifests when the middleware attempts to match incoming request paths against the configured static URL prefixes. Because the implementation relies on a basic string prefix check without enforcing directory boundaries, attackers can request files that merely share a text prefix with a legitimate static directory. This results in the server returning files that were never intended for public exposure.
The core of the vulnerability resides in the route_file method of the Rack::Static class. This method evaluates whether an incoming HTTP request path should be processed by the static file handler. The evaluation logic relies on the String#index method to determine if the request path begins with any of the configured URL prefixes.
The vulnerable implementation uses the condition path.index(url) == 0, which is functionally equivalent to the start_with? method in Ruby. This approach verifies only that the sequence of characters in the request path begins with the exact character sequence defined in the configuration. It does not verify that the prefix represents a complete path segment terminating in a forward slash (/).
Consequently, if a developer configures Rack::Static to serve files from the /css URL prefix, the routing logic will intercept any request path beginning with those four characters. A request for /css-config.env will yield an index of 0 when evaluated against the /css prefix. The middleware incorrectly determines that it should handle the request and proceeds to locate and serve the requested file from the static root directory.
Analyzing the source code before and after commit 7a8f32696609b88e2c4c1f09d473a1d2d837ed4b highlights the precise mechanism of the vulnerability and its resolution. The vulnerable route_file method contained a single line of logic for prefix matching:
def route_file(path)
@urls.kind_of?(Array) && @urls.any? { |url| path.index(url) == 0 }
endThe patch addresses this logic flaw by introducing a strict boundary check during the initialization phase of the middleware. The urls configuration array is transformed to store a tuple for each prefix, consisting of the exact original prefix and a version explicitly terminated with a forward slash:
if @urls.kind_of?(Array)
@urls = @urls.map { |url| [url, url.end_with?('/') ? url : "#{url}/".freeze].freeze }.freeze
endThe route_file method was subsequently rewritten to utilize these tuples. The new logic evaluates whether the request path exactly matches the configured prefix or if it starts with the slash-terminated version:
def route_file(path)
@urls.kind_of?(Array) && @urls.any? { |url, url_slash| path == url || path.start_with?(url_slash) }
endThis structural change ensures that a request for /css-backup.sql no longer matches the /css configuration. The path does not exactly equal /css, nor does it start with the boundary-enforced string /css/. The middleware will decline to handle the request, passing it down the Rack stack or returning an appropriate HTTP error.
Exploiting this vulnerability requires specific environmental prerequisites. The target application must utilize the Rack::Static middleware and explicitly define an array of URL prefixes via the :urls configuration option. Furthermore, a sensitive file or directory must reside within the designated static :root directory and possess a name that shares a literal string prefix with one of the configured URLs.
An attacker initiates the exploit by mapping the application's expected static asset paths. By observing the HTML source or network traffic, the attacker identifies prefixes such as /assets, /css, or /js. The attacker then formulates HTTP GET requests targeting common sensitive file names appended directly to these prefixes, bypassing the directory separator.
# Proof of Concept targeting a database backup file
curl -v http://target-app.internal/css-backup.sqlThe following diagram illustrates the execution flow during an exploitation attempt:
Upon receiving the crafted request, the Rack application routes it to the Rack::Static middleware. The middleware validates the prefix, locates the corresponding file on the local filesystem within the static root, and returns its contents to the unauthenticated attacker.
The primary impact of CVE-2026-34785 is the unauthorized disclosure of sensitive information. The vulnerability permits an attacker to read the contents of files located within the configured static root directory. The severity of the disclosure depends entirely on the operational practices of the deployment environment and the types of files inadvertently placed alongside public assets.
This vulnerability does not facilitate arbitrary file reading or path traversal attacks against the underlying operating system. The Rack::Static middleware still enforces constraints that prevent access to files outside the defined :root directory. Attackers cannot read /etc/passwd or application source code located completely outside the static assets folder. The exposure is strictly limited to siblings of the intended static directories.
Commonly exposed data includes database backup files, unminified source code, environment variable configuration files, and local deployment artifacts. The CVSS v3.1 vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N accurately reflects a high severity rating for confidentiality impact, with low attack complexity and no requirement for user interaction or prior authentication.
The primary remediation for CVE-2026-34785 requires updating the rack gem to a patched version. Maintainers have released fixes in Rack versions 2.2.23, 3.1.21, and 3.2.6. Development teams should update their dependency manifests and deploy the updated gem to all environments utilizing the Rack::Static middleware.
If immediate patching is technically prohibitive, administrators can implement a configuration-based workaround. Modifying the Rack::Static initialization to include a trailing slash in all configured URL prefixes prevents the partial string match. Changing :urls => ["/css"] to :urls => ["/css/"] manually enforces the directory boundary that the patched code handles automatically.
Organizations should also enforce strict segregation of public assets and sensitive files. Deployment pipelines must ensure that database backups, environment configuration files, and uncompiled application source code are never placed within directories designated for public static file serving. Implementing automated directory structure linting can prevent inadvertent co-location of these assets.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Rack Rack Project | < 2.2.23 | 2.2.23 |
Rack Rack Project | >= 3.0.0.beta1, < 3.1.21 | 3.1.21 |
Rack Rack Project | >= 3.2.0, < 3.2.6 | 3.2.6 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-187 (Partial String Comparison) |
| Attack Vector | Network |
| CVSS Score | 7.5 (High) |
| Impact | Confidentiality (High) |
| Exploit Status | Proof of Concept |
| CISA KEV | No |
The application performs a string comparison that does not verify that a match is exact or adheres to expected boundaries, leading to unauthorized operations.