Skip to content

Commit 89ad172

Browse files
committed
Prevent unsafe directory traversal
Paths are now verified with filename:safe_relative_path/1 to ensure they don't refer to files outside of the user-supplied static directory.
1 parent 02c6919 commit 89ad172

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/elli_static.erl

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
-include_lib("kernel/include/file.hrl").
1010

1111
-define(TABLE, elli_static_table).
12-
12+
-define(NOT_FOUND, {404, [], <<"Not Found">>}).
1313

1414
%% elli_handler callbacks
1515
-export([handle/2, handle_event/3]).
@@ -81,15 +81,31 @@ file_info(Filename) ->
8181
{error, Reason} -> throw(Reason)
8282
end.
8383

84-
8584
maybe_file(Req, Prefix, Dir) ->
85+
%% all paths start with a slash which `safe_relative_path/1' interprets as
86+
%% unsafe (absolute path), so temporarily remove it
87+
<<"/", RawPath/binary>> = elli_request:raw_path(Req),
88+
89+
%% santize the path ensuring the request doesn't access any parent
90+
%% directories ... and reattach the slash if deemed safe
91+
SafePath = case filename:safe_relative_path(RawPath) of
92+
unsafe ->
93+
throw(?NOT_FOUND);
94+
%% return type quirk work around
95+
[] ->
96+
<<"/">>;
97+
Sanitized ->
98+
<<"/", Sanitized/binary>>
99+
end,
100+
86101
Size = byte_size(Prefix),
87-
case elli_request:raw_path(Req) of
102+
case SafePath of
103+
%% ensure that `SafePath' starts with the correct prefix
88104
<<Prefix:Size/binary,"/",Path/binary>> ->
89105
Filename = filename:join(Dir, Path),
90106
case filelib:is_regular(Filename) of
91107
true -> {just, Filename};
92-
false -> throw({404, [], <<"Not Found">>})
108+
false -> throw(?NOT_FOUND)
93109
end;
94110
_ ->
95111
nothing

0 commit comments

Comments
 (0)