CVE-2026-93712 Overview
CVE-2026-93712 is a path traversal vulnerability in the Perl web framework Dancer2, affecting versions from 2.1.0 before 2.2.0. The Dancer2::Handler::File route handler joins the request path onto public_dir without collapsing relative path segments. An unauthenticated attacker can request paths containing ../ sequences, or their percent-encoded equivalents, to read files outside the intended web root. Any file readable by the worker process is exposed, including the application's config.yml located above public_dir. The vulnerability is tracked under CWE-22 (Improper Limitation of a Pathname to a Restricted Directory).
Critical Impact
Unauthenticated remote attackers can read arbitrary files accessible to the Perl worker process, including application configuration files containing secrets.
Affected Products
- Dancer2 for Perl, versions 2.1.0 through 2.1.x
- Applications that register File in route_handlers and set static_handler to 0
- Fixed in Dancer2 version 2.2.0
Discovery Timeline
- 2026-09-22 - CVE-2026-93712 published to the National Vulnerability Database
- 2026-09-22 - Vulnerability disclosed on the OpenWall oss-security mailing list
- 2026-09-22 - Last updated in NVD database
Technical Details for CVE-2026-93712
Vulnerability Analysis
The flaw resides in Dancer2::Handler::File, which serves static files from a configured public_dir. When the handler receives a request, it joins the request PATH_INFO onto public_dir using Path::Tiny and then verifies only that the resulting path is a readable regular file. Because Path::Tiny does not collapse ../ segments, a joined path such as public_dir/../outside.txt still resolves to a file outside the intended directory. The -f check passes and the file is streamed to the client.
Percent-encoded variants of the dot characters bypass the same check because URL decoding occurs before the join. Any file readable by the Perl worker process, including config.yml above public_dir, is served to unauthenticated requests.
Root Cause
The handler relied on a naïve file-existence check rather than a canonicalized containment check. Dancer2's default static_handler normally refuses requests containing dot segments before routing, but naming File in route_handlers with static_handler set to 0 disables that protection. The File handler itself never called realpath and never verified that the resolved path was subsumed by public_dir.
Attack Vector
An unauthenticated attacker sends an HTTP request with a crafted path such as /../config.yml or its percent-encoded form /%2E%2E/config.yml. The request traverses out of public_dir and returns the target file contents. No authentication, user interaction, or elevated privileges are required.
# Security patch in lib/Dancer2/Handler/File.pm
my $file_path = Path::Tiny::path( $self->_public_dir_path, $path );
my $file_path_str = $file_path->stringify;
if ( !-f $file_path_str ) {
$app->response->has_passed(1);
return;
}
# Path::Tiny does not collapse '../' segments, so the joined path
# above may still point outside public_dir even though it is a
# readable file (F4). Resolve it and refuse anything that escapes,
# the same containment check send_file uses at
# Dancer2/Core/App.pm:1180-1182.
$file_path = $file_path->realpath;
$file_path_str = $file_path->stringify;
if ( !$self->_public_dir_path->realpath->subsumes($file_path) ) {
return $self->standard_response( $app, 403 );
}
if ( !-r $file_path_str ) {
return $self->standard_response( $app, 403 );
}
Source: Dancer2 patch commit 2446a09. The fix resolves the joined path with realpath and enforces subsumes containment against public_dir.
Detection Methods for CVE-2026-93712
Indicators of Compromise
- HTTP access log entries containing ../, ..%2F, %2E%2E/, or %2E%2E%2F in the request path served by a Dancer2 application.
- HTTP 200 responses to requests that resolve outside the configured public_dir, especially for files such as config.yml, .env, or environments/*.yml.
- Repeated requests probing for common sensitive filenames from a single client IP.
Detection Strategies
- Inspect web server and reverse proxy logs for percent-encoded dot sequences targeting Dancer2 endpoints.
- Audit application configuration for any use of File in route_handlers combined with static_handler => 0.
- Deploy web application firewall rules that normalize URL encoding and block traversal patterns before they reach the Perl worker.
Monitoring Recommendations
- Alert on unauthenticated reads of configuration files, credential stores, or files outside the documented web root.
- Track outbound responses containing YAML or configuration markers such as password:, api_key:, or database DSN strings served over HTTP.
- Correlate scanner-like request patterns with subsequent authenticated activity from newly seen credentials.
How to Mitigate CVE-2026-93712
Immediate Actions Required
- Upgrade Dancer2 to version 2.2.0 or later from CPAN.
- Rotate any secrets, API keys, or database credentials stored in config.yml or environment files that may have been exposed.
- Review web server logs for prior traversal attempts and treat successful reads of sensitive files as a confirmed incident.
Patch Information
The fix is included in Dancer2 2.2.0, published on MetaCPAN. See the MetaCPAN Dancer2 2.2.0 change log, the GitHub Security Advisory GHSA-6xw8-v24c-m783, and the upstream patch commit. The patch calls realpath on the joined path and enforces a subsumes containment check against public_dir.
Workarounds
- Remove File from route_handlers and rely on the default static_handler, which rejects dot segments before routing.
- If a custom static handler is required, restore static_handler => 1 so Dancer2's built-in traversal filter runs first.
- Front the application with a reverse proxy such as nginx or Apache that normalizes and rejects ../ sequences in request paths.
# Upgrade Dancer2 to the patched release
cpanm Dancer2@2.2.0
# Verify the installed version
perl -MDancer2 -e 'print "$Dancer2::VERSION\n"'
# Example config.yml hardening: keep the default static handler enabled
# static_handler: 1
# route_handlers:
# - AutoPage: 1
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

