Skip to content

Commit eb6263f

Browse files
authored
Merge pull request #28 from drgrice1/file-traversal-protect
Protect static file routes from directory traversal attacks.
2 parents 31abf57 + c07716b commit eb6263f

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed
Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,49 @@
11
package Renderer::Controller::StaticFiles;
22
use Mojo::Base 'Mojolicious::Controller', -signatures;
33

4-
use Mojo::File qw(path);
4+
use Mojo::File qw(path);
5+
use File::Spec::Functions qw(canonpath);
56

6-
sub reply_with_file_if_readable ($c, $file) {
7-
if (-r $file) {
8-
return $c->reply->file($file);
7+
sub path_is_subdir ($path, $dir) {
8+
return 0 unless $path =~ /^\//;
9+
10+
$path = canonpath($path);
11+
return 0 if $path =~ m#(^\.\.$|^\.\./|/\.\./|/\.\.$)#;
12+
13+
$dir = canonpath($dir);
14+
return 0 unless $path =~ m|^$dir|;
15+
16+
return 1;
17+
}
18+
19+
sub reply_with_file_if_readable ($c, $directory, $file) {
20+
my $filePath = $directory->child($file);
21+
if (-r $filePath && path_is_subdir($filePath, $directory)) {
22+
return $c->reply->file($filePath);
923
} else {
1024
return $c->render(data => 'File not found', status => 404);
1125
}
1226
}
1327

1428
# Route requests for pg_files/CAPA_Graphics to render root Contrib/CAPA/CAPA_Graphics
1529
sub CAPA_graphics_file ($c) {
16-
return $c->reply_with_file_if_readable($c->app->home->child('Contrib/CAPA/CAPA_Graphics', $c->stash('static')));
30+
return $c->reply_with_file_if_readable($c->app->home->child('Contrib/CAPA/CAPA_Graphics'), $c->stash('static'));
1731
}
1832

1933
# Route requests for pg_files to the render root tmp. The
2034
# only requests should be for files in the temporary directory.
2135
# FIXME: Perhaps this directory should be configurable.
2236
sub temp_file ($c) {
23-
$c->reply_with_file_if_readable($c->app->home->child('tmp', $c->stash('static')));
37+
return $c->reply_with_file_if_readable($c->app->home->child('tmp'), $c->stash('static'));
2438
}
2539

2640
# Route request to pg_files to lib/PG/htdocs.
2741
sub pg_file ($c) {
28-
$c->reply_with_file_if_readable(path($ENV{PG_ROOT}, 'htdocs', $c->stash('static')));
42+
return $c->reply_with_file_if_readable(path($ENV{PG_ROOT}, 'htdocs'), $c->stash('static'));
2943
}
3044

3145
sub public_file ($c) {
32-
$c->reply_with_file_if_readable($c->app->home->child('public', $c->stash('static')));
46+
return $c->reply_with_file_if_readable($c->app->home->child('public'), $c->stash('static'));
3347
}
3448

3549
1;

0 commit comments

Comments
 (0)