Security Advisories (1)
CVE-2026-7381 (2026-04-29)

Plack::Middleware::XSendfile versions through 1.0053 for Perl can allow client-controlled path rewriting. Plack::Middleware::XSendfile allows the variation setting (sendfile type) to be set by the client via the X-Sendfile-Type header, if it is not considered in the middleware constructor or the Plack environment. A malicious client can set the X-Sendfile-Type header to "X-Accel-Redirect" to services running behind nginx reverse proxies, and then set the X-Accel-Mapping to map the path to an arbitrary file on the server. Since 1.0053, Plack::Middleware::XSendfile is deprecated and will be removed from future releases of Plack. This is similar to CVE-2025-61780 for Rack::Sendfile, although Plack::Middleware::XSendfile has some mitigations that disallow regular expressions to be used in the mapping, and only apply the mapping for the "X-Accel-Redirect" type.

NAME

Plack::Middleware::XSendfile - Sets X-Sendfile (or a like) header for frontends

SYNOPSIS

enable "Plack::Middleware::XSendfile";

DEPRECATION NOTICE

This middleware is deprecated and will be removed in a future release, due to poor security design caused by the way configuration is passed via HTTP request headers. See "SECURITY".

The simplest replacement is to set the appropriate header directly in your application when serving a file. For example, in a Mojolicious controller:

sub download {
    my $c = shift;
    $c->res->headers->header('X-Accel-Redirect' => '/path/to/document.pdf');
    $c->render(data => '', status => 200);
}

If you need to handle this at the middleware layer instead to make it more transparent, you can replicate the behavior inline using Plack::Builder:

use Plack::Builder;
use Plack::Util;
use Scalar::Util qw(blessed);

builder {
    enable sub {
        my $app = shift;
        sub {
            my $env = shift;
            my $res = $app->($env);
            Plack::Util::response_cb($res, sub {
                my $res = shift;
                my $body = $res->[2];
                if (blessed($body) && $body->can('path')) {
                    my $h = Plack::Util::headers($res->[1]);
                    $h->set('X-Sendfile' => $body->path);
                    $h->set('Content-Length', 0);
                    $res->[2] = [];
                }
            });
        };
    };
    $app;
};

DESCRIPTION

When the body is a blessed reference with a path method, then the return value of that method is used to set the X-Sendfile header.

The body is set to an empty list, and the Content-Length header is set to 0.

If the X-Sendfile header is already set, then the body and Content-Length will be untouched.

You should use IO::File::WithPath or Plack::Util's set_io_path to add path method to an IO object in the body.

See https://www.nginx.com/resources/wiki/start/topics/examples/xsendfile for frontend configuration examples.

Plack::Middleware::XSendfile does not set the Content-Type header.

FRONTEND CONFIGURATION

Nginx

Nginx supports X-Accel-Redirect. Configure an internal location and pass the X-Accel-Mapping header to the backend so the middleware can rewrite filesystem paths into internal URLs:

location ~ /files/(.*) {
    internal;
    alias /var/www/$1;
}

location / {
    proxy_pass         http://127.0.0.1:5000/;
    proxy_set_header   X-Sendfile-Type     X-Accel-Redirect;
    proxy_set_header   X-Accel-Mapping     /var/www/=/files/;
}

X-Accel-Mapping tells the middleware which filesystem prefix to replace and what internal URL prefix to use instead.

Apache

Enable mod_xsendfile (https://tn123.org/mod_xsendfile/) and set the request header so the middleware activates:

RequestHeader Set X-Sendfile-Type X-Sendfile
XSendFile on

lighttpd

proxy-core.allow-x-sendfile = "enable"
proxy-core.rewrite-request = (
    "X-Sendfile-Type" => (".*" => "X-Sendfile")
)

SECURITY

This middleware reads X-Sendfile-Type and X-Accel-Mapping from incoming request headers to determine how to serve files. It is therefore critical that these headers are set by the frontend proxy and cannot be supplied by untrusted clients; otherwise a client could influence which files the frontend serves.

The Plack backend must not be directly reachable by untrusted clients.

For each frontend, make sure both headers are explicitly set in the proxy configuration. proxy_set_header (nginx), RequestHeader Set (Apache), and proxy-core.rewrite-request (lighttpd) all overwrite any client-supplied values, which is why the examples above use those directives.

CONFIGURATION

variation

The header tag to use. If unset, the environment key plack.xsendfile.type will be used, then the HTTP_X_SENDFILE_TYPE header.

Supported values are:

  • X-Accel-Redirect

  • X-Lighttpd-Send-File

  • X-Sendfile.

An unsupported value will log an error.

AUTHOR

Tatsuhiko Miyagawa